本文主要跟大家分享JS原型鏈詳解,函數(Function)才有prototype屬性,物件(除Object)擁有__proto__。希望能幫助大家。
#所謂原型鏈,指的就是圖中的proto這條指標鏈!
原型鏈的頂層就是Object.prototype,而這個物件的是沒有原型物件的。
可在chrome的控制台裡面輸入:
Object.__proto__
#輸出是:
function Empty() {}
原型鏈,如此而已。
原型是一個對象,其他物件可以透過它實現屬性繼承。
一、prototype與__proto__的差異
var a = {}; console.log(a.prototype); //undefined console.log(a.__proto__); //Object {} var b = function(){} console.log(b.prototype); //b {} console.log(b.__proto__); //function() {}
/*1、字面量方式*/ var a = {}; console.log(a.__proto__); //Object {} console.log(a.__proto__ === a.constructor.prototype); //true /*2、构造器方式*/ var A = function(){}; var a = new A(); console.log(a.__proto__); //A {} console.log(a.__proto__ === a.constructor.prototype); //true /*3、Object.create()方式*/ var a1 = {a:1} var a2 = Object.create(a1); console.log(a2.__proto__); //Object {a: 1} console.log(a.__proto__ === a.constructor.prototype); //false(此处即为图1中的例外情况)
var A = function(){}; var a = new A(); console.log(a.__proto__); //A {}(即构造器function A 的原型对象) console.log(a.__proto__.__proto__); //Object {}(即构造器function Object 的原型对象) console.log(a.__proto__.__proto__.__proto__); //null
我在寫一篇圖解prototype和__proto__的區別時,搜資料搜到了一個有意思的現象,下面這兩個運算返回的結果是一樣的:
Function instanceof Object;//true Object instanceof Function;//true
這個是怎麼一回事呢?要從運算子instanceof說起。
一、instanceof究竟是運算什麼的?
我曾经简单理解instanceof只是检测一个对象是否是另个对象new出来的实例(例如var a = new Object(),a instanceof Object返回true),但实际instanceof的运算规则上比这个更复杂。
首先w3c上有官方解释(传送门,有兴趣的同学可以去看看),但是一如既往地让人无法一目了然地看懂……
知乎上有同学把这个解释翻译成人能读懂的语言(传送门),看起来似乎明白一些了:
//假设instanceof运算符左边是L,右边是R L instanceof R //instanceof运算时,通过判断L的原型链上是否存在R.prototype L.__proto__.__proto__ ..... === R.prototype ? //如果存在返回true 否则返回false
注意:instanceof运算时会递归查找L的原型链,即L.__proto__.__proto__.__proto__.__proto__...直到找到了或者找到顶层为止。
所以一句话理解instanceof的运算规则为:
instanceof检测左侧的__proto__原型链上,是否存在右侧的prototype原型。
二、图解构造器Function和Object的关系
<br/>
我们再配合代码来看一下就明白了:
//①构造器Function的构造器是它自身 Function.constructor=== Function;//true //②构造器Object的构造器是Function(由此可知所有构造器的constructor都指向Function) Object.constructor === Function;//true //③构造器Function的__proto__是一个特殊的匿名函数function() {} console.log(Function.__proto__);//function() {} //④这个特殊的匿名函数的__proto__指向Object的prototype原型。 Function.__proto__.__proto__ === Object.prototype//true //⑤Object的__proto__指向Function的prototype,也就是上面③中所述的特殊匿名函数 Object.__proto__ === Function.prototype;//true Function.prototype === Function.__proto__;//true
三、当构造器Object和Function遇到instanceof
我们回过头来看第一部分那个“奇怪的现象”,从上面那个图中我们可以看到:
Function.__proto__.__proto__ === Object.prototype;//true Object.__proto__ === Function.prototype;//true
所以再看回第一点中我们说的instanceof的运算规则,Function instanceof Object 和 Object instanceof Function运算的结果当然都是true啦!
如果看完以上,你还觉得上面的关系看晕了的话,只需要记住下面两个最重要的关系,其他关系就可以推导出来了:
1、所有的构造器的constructor都指向Function
2、Function的prototype指向一个特殊匿名函数,而这个特殊匿名函数的__proto__指向Object.prototype
至於prototype和__proto__的關係如何推導,可以參考我寫的上一篇部落格《三張圖搞懂JavaScript的原型物件與原型鏈》
本文試著闡述Js中原型(prototype)、原型鏈(prototype chain)等概念及其作用機制。上一篇文章(圖解Javascript上下文與作用域)介紹了Js中變數作用域的相關概念,實際上關注的一個核心問題是:“在執行當前這行程式碼時Js解釋器可以獲得哪些變數”,而原型與原型鏈其實還是關於這個問題。
我們知道,在Js中一切皆為物件(Object),但Js中並沒有類別(class);Js是基於原型(prototype-based)來實現的物件導向(OOP)的程式設計範式的,但並不是所有的物件都有prototype
這一屬性:
1 2 3 4 5 6 7 8 |
#var
console.log(c.prototype);
1.
|
function 是Js的一個關鍵字,用來定義函數類型的變量,有兩種語法形式: #################### #############1######2######3######4#######5######6# #####7######8####9 |
##} typeof 如果用更物件導向的方法定義函數,可以用
|
以上是JS原型鏈詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!