hh54188
hh54188

Reputation: 15626

Confuse about prototype inheritance in javascript

I want to achieve a extend method on a constructor function, and use it to initialize an instance, like:

var view_instance = View.extend()

so I tried this:

define(function (require, exports, module) {

    function View(size, color) {
        this.size = size;
        this.color = color;
    };

    View.prototype = {
        show: function () {
            console.log("This is view show");
        }
    }

    View.extend = function (props) {
        var tmp = new this("12", "red");
        console.log(this);
            console.log(tmp instanceof this) //true
        console.log(tmp.prototype); //undefined!
        return tmp
    }

    return View;
})

in the above extend method, I initialize an instance through new this(), but I can't log its prototype, and I check the this is right.

So what's wrong with my code? Why the prototype disappear? How can I do it right?

Upvotes: -1

Views: 98

Answers (3)

Trantor Liu
Trantor Liu

Reputation: 9126

tmp.constructor.prototype is what you want. o.__proto__ is just a shortcut for o.constructor.prototype and it's non-standard.

[EDIT]

You can see the figure in this question. It shows that Foo.prototype.constructor points to Foo itself. However, since you are overwriting the prototype of the constructor with the line View.prototype = {...}, View.prototype.constructor will be function Object() { [native code] } instead of View itself. So a more accurate way would be assigning properties to the original prototype directly or overwriting it with the constructor property set manually:

// Assign properties to the original prototype to prevent overwriting the `constructor` properties.
View.prototype.show = function() {};

// Or set the constructor manually.
View.prototype = {
  show: function() {},
  constructor: View
};

Upvotes: 1

Aadit M Shah
Aadit M Shah

Reputation: 74204

There's nothing wrong with your code. It does what it's supposed to do. The prototype property only exists on functions.

When you precede a function call with the new keyword JavaScript creates an object which inherits from the prototype of the constructor.

To put it in simple terms:

function F() {}                                        // we have a constructor
var o = new F;                                         // we create an instance
console.log(Object.getPrototypeOf(o) === F.prototype); // o inherits from
                                                       // F.prototype

Objects in JavaScript inherit from other objects via delegation. This means say we try to access a property on the object o which we saw above:

  1. JavaScript will first try to find the property on o itself.
  2. If it can't find the property on o then it will try to find it on Object.getPrototypeOf(o) (or to put it more succinctly o.__proto__). The prototype of o is F.prototype.
  3. If it can't find the property on F.prototype then it will try to find it on F.prototype.__proto__ which is Object.prototype.
  4. If it can't find the property on Object.prototype then it will give up because Object.prototype.__proto__ is null.

That is prototypal inheritance for you in a nutshell.

The reason your code logs undefined for tmp.prototype is because tmp doesn't have any property called prototype. Only functions have a prototype property. Try this instead:

console.log(Object.getPrototypeOf(tmp));

The above is the same as the following. However the __proto__ property of objects is deprecated. Use it at your own risk:

console.log(tmp.__proto__);

If you want to learn more about inheritance then read the following articles:

  1. Aadit M Shah | Why Prototypal Inheritance Matters
  2. JavaScript inheritance and the constructor property - Stack Overflow

Upvotes: 1

bfavaretto
bfavaretto

Reputation: 71918

The prototype property belongs to constructors. The instances have a non-standard __proto__ property pointing to the same object. So:

console.log(tmp.__proto__);

Or:

console.log(Object.getPrototypeOf(tmp));

Upvotes: 0

Related Questions