【问题标题】:Construct an object with a prototype using Function.apply()使用 Function.apply() 构造一个带有原型的对象
【发布时间】:2016-02-25 04:53:29
【问题描述】:

在了解 JS 的原型继承时,我有点进退两难。我想做的是:

  1. 定义一个名为mod的对象

    var mod = function() {
        function sayGoodbye() {
            alert("Goodbye!");
        }
    
        function saySomethingElse(message) {
            alert(message);
        }
    
        return {
            sayGoodbye: sayGoodbye,
            saySomethingElse: saySomethingElse
        };
    };
    
  2. 定义一个名为proto

    的原型对象
    var proto = {
        sayHello: function() {
            alert("Hello!");
        }
    };
    
  3. mod的原型设置为proto

    mod.prototype = proto;
    
  4. 使用 proto 原型调用构造 mod 新实例的函数

    function construct(constructor, args) {
    
        function constructorWrapper() {
            return constructor.apply(this, args)
        }
    
        constructorWrapper.prototype = constructor.prototype;
    
        return new constructorWrapper();
    }
    
    var foo = construct(mod, ["Other Message 1"]);
    var bar = construct(mod, ["Other Message 2"]);
    
    console.dir(foo);
    console.dir(bar);
    

construct 函数使用 apply 函数正确地创建了一个新的 mod 实例,但它的原型不是 proto >。我错过了什么阻止 mod 被构造为 proto 作为它的原型?

这是带有上述代码的fiddle

谢谢大家!!

【问题讨论】:

  • 您的mod 函数是一个返回对象的工厂。不应该,它应该是初始化this上的属性的构造函数(或方法)。
  • 我想知道你为什么不直接使用new mod("Other message 1")
  • @squint:我猜第 4 步应该设置原型链。如果constructorWrapperconstructor 没有返回对象,它甚至会返回。
  • @Bergi:哦,我明白了。他只是在搬运它。编辑:我错过了他实际上是在分配功能。不知何故,我将其视为 IIFE。我希望人们尽可能使用函数声明。
  • 太棒了@squint。感谢您的帮助!

标签: javascript inheritance constructor prototype instance


【解决方案1】:

.prototype 赋值对您不起作用的原因是,像这样设置原型链仅在您在构造函数上使用 new 运算符时才有效。

您创建了一个返回新创建对象的工厂函数。去掉 mod 中的 return 并使用 this 附加您的方法并在创建 mod 实例时使用 new 运算符将使 .prototype 分配工作。

这可能会令人困惑,所以我更新了你的小提琴: https://jsfiddle.net/6fdo649y/1/

有几种方法可以实现您想要做的事情,但这个示例解释了为什么您看不到 .prototype 工作。

//Constructor function using this
function Mod(arg1) {
    this.sayGoodbye = function sayGoodbye() {
        alert("Goodbye!");
    }

    this.saySomethingElse = function saySomethingElse(message) {
        alert(message);
    }

    this.arg1 = arg1;
};

var proto = {
    sayHello: function() {
        alert("Hello!");
    }
};

Mod.prototype = proto;

function construct(constructor, args) {

    function constructorWrapper() {
        constructor.apply(this, args)
    }

    constructorWrapper.prototype = constructor.prototype;

    return new constructorWrapper();
}

var foo = construct(Mod, ["Other Message 1"]);
var bar = construct(Mod, ["Other Message 2"]);

console.dir(foo === bar);
console.dir(foo);
console.dir(bar);

已编辑:在使用 apply 传递参数时添加。

【讨论】:

  • 请将更改后的代码添加到您的答案中,而不是(仅)添加到小提琴中。
猜你喜欢
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
  • 2019-11-05
  • 2016-09-05
  • 2011-05-13
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多