天天看點

javascript_原型與原型鍊

1.prototype

在JavaScript中,每個函數都有一個prototype屬性,這個屬性指向函數的原型對象。

<script type="text/javascript">
  //每一個函數都由一個prototype,預設指向一個object
  console.log(Date.prototype,typeof Date.prototype)
  function fun() {
    console.log("test")

  }

  console.log(fun.prototype,typeof fun.prototype)
  fun.prototype.test = function () {
    alert("1")

  }
  console.log(fun.prototype,typeof fun.prototype)
  //原型對象有一個屬性contructor,預設指向函數對象
  console.log(fun.prototype.constructor === fun)//fun

  console.log(Date.prototype.constructor === Date)
  //建立一個執行個體,
  var f1 = new fun()
  f1.test()
</script>
      
javascript_原型與原型鍊

上述例子中,函數的prototype指向了一個對象,而這個對象正是調用構造函數時建立的執行個體的原型,也就是person1和person2的原型。

原型的概念:每一個javascript對象(除null外)建立的時候,就會與之關聯另一個對象,這個對象就是我們所說的原型,每一個對象都會從原型中“繼承”屬性。

讓我們用一張圖表示構造函數和執行個體原型之間的關系:

javascript_原型與原型鍊

2.proto

<script type="text/javascript">
   //顯示屬性:prototype
   //隐式屬性:__proto__
   function fun() {


   }

   console.log(fun.prototype)

   var f1 = new fun()
   console.log(f1.__proto__ === fun.prototype)
 </script>
      
javascript_原型與原型鍊

圖的關系:

javascript_原型與原型鍊

補充說明:

絕大部分浏覽器都支援這個非标準的方法通路原型,然而它并不存在于 Person.prototype 中,實際上,它是來自于 Object.prototype ,與其說是一個屬性,不如說是一個 getter/setter,當使用 obj.proto 時,可以了解成傳回了 Object.getPrototypeOf(obj)。

3.constructor

每個原型都有一個constructor屬性,指向該關聯的構造函數。

javascript_原型與原型鍊
<script type="text/javascript">
  //每一個函數都由一個prototype,預設指向一個object
  console.log(Date.prototype,typeof Date.prototype)
  function fun() {
    console.log("test")

  }

  console.log(fun.prototype,typeof fun.prototype)
  fun.prototype.test = function () {
    alert("1")

  }
  console.log(fun.prototype,typeof fun.prototype)
  //原型對象有一個屬性contructor,預設指向函數對象
  console.log(fun.prototype.constructor === fun)//fun

  console.log(Date.prototype.constructor === Date)
  //建立一個執行個體,
  var f1 = new fun()
  f1.test()
</script>
      
javascript_原型與原型鍊

圖:

javascript_原型與原型鍊

4.執行個體與原型

當讀取執行個體的屬性時,如果找不到,就會查找與對象關聯的原型中的屬性,如果還查不到,就去找原型的原型,一直找到最頂層為止。

function Person() {

}

Person.prototype.name = 'Kevin';

var person = new Person();

person.name = 'Daisy';
console.log(person.name) // Daisy

delete person.name;
console.log(person.name) // Kevin
      

在這個例子中,我們給執行個體對象 person 添加了 name 屬性,當我們列印 person.name 的時候,結果自然為 Daisy。

但是當我們删除了 person 的 name 屬性時,讀取 person.name,從 person 對象中找不到 name 屬性就會從 person 的原型也就是 person.proto ,也就是 Person.prototype中查找,幸運的是我們找到了 name 屬性,結果為 Kevin。

5.原型的原型

原型也是一個對象

var obj = new Object()
   obj.name = "Zjy"
   console.log(obj.name)      
javascript_原型與原型鍊

其實原型對象就是通過 Object 構造函數生成的,結合之前所講,執行個體的 proto 指向構造函數的 prototype ,是以我們再更新下關系圖:

javascript_原型與原型鍊

6.原型鍊

簡單的回顧一下構造函數、原型和執行個體的關系:每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而執行個體都包含一個指向原型對象的内部指針。那麼假如我們讓原型對象等于另一個類型的執行個體,結果會怎樣?顯然,此時的原型對象将包含一個指向另一個原型的指針,相應地,另一個原型中也包含着一個指向另一個構造函數的指針。假如另一個原型又是另一個類型的執行個體,那麼上述關系依然成立。如此層層遞進,就構成了執行個體與原型的鍊條。這就是所謂的原型鍊的基本概念。

console.log(Object.prototype.__proto__ === null)      

繼續閱讀