JS原型、原型鏈深刻理解

原型是JavaScript中一個比較難理解的概念,原型相關的屬性也比較多,對象有」prototype」屬性,函數對象有」prototype」屬性,原型對象有」constructor」屬性。瀏覽器

1、初識原型
在JavaScript中,原型也是一個對象,經過原型能夠實現對象的屬性繼承,JavaScript的對象中都包含了一個」[[Prototype]]」內部屬性,這個屬性所對應的就是該對象的原型。
「[[Prototype]]」做爲對象的內部屬性,是不能被直接訪問的。因此爲了方便查看一個對象的原型,Firefox和Chrome中提供了__proto__這個非標準(不是全部瀏覽器都支持)的訪問器(ECMA引入了標準對象原型訪問器」Object.getPrototype(object)」)。在JavaScript的原型對象中,還包含一個」constructor」屬性,這個屬性對應建立全部指向該原型的實例的構造函數app

2、規則
在JavaScript中,每一個函數 都有一個prototype屬性,當一個函數被用做構造函數來建立實例時,這個函數的prototype屬性值會被做爲原型賦值給全部對象實例(也就是設置 實例的`__proto__`屬性),也就是說,全部實例的原型引用的是函數的prototype屬性。(****`只有函數對象纔會有這個屬性!`****)函數

new 的過程分爲三步  this

?
1
var p = new Person( '張三' ,20);

1. var p={}; 初始化一個對象p。
2. p._proto_=Person.prototype;,將對象p的 __proto__ 屬性設置爲 Person.prototype
3. Person.call(p,」張三」,20);調用構造函數Person來初始化p。關於call/apply使用spa

3、初識Object
Object對象自己是一個函數對象。(CODE TEST) 既然是Object函數,就確定會有prototype屬性,因此能夠看到」Object.prototype」的值就是」Object {}」這個原型對象。反過來,當訪問」Object.prototype」對象的」constructor」這個屬性的時候,就獲得了Obejct函數。
另外,當經過」Object.prototype._proto_」獲取Object原型的原型的時候,將會獲得」null」,也就是說」Object {}」原型對象就是原型鏈的終點了。
4、初識Function
如上面例子中的構造函數,JavaScript中函數也是對象,因此就能夠經過_proto_查找到構造函數對象的原型。
Function對象做爲一個函數,就會有prototype屬性,該屬性將對應」function () {}」對象。
Function對象做爲一個對象,就有__proto__屬性,該屬性對應」Function.prototype」,也就是說,」Function._proto_ === Function.prototype」。.net

在這裏對「prototype」和「proto」進行簡單的介紹:
對於全部的對象,都有__proto__屬性,這個屬性對應該對象的原型.
對於函數對象,除了__proto__屬性以外,還有prototype屬性,當一個函數被用做構造函數來建立實例時,該函數的prototype屬性值將被做爲原型賦值給全部對象實例(也就是設置實例的__proto__屬性)prototype

原型鏈結構圖code

原型鏈
由於每一個對象和原型都有原型,對象的原型指向原型對象,
而父的原型又指向父的父,這種原型層層鏈接起來的就構成了原型鏈。htm

1、屬性查找
當查找一個對象的屬性時,JavaScript 會向上遍歷原型鏈,直到找到給定名稱的屬性爲止,到查找到達原型鏈的頂部(也就是 Object.prototype),若是仍然沒有找到指定的屬性,就會返回 undefined。對象

?
1
2
3
4
5
6
7
8
9
function Person(name, age){
     this .name = name;
     this .age = age;
   }
Person.prototype.MaxNumber = 9999;
Person.__proto__.MinNumber = -9999;
var will = new Person( "Will" , 28);
console.log(will.MaxNumber); // 9999
console.log(will.MinNumber); // undefined

在這個例子中分別給」Person.prototype 「和」 Person.proto」這兩個原型對象添加了」MaxNumber 「和」MinNumber」屬性,這裏就須要弄清」prototype」和」proto」的區別了。

「Person.prototype 「對應的就是Person構造出來全部實例的原型,也就是說」Person.prototype 「屬於這些實例原型鏈的一部分,因此當這些實例進行屬性查找時候,就會引用到」Person.prototype 「中的屬性。

對象建立方式影響原型鏈

?
1
2
3
4
5
6
7
8
var July = {
    name: "張三" ,
    age: 28,
    getInfo: function (){
      console.log( this .name + " is " + this .age + " years old" );
    }
  }
console.log(July.getInfo());

當使用這種方式建立一個對象的時候,原型鏈就變成下圖了. July對象的原型是」Object.prototype」也就是說對象的構建方式會影響原型鏈的形式。

{}對象原型鏈結構圖

綜圖所述
1. 全部的對象都有__proto__屬性,該屬性對應該對象的原型.
2. 全部的函數對象都有prototype屬性,該屬性的值會被賦值給該函數建立的對3. 象的_proto_屬性.
4. 全部的原型對象都有constructor屬性,該屬性對應建立全部指向該原型的實例的構造函數.
5. 函數對象和原型對象經過prototype和constructor屬性進行相互關聯.

