關於javascript的原型和原型鏈,看我就夠了(三)

溫故

咱們先回顧一下前兩天討論的內容javascript

建立對象的三種方式

  • 經過對象直接量
  • 經過new建立對象
  • 經過Object.create()

js中對象分爲兩種

  • 函數對象
  • 普通對象

原型對象prototype

  • 每個函數對象都有一個prototype屬性,可是普通對象是沒有的;
  • 普通對象都是經過函數建立的

在 ECMAScript 核心所定義的所有屬性中,最回味無窮的就要數 prototype 屬性了。對於 ECMAScript 中的引用類型而言,prototype 是保存着它們全部實例方法的真正所在。換句話所說,諸如 toString()和 valuseOf() 等方法實際上都保存在 prototype 名下,只不過是經過各自對象的實例訪問罷了。----《JavaScript 高級程序設計》java

構造函數constructor

function Foo(name) {
    this.name = name;
}
var foo = new Foo('陌上寒');
 console.log(Foo.prototype.constructor===Foo)//true
 console.log(foo.constructor===Foo);//true
複製代碼

原型對象有一個constructor屬性,指向該原型對象對應的構造函數 foo 爲何有 constructor 屬性?那是由於 foo 是 Foo 的實例。 那 Foo.prototype 爲何有 constructor 屬性??同理, Foo.prototype Foo 的實例。 也就是在 Foo 建立的時候,建立了一個它的實例對象並賦值給它的 prototypesegmentfault

隱式原型_proto_

在Firefox、Safari 和 Chrome 的每一個對象上都有這個_proto_,屬性 ,而在其餘瀏覽器中是徹底不可見的爲了確保瀏覽器兼容性問題,不要直接使用 proto 屬性)數組

// 普通對象的\__proto\__指向當前函數對象的原型,
console.log('陌上寒'.__proto__===String.prototype);//true
//原型對象(也屬於普通對象)的__proto__指向當前函數對象的原型
console.log(String.prototype.__proto__===Object.prototype);//true
//內置函數對象的\__proto\__指向的都是ƒ () { [native code] }
console.log(Object.__proto__);//ƒ () { [native code] }
//Object的原型對象的\__proto\__爲null
console.log(Object.prototype.__proto__)//null
複製代碼
  • 普通對象的__proto__指向當前函數對象的原型,
  • 原型對象(也屬於普通對象)的__proto__指向當前函數對象的原型
  • 內置函數對象的__proto__指向的都是ƒ () { [native code] }
  • 全部對象(除了Object.prototype)都存在_proto_
  • Object的原型對象的__proto__爲null 好好消化上面的知識點,有助於我麼討論新的內容==>原型鏈

知新

原型鏈

  • 原型對象prototype
  • 構造函數constructor
  • 隱式原型_proto_ 經過三者之間的聯繫,造成了原型鏈 繼續看一下我門昨天討論過的代碼
console.log('陌上寒'.__proto__===String.prototype);//true
console.log(String.prototype.__proto__===Object.prototype);//true
//等量代換,得出如下結論
console.log('陌上寒'.__proto__.__proto__===Object.prototype);//true
複製代碼

咱們剛纔說過,普通對象的__proto__指向當前函數對象的原型 咱們剛纔還說過,普通對象都是經過函數建立的 根據以上兩個結論咱們分析一下上面的代碼 ‘陌上寒’是字符串類型,’陌上寒’的構造函數是String(), 因此’陌上寒’的__proto__指向String的原型 String是js的內置構造函數,內置構造函數繼承自Object String的原型對象String.prototype也是一個普通對象,它的__proto__指向Object的原型,即Object.prototype 因此瀏覽器

console.log('陌上寒'.__proto__.__proto__===Object.prototype);//true
複製代碼

這就是原型鏈 咱們繼續品讀如下代碼函數

//咱們建立一個構造函數Foo(要記得,構造函數命名,首字母要大寫)
function Foo() {}
//經過咱們自定義的構造函數。經過new操做符,咱們實例化出來一個對象foo
const foo = new Foo()
//對象的__proto__指向當前函數對象(foo是同構Foo實例化出來的,因此foo的函數對象是Foo)的原型
console.log(foo.__proto__===Foo.prototype);
//原型對象也存在__proto__,指向該原型對象(Foo.prototype)所對應的函數對象(Object)的原型(好像有點繞,看代碼就沒那麼繞了)
console.log(Foo.prototype.__proto__===Object.prototype);//true
//上面的若是懂了,這行代碼就簡單了,一個數學的等量代換,就得出告終論
console.log(foo.__proto__.__proto__===Object.prototype);//true
console.log('---我是分割線----');
//咱們經過字面量建立了一個對象,等同於 const obj = new Object()
const obj = {}
//obj 是經過內置構造函數Object建立的,因此,obj的__proto__指向它的函數對象(Object)的原型(prototype)即:Object.prototype
console.log(obj.__proto__===Object.prototype);//true
console.log('---我是分割線----');//true
//建立一個對象b
const b = {}
//咱們以前說過建立對象有三種方式,咱們使用第三種方式建立一個對象b1,對象b1繼承自對象b,也就是說,對象b是對象b1的__proto__
const b1 = Object.create(b)
//對象b是對象b1的__proto__
console.log(b1.__proto__===b);//true
//前面已經證明過,b.__proto__==Object.prototype,再也不贅述
console.log(b.__proto__==Object.prototype);//true
//等量代換就得出如下結論
console.log(b1.__proto__.__proto__===b.__proto__);//true
console.log(b1.__proto__.__proto__==Object.prototype);//true
複製代碼

我偷了一張圖😁,咱們看一下 ui

啊,好像很簡單,咱們看一下

//自定義構造函數A(構造函數命名首字母大寫)建立方式等同於var A = new Function()
var A = function(){}//等同於var A = new Function()
//經過構造函數A,使用new操做符實例化一個對象a(A是a的構造函數,a是A建立出來的)
var a = new A()
//對象的的__proto__指向它所對象函數對象(A)的原型(A.prototype)
console.log(a.__proto__===A.prototype)//true
//A是經過js內置構造函數Function建立出來的,然而
console.log(A.prototype.__proto__===Function.prototype);//false
console.log(A.prototype.__proto__==Object.prototype);//true
console.log(Function.prototype)//ƒ () { [native code] }
複製代碼

Function特例

咱們從新修改一下上面的代碼this

var A  = new Function()
var a = new A()
複製代碼

A.prototype是個函數對象,理論上他的__proto__應該指向 Function.prototype,就是他本身,本身指向本身,沒有意義。 js一直強調萬物皆對象,函數對象也是對象,給他認個祖宗,指向Object.prototype。Object.prototype._proto_ === null,保證原型鏈可以正常結束。 事實驗證了這樣一個道理spa

console.log(a.__proto__===A.prototype)//true
console.log(A.prototype.__proto__===Function.prototype);//false
console.log(A.prototype.__proto__==Object.prototype);//true
console.log(a.__proto__.__proto__==Object.prototype);//true
複製代碼

A的原型對象的__proto__指向的是Object的原型 再看一張圖 .net

圖片來源

  • 原型對象是構造函數的prototype屬性,是全部實例化對象共享屬性和方法的原型對象。
  • 實例化對象經過new構造函數獲得,都繼承了原型對象的屬性和方法。
  • 原型對象中有個隱式的constructor,指向了構造函數自己。

再看一張圖,細細品味

圖片地址

總結

今天先討論到這裏,咱們一塊兒對今天的內容作一個總結 全部函數對象的\ _proto_ 都指向 Function.prototype,它是一個空函數(Empty function)ƒ () { [native code] }

var obj = {name: '陌上寒'}
var arr = [1,2,3]
var reg = /hello/g
var date = new Date
var err = new Error('exception')
console.log(obj.__proto__ === Object.prototype) // true
console.log(arr.__proto__ === Array.prototype)  // true
console.log(reg.__proto__ === RegExp.prototype) // true
console.log(date.__proto__ === Date.prototype)  // true
console.log(err.__proto__ === Error.prototype)  // true
複製代碼

全部對象的 _proto_ 都指向其構造器的 prototype 原型鏈 原型鏈是實現繼承的主要方法。

本身是由本身建立的,好像不符合邏輯,但仔細想一想,現實世界也有些相似,你是怎麼來的,你媽生的,你媽怎麼來的,你姥姥生的,……類人猿進化來的,那類人猿從哪來,一直追溯下去……,就是無,(NULL生萬物) 正如《道德經》裏所說「無,名天地之始」。

function Person(){}
var person1 = new Person();
console.log(person1.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype) //true
console.log(Object.prototype.__proto__) //null

Person.__proto__ === Function.prototype; //true
console.log(Function.prototype)// function(){} (空函數)

var num = new Array()
console.log(num.__proto__ === Array.prototype) // true
console.log( Array.prototype.__proto__ === Object.prototype) // true
console.log(Array.prototype) // [] (空數組)
console.log(Object.prototype.__proto__) //null
console.log(Array.__proto__ === Function.prototype)// true
複製代碼

咱們一塊兒連續討論了那麼多,相信你必定對js原型和原型鏈有了些認識,可是光有認識仍是不夠的,原型和原型鏈在實際場景中是怎麼發揮做用的呢?咱們如何將原型鏈的相關技能投入到開發中呢?咱們明天繼續討論javascript的原型和原型鏈,不見不散

原文連接

相關文章

關於javascript的原型和原型鏈,看我就夠了(一)

關於javascript的原型和原型鏈,看我就夠了(二)

關於javascript的Object. hasOwnProperty,看我就夠了

參考連接

JavaScript之原型與原型鏈

圖解prototype、proto和constructor的三角關係

Function.proto===Function.prototype怎麼解釋?

最詳盡的 JS 原型與原型鏈終極詳解,沒有「多是」。(一)

相關文章
相關標籤/搜索