简体   繁体   中英

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

I'm having a bit of a dilemma getting my head around JS' prototypal inheritance. What I'm trying to do is:

  1. Define an object called mod

     var mod = function() { function sayGoodbye() { alert("Goodbye!"); } function saySomethingElse(message) { alert(message); } return { sayGoodbye: sayGoodbye, saySomethingElse: saySomethingElse }; }; 
  2. Define a prototype object called proto

     var proto = { sayHello: function() { alert("Hello!"); } }; 
  3. Set the prototype of mod to proto

     mod.prototype = proto; 
  4. Call a function that constructs a new instance of mod with the proto prototype

     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); 

The construct function creates a new instance of mod correctly using the apply function but it's prototype is not proto . What am I missing that prevents mod from being constructed with proto as it's prototype?

Here is a fiddle with the above code.

Thanks heaps!!

The reason the .prototype assignment isn't working for you is because setting the prototype chain like this only works when you use the new operator on a constructor function.

You created a factory function that returns a newly created object. Get rid of the return in mod and use this to attach your method and use new operator when creating instances of mod will make the .prototype assignment work.

This might be confusing so I updated your fiddle: https://jsfiddle.net/6fdo649y/1/

There are several ways to achieve what you are trying to do, but this example explains why you don't see .prototype work.

//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);

edited: added in passing the args through with apply.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM