前置

          原型是 JavaScript 巧妙的設(shè)計(jì),它非常容易理解。都 2020 年了,看完這篇希望你以后不需要再重復(fù)學(xué)習(xí) JavaScript
          原型了。如有不當(dāng)之處,懇請(qǐng)指點(diǎn)一二!

          單詞

          下面是相關(guān)單詞及其翻譯,牢牢記住它們就成功一半了。

          * constructor 構(gòu)造器
          * proto & prototype 原型;雛形;最初形態(tài)
          constructor
          function Drink() {} const a = new Drink() console.log(a.constructor) // ?
          Drink() {}
          a 是由函數(shù) Drink 構(gòu)造而來(lái)的。

          prototype

          簡(jiǎn)單寫(xiě)點(diǎn)代碼,后面全是 console.log。
          function f() { this.a = 1 this.b = 2 } const o = new f() f.prototype.b = 3
          f.prototype.c = 4
          o 是 new f() 返回的結(jié)果,不妨回顧一下當(dāng)執(zhí)行 new f() 時(shí), new 操作符對(duì)函數(shù) f 做了些什么事。

          * 創(chuàng)建一個(gè)空對(duì)象(即{}): var obj = Object.create(null)。
          * 鏈接該對(duì)象(即設(shè)置該對(duì)象的構(gòu)造函數(shù))到另一個(gè)對(duì)象(本函數(shù)), 這個(gè)空對(duì)象繼承其原型: obj.__proto__ = f.prototype。
          * 使用指定的參數(shù)調(diào)用函數(shù) f,new Foo 等同于 new Foo(),也就是 f 不帶任何參數(shù)調(diào)用的情況; 將步驟 1 創(chuàng)建的對(duì)象作為 this
          的上下文(將 this 綁定到新創(chuàng)建的對(duì)象 | f 函數(shù)中的 this 的指針替換成 obj) ,f.call(obj)。
          * 如果該函數(shù)沒(méi)有顯式地在函數(shù)中寫(xiě) return,則返回 this。
          對(duì)于一個(gè)函數(shù),如果不使用 new 操作它,它只是一個(gè)正常的函數(shù);使用 new 操作符僅僅改變了它的 this
          指向且在函數(shù)內(nèi)部隱式地創(chuàng)建了一個(gè)對(duì)象,然后再稱(chēng)之為 “構(gòu)造函數(shù)”。僅此而已。

          如果你對(duì)第三步中的操作有困惑,看幾個(gè)簡(jiǎn)單的例子:
          設(shè)置構(gòu)造函數(shù) function f() { this.a = 1 this.b = 2 } f() console.log(f.constructor)
          //? Function() { [native code] } function f() { this.a = 1 this.b = 2 } const o
          = new f() console.log(o.constructor) // ? f() { // this.a = 1 // this.b = 2 // }
          this指針替換 function f() { console.log(this) // window this.a = 1 this.b = 2 } f()
          function f() { console.log(this) // f?{} this.a = 1 this.b = 2
          console.log(this) // f?{a: 1, b: 2} } new f() 什么是call? const drink = { name:
          'Coca Cola', color: 'black', price: '3.5', intro: function () {
          console.log(`名稱(chēng):${this.name},顏色:${this.color},價(jià)格:${this.price}`) }, } const
          computer = { name: 'Orange Juice', color: 'orange', price: '4', }
          drink.intro.call(computer) //名稱(chēng):Orange Juice,顏色:orange,價(jià)格:4
          確保上面的內(nèi)容你能十分清晰,否則不要進(jìn)行下面的內(nèi)容。
          console.log(o.b) // 2
          o 的值是通過(guò) new f() 得到的對(duì)象,this 指向這個(gè)對(duì)象,函數(shù)中給 this 添加了屬性 b 為其賦值為 2,并將他返回。所以 這里打印出 2。
          f.prototype 是無(wú)法被訪問(wèn)到的,這種情況還被稱(chēng)之為 property shadowing ---屬性遮蔽。
          console.log(o.c) // 4 console.log(o.__proto__.c) // 4 console.log(o.__proto__
          === f.prototype) // true
          函數(shù)中并沒(méi)有給 this 添加 c 屬性并為其賦值 4,但是打印 o.c 返回 4。通過(guò)上文你已經(jīng)知道 constructor 是干什么的了:
          console.log(o.constructor.prototype.b) // 3
          o 是由函數(shù) f 構(gòu)造的,o.constructor 返回函數(shù) f,所以o.constructor.prototype === f.prototype,
          f.prototype 返回什么呢?上面初始代碼中直接寫(xiě)好的,現(xiàn)在可以翻上去看看 f.prototype,所以
          o.constructor.prototype.b 返回 3。查找對(duì)象上的屬性就是先找自身再通過(guò) __proto__ 一層一層往上找的:

          * 如果自身有該屬性直接獲取它的值;
          * 如果自身有且其構(gòu)造器的 prototype 上也有,屬性遮蔽不會(huì)忘了吧;
          * 如果一直沿著 __proto__ 找但沒(méi)找到,會(huì)返回 undefined;為什么呢? console.log({}.constructor) // ?
          Object() { [native code] } console.log({}.__proto__ === Object.prototype) //
          true console.log(Object.prototype.__proto__) // null
          看到這里,應(yīng)該十分清晰了。這就是最終為什么會(huì)返回 undefind 的原因:Object.prototype.__proto__ 指向 null。

          小練習(xí)

          做一個(gè)簡(jiǎn)單又不給你解釋的小練習(xí)吧!
          console.log(o.b) console.log(o.__proto__.b) console.log(o.d) 答案 // 2 // 3 //
          undefined
          重要提示

          對(duì)于 Object.prototype.__proto__:



          測(cè)試代碼

          如果看完還是不太明白,動(dòng)手試一試吧!我把本文用到的代碼片段放到此處供你快速拷貝。
          function f() { this.a = 1 this.b = 2 } const o = new f() f.prototype.b = 3
          f.prototype.c = 4 console.log(o.b) // 2 console.log(o.c) // 4
          console.log(o.__proto__.c) // 4 console.log(o.__proto__ === f.prototype) //
          true console.log(o.constructor.prototype.b) // 3 console.log(o.b) // 2
          console.log(o.__proto__.b) // 3 console.log(o.d) // undefined
          console.log({}.constructor) // ? Object() { [native code] }
          console.log({}.__proto__ === Object.prototype) // true
          console.log(Object.prototype.__proto__) // null // --------- other --------
          console.log(o.__proto__) // {b: 3, c: 4, constructor: ?}
          console.log(o.__proto__.__proto__ === Object.prototype) // true
          console.log(Object.prototype.__proto__) // null
          console.log(o.__proto__.__proto__.__proto__) // null
          console.log(f.prototype.__proto__ === Object.prototype) // true

          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點(diǎn)信息
          問(wèn)題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                女人被狂躁60分钟视频 | 福利色导航 | 毛片基地大全 | www..com毛片 | 韩国黄色影视 |