在javascript中混淆原型继承

时间:2013-07-26 01:50:51

标签: javascript inheritance prototype

我想在构造函数上实现一个extend方法,并用它来初始化一个实例,如:

var view_instance = View.extend()

所以我尝试了这个:

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

在上面的extend方法中,我通过new this()初始化了一个实例,但我无法记录其原型,并检查this是否正确。

我的代码出了什么问题?为什么原型会消失?我该怎么办呢?

3 个答案:

答案 0 :(得分:1)

tmp.constructor.prototype就是你想要的。 o.__proto__只是o.constructor.prototypeit's non-standard的快捷方式。

[编辑]

您可以在此question中看到该图。它表明Foo.prototype.constructor指向Foo本身。但是,由于您使用行View.prototype = {...}覆盖构造函数的原型,View.prototype.constructorfunction Object() { [native code] }而不是View本身。 因此,更准确的方法是直接为原始原型分配属性,或者手动设置constructor属性来覆盖它:

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

答案 1 :(得分:1)

您的代码没有任何问题。它做了它应该做的事情。 prototype属性仅存在于函数中。

当您使用new关键字进行函数调用之前,JavaScript会创建一个继承自构造函数prototype的对象。

简单来说:

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

JavaScript中的对象通过委托从其他对象继承。这意味着我们尝试访问上面看到的对象o上的属性:

  1. JavaScript会首先尝试在o本身找到该属性。
  2. 如果在o找不到该属性,则会尝试在Object.getPrototypeOf(o)上找到该属性(或者更简洁地o.__proto__)。 o的原型是F.prototype
  3. 如果在F.prototype找不到该属性,则会尝试在F.prototype.__proto__ Object.prototype上找到该属性。
  4. 如果在Object.prototype找不到该属性,那么它会放弃,因为Object.prototype.__proto__null
  5. 简而言之,这就是原型继承。

    您的代码为undefined记录tmp.prototype的原因是tmp没有任何名为prototype的属性。只有函数具有prototype属性。试试这个:

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

    以上与以下相同。但是,不推荐使用对象的__proto__属性。使用它需要您自担风险:

    console.log(tmp.__proto__);
    

    如果您想了解有关继承的更多信息,请阅读以下文章:

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

答案 2 :(得分:0)

prototype属性属于构造函数。实例具有指向同一对象的非标准__proto__属性。所以:

console.log(tmp.__proto__);

或者:

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