圖解Javascript原型鏈

jopen 9年前發布 | 39K 次閱讀 JavaScript開發 JavaScript

 

本文嘗試闡述Js中原型(prototype)、原型鏈(prototype chain)等概念及其作用機制。上一篇文章( 圖解Javascript上下文與作用域 )介紹了Js中變量作用域的相關概念,實際上關注的一個核心問題是:“在執行當前這行代碼時Js解釋器可以獲取哪些變量”,而原型與原型鏈實際上還是關于這一問題。

我們知道,在Js中一切皆為對象(Object),但是Js中并沒有類(class);Js是基于原型(prototype-based)來實現的面向對象(OOP)的編程范式的,但并不是所有的對象都擁有prototype這一屬性:

var a = {};
console.log(a.prototype); //=> undefined

var b = function(){};
console.log(b.prototype); //=> {}

var c = 'Hello';
console.log(c.prototype); //=> undefined </pre>

prototype是每個function定義時自帶的屬性,但是Js中function本身也是對象,我們先來看一下下面幾個概念的差別:

1.function、Function、Object和{}

function是Js的一個關鍵詞,用于定義函數類型的變量,有兩種語法形式:

function f1(){
console.log('This is function f1!'); } typeof(f1); //=> 'function'

var f2 = function(){
console.log('This is function f2!'); } typeof(f2); //=> 'function' </pre>
如果用更加面向對象的方法來定義函數,可以用Function:

var f3 = new Function("console.log('This is function f3!');");
f3(); //=> 'This is function f3!'
typeof(f3); //=> 'function'

typeof(Function); //=> 'function' </pre>
實際上Function就是一個用于構造函數類型變量的類,或者說是函數類型實例的構造函數(constructor);與之相似有的Object或String、Number等,都是Js內置類型實例的構造函數。比較特殊的是Object,它用于生成對象類型,其簡寫形式為{}:

var o1 = new Object();
typeof(o1); //=> 'object'

var o2 = {};
typeof(o2); //=> 'object'

typeof(Object); //=> 'function' </pre>

2.prototypeVS__proto__

清楚了上面的概念之后再來看prototype:

Each function has two properties:lengthandprototype

</div>

prototype和length是每一個函數類型自帶的兩個屬性,而其它非函數類型并沒有(開頭的例子已經說明),這一點之所以比較容易被忽略或誤解,是因為所有類型的構造函數本身也是函數,所以它們自帶了prototype屬性:

// Node
console.log(Object.prototype);  //=> {}  
console.log(Function.prototype);//=> [Function: Empty]  
console.log(String.prototype);  //=> [String: '']  

除了prototype之外,Js中的所有對象(undefined、null等特殊情況除外)都有一個內置的[[Prototype]]屬性,指向它“父類”的prototype,這個內置屬性在ECMA標準中并沒有給出明確的獲取方式,但是許多Js的實現(如Node、大部分瀏覽器等)都提供了一個proto屬性來指代這一[[Prototype]],我們通過下面的例子來說明實例中的proto是如何指向構造函數的prototype的:
var Person = function(){};
Person.prototype.type = 'Person';
Person.prototype.maxAge = 100;

var p = new Person();
console.log(p.maxAge);
p.name = 'rainy';

Person.prototype.constructor === Person; //=> true
p.proto === Person.prototype; //=> true
console.log(p.prototype); //=> undefined </pre>

上面的代碼示例可以用下圖解釋:

圖解Javascript原型鏈

Person是一個函數類型的變量,因此自帶了prototype屬性,prototype屬性中的constructor又指向Person本身;通過new關鍵字生成的Person類的實例p1,通過__proto__屬性指向了Person的原型。這里的__proto__只是為了說明實例p1在內部實現的時候與父類之間存在的關聯(指向父類的原型),在實際操作過程中實例可以直接通過.獲取父類原型中的屬性,從而實現了繼承的功能。

3. 原型鏈

清楚了prototype與__proto__的概念與關系之后我們會對“Js中一切皆為對象”這句話有更加深刻的理解。進而我們會想到,既然__proto__是(幾乎)所有對象都內置的屬性,而且指向父類的原型,那是不是意味著我們可以“逆流而上”一直找到源頭呢?我們來看下面的例子:

// Node
var Obj = function(){};
var o = new Obj();
o.proto === Obj.prototype; //=> true
o.proto.constructor === Obj; //=> true

Obj.proto === Function.prototype; //=> true
Obj.proto.constructor === Function; //=> true

Function.proto === Function.prototype; //=> true
Object.proto === Object.prototype; //=> false
Object.proto === Function.prototype; //=> true

Function.proto.constructor === Function;//=> true
Function.proto.proto; //=> {}
Function.proto.proto === o.proto.proto; //=> true
o.proto.proto.proto === null; //=> true </pre>

圖解Javascript原型鏈

從上面的例子和圖解可以看出,prototype對象也有__proto__屬性,向上追溯一直到null。

4.new和instanceof

5. 原型與繼承

http://pivotallabs.com/javascript-constructors-prototypes-and-the-new-keyword/

the Object type in ECMAScript is the base from which all other objects are derived

note that objects in the scope chain also have a prototype chain, so searching may include each object’s prototype chain

Each function has two properties:lengthandprototype

The prototype property is perhaps the most interesting part of the ECMAScript core. The prototype is the actual location of all instance methods for reference types, meaning methods such as toString() and valueOf() actually exist on the prototype and are then accessed from the object instances. This property is very important in terms of defining your own reference types and inheritance. (These topics are covered in Chapter 6.) In ECMAScript 5, the prototype property is not enumerable and so will not be found using for-in.

</div>

P185

How Prototypes Work

</div>

http://www.ruanyifeng.com/blog/2010/05/object-oriented javascript encapsulation.html

首先要區分prototype&[[Prototype]]/__proto__

  1. function Function Object {}

  2. Object的默認屬性與方法

  3. prototype VS proto

  4. constructor ?

  5. prototype chain

  6. instanceof new

  7. 原型與繼承








 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!