原文地址:http://www.jb51.net/article/80109.htm

原型是JavaScript中一個比較難理解的概念,原型相關的屬性也比較多,對象有」prototype」屬性,函數對象有」prototype」屬性,原型對象有」constructor」屬性。

1、初識原型
在JavaScript中,原型也是一個對象,經過原型能夠實現對象的屬性繼承,JavaScript的對象中都包含了一個」[[Prototype]]」內部屬性,這個屬性所對應的就是該對象的原型。
「[[Prototype]]」做爲對象的內部屬性,是不能被直接訪問的。因此爲了方便查看一個對象的原型,Firefox和Chrome中提供了__proto__這個非標準(不是全部瀏覽器都支持)的訪問器(ECMA引入了標準對象原型訪問器」Object.getPrototype(object)」)。在JavaScript的原型對象中,還包含一個」constructor」屬性,這個屬性對應建立全部指向該原型的實例的構造函數

2、規則
在JavaScript中,每一個函數 都有一個prototype屬性,當一個函數被用做構造函數來建立實例時,這個函數的prototype屬性值會被做爲原型賦值給全部對象實例(也就是設置 實例的`__proto__`屬性),也就是說,全部實例的原型引用的是函數的prototype屬性。(****`只有函數對象纔會有這個屬性!`****)

new 的過程分爲三步  

?
1
var p = new Person( '張三' ,20);

1. var p={}; 初始化一個對象p。
2. p._proto_=Person.prototype;,將對象p的 __proto__ 屬性設置爲 Person.prototype
3. Person.call(p,」張三」,20);調用構造函數Person來初始化p。關於call/apply使用

3、初識Object
Object對象自己是一個函數對象。(CODE TEST) 既然是Object函數,就確定會有prototype屬性,因此能夠看到」Object.prototype」的值就是」Object {}」這個原型對象。反過來,當訪問」Object.prototype」對象的」constructor」這個屬性的時候,就獲得了Obejct函數。
另外,當經過」Object.prototype._proto_」獲取Object原型的原型的時候,將會獲得」null」,也就是說」Object {}」原型對象就是原型鏈的終點了。
4、初識Function
如上面例子中的構造函數,JavaScript中函數也是對象,因此就能夠經過_proto_查找到構造函數對象的原型。
Function對象做爲一個函數,就會有prototype屬性,該屬性將對應」function () {}」對象。
Function對象做爲一個對象,就有__proto__屬性,該屬性對應」Function.prototype」,也就是說,」Function._proto_ === Function.prototype」。

在這裏對「prototype」和「proto」進行簡單的介紹:
對於全部的對象,都有__proto__屬性,這個屬性對應該對象的原型.
對於函數對象,除了__proto__屬性以外,還有prototype屬性,當一個函數被用做構造函數來建立實例時,該函數的prototype屬性值將被做爲原型賦值給全部對象實例(也就是設置實例的__proto__屬性)

原型鏈結構圖

原型鏈
由於每一個對象和原型都有原型,對象的原型指向原型對象,
而父的原型又指向父的父,這種原型層層鏈接起來的就構成了原型鏈。

1、屬性查找
當查找一個對象的屬性時,JavaScript 會向上遍歷原型鏈,直到找到給定名稱的屬性爲止,到查找到達原型鏈的頂部(也就是 Object.prototype),若是仍然沒有找到指定的屬性,就會返回 undefined。

?
1
2
3
4
5
6
7
8
9
function Person(name, age){
     this .name = name;
     this .age = age;
   }
Person.prototype.MaxNumber = 9999;
Person.__proto__.MinNumber = -9999;
var will = new Person( "Will" , 28);
console.log(will.MaxNumber); // 9999
console.log(will.MinNumber); // undefined

在這個例子中分別給」Person.prototype 「和」 Person.proto」這兩個原型對象添加了」MaxNumber 「和」MinNumber」屬性,這裏就須要弄清」prototype」和」proto」的區別了。

「Person.prototype 「對應的就是Person構造出來全部實例的原型,也就是說」Person.prototype 「屬於這些實例原型鏈的一部分,因此當這些實例進行屬性查找時候,就會引用到」Person.prototype 「中的屬性。

對象建立方式影響原型鏈

?
1
2
3
4
5
6
7
8
var July = {
    name: "張三" ,
    age: 28,
    getInfo: function (){
      console.log( this .name + " is " + this .age + " years old" );
    }
  }
console.log(July.getInfo());

當使用這種方式建立一個對象的時候,原型鏈就變成下圖了. July對象的原型是」Object.prototype」也就是說對象的構建方式會影響原型鏈的形式。

{}對象原型鏈結構圖

綜圖所述1. 全部的對象都有__proto__屬性,該屬性對應該對象的原型.2. 全部的函數對象都有prototype屬性,該屬性的值會被賦值給該函數建立的對3. 象的_proto_屬性.4. 全部的原型對象都有constructor屬性,該屬性對應建立全部指向該原型的實例的構造函數.5. 函數對象和原型對象經過prototype和constructor屬性進行相互關聯.

相關文章
相關標籤/搜索