2011-05-24 51 views
4

我有一個簡單的類在javascript:的Javascript原型和__proto__和getPrototypeOf問題

function foo() { 
    this.bar = "bar"; 
} 

var test = new foo; 

console.log(foo.prototype,foo.__proto__) 
/*output: foo { 
       constructor: function foo() { 
       __proto__: Object 
       } 
      , 
      function Empty() {} 
*/ 
console.log(test,test.prototype,test.__proto__,test.__proto__.__proto__) 
/*output: foo { 
       bar: "bar" 
       __proto__: foo 
      } 
      , 
      undefined 
      , 
      foo { 
       constructor: function foo() { 
       __proto__: Object 
      } 
      , 
      Object { 
       ... 
      } 
     */ 

什麼我不明白:

在第一次登錄的foo.prototype__proto__屬性,它是一個Object 在第二個日誌test.__proto__具有__proto__屬性,該屬性是Object

何時使用__proto__prototype,有什麼區別?


UPDATE:

John Resig's blog}這種節有什麼啥子我不明白:

如果我使用var asd = "asd";Object.getPrototypeOf(asd)它拋出一個TypeError但如果我用var dsa = new String("dsa");Object.getPrototypeOf(dsa)返回String
asd.constructor.prototype == dsa.constructor.prototypetrue

爲什麼Object.getPrototypeOf(asd)拋出錯誤?這是一個字符串,不是嗎?

回答

6

始終使用prototypeObject.getPrototypeOf

__proto__是非標準的,已被Mozilla棄用。

John Resig對此有不錯的blog entry


test.prototype未定義的原因是因爲您創建了一個沒有構造函數原型的新對象。以下是使用Object.getPrototypeOf時的示例。

js> function foo(){} 
js> typeof foo.prototype; 
object 
js> var f = new foo(); 
js> typeof f.prototype; 
undefined 
js> typeof Object.isPrototypeOf(f); 
object 
js> typeof f.constructor.prototype; 
object 
js> foo.prototype === Object.getPrototypeOf(f); 
true 
js> foo.prototype === f.constructor.prototype; 
true 

正如你所知道的,繼承在JavaScript是棘手的。讓我們看一個例子:

js> typeof "asdf"; 
string 
js> typeof String("asdf"); 
string 

字符串文字是字符串類型。作爲函數調用String()時也是如此。現在,由於new運算符的行爲,會創建一個新對象,其原型爲String()作爲其父項。

js> var s = new String("asdf"); 
js> typeof s; 
object 

因爲JS喜歡強迫的事情,你可以在字符串字面量的幾種方法:

js> s 
asdf 
js> s.valueOf(); 
asdf 
js> typeof s 
object 
js> typeof s.valueOf(); 
string 

Prototypal Inheritance in JavaScript由克羅克福德瞭解JS繼承的時候幫助了我很多。

從Mozilla的Strings頁:

String對象可通過 調用構造新的String創建()。 String對象用下面描述的 方法打包JavaScript的 字符串基本數據類型。函數String()的全局函數 也可以被稱爲 而不需要在前面創建一個 原始字符串。 中的字符串文字JavaScript是原始字符串。

+0

但正如你看到第二個日誌,'test.prototype == undefined' – 2011-05-24 15:49:56

+0

我修改了我的答案與示例repl輸出。 – Jeremy 2011-05-24 16:13:30

+0

感謝這個非常好的例子。現在我明白了一切。 – 2011-05-24 21:08:19

5

__proto__是一個對象與它的原型之間的中介對象。使用它的最大好處是可以完全更改對象的原型鏈,而無需修改實例或原型。

實施例:

function F() {} 
F.prototype.a = 1; 
var f = new F(); 
f.__proto__ = { b : 2 }; 
"a" in f => false; 
"b" in f => true; 

但作爲傑里米說,__proto__已棄用。唯一的用例是如果你想添加一組屬性到一個對象,改變它的原型而不必遍歷每一個。沒什麼大不了的。