使用 Function.apply() 构造带有原型的对象

Construct an object with a prototype using Function.apply()

关于 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 的新实例16=]

    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[=60 创建了 mod 的新实例=] 函数,但它的原型不是 proto。我错过了什么阻止 mod 被构造成 proto 作为原型?

这里是fiddle上面的代码。

非常感谢!!

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

您创建了一个 returns 新创建对象的工厂函数。摆脱 mod 中的 return 并使用 this 附加您的方法并在创建 mod 实例时使用 new 运算符将使 .prototype 作业。

这可能令人困惑,所以我更新了您的 fiddle: 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);

已编辑:在通过应用传递参数时添加。