2013-07-26 147 views
0

我想达到的一个构造函数扩展方法,并用它来初始化实例,如:混淆有关原型继承在JavaScript

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是对的。

那么,我的代码有什么问题?为什么原型消失?我该怎么做对不对?

+0

呦使用[的Object.create您自担风险使用它](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)now – aaronman

+0

@aaronman:我试着自己做一个 – hh54188

回答

1

没有什么错与您的代码。它做它应该做的事情。 prototype属性只存在于函数上。

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

说得简单来说:在JavaScript

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 

对象从通过委托其他对象继承。这意味着说,我们尝试将对象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

这简直就是你的原型继承。

您代码记录的原因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
0

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

console.log(tmp.__proto__); 

或者:

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

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

[编辑]

你可以看到在这个question的身影。它显示Foo.prototype.constructor指向Foo本身。但是,由于您使用行View.prototype = {...}覆盖构造函数的原型,因此View.prototype.constructor将是function 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 
};