2013-07-26 116 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 
};