0

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!!

9
  • Your mod function is a factory that returns an object. It should not be, it should be a constructor (or method) that initialises properties on this. Commented Feb 25, 2016 at 4:58
  • I wonder why you don't just use new mod("Other message 1")? Commented Feb 25, 2016 at 4:59
  • @squint: I guess step 4 was supposed to set up the prototype chain. It even would have, if constructorWrapper or constructor would not have returned an object. Commented Feb 25, 2016 at 5:00
  • 1
    @Bergi: Oh, I see. He was just transporting it. EDIT: I missed that he was actually assigning the function. Somehow I saw it as an IIFE. I wish people would use function declarations when able. Commented Feb 25, 2016 at 5:02
  • 1
    That's great @squint. Thanks for your help! Commented Feb 25, 2016 at 5:45

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Please add the changed code to your answer, not (only) to the fiddle.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.