欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

徹底理解JavaScript的原型與原型鏈

 更新時間:2021年10月14日 10:03:06   作者:戰(zhàn)場小包  
原型和原型鏈是js中的難點也是重點,明白了原型和原型鏈會讓我們在后面不管是學(xué)習(xí)還是工作都會更加高效,這篇文章主要給大家介紹了關(guān)于JavaScript原型與原型鏈的相關(guān)資料,需要的朋友可以參考下

前言

原型與原型鏈知識歷來都是面試中考察的重點,說難不算太難,但要完全理解還是得下一定的功夫。先來看一道面試題開開胃口吧:

function User() {}
User.prototype.sayHello = function() {}
var u1 = new User();
var u2 = new User();
console.log(u1.sayHello === u2.sayHello); 
console.log(User.prototype.constructor); 
console.log(User.prototype === Function.prototype); 
console.log(User.__proto__ === Function.prototype); 
console.log(User.__proto__ === Function.__proto__); 
console.log(u1.__proto__ === u2.__proto__); 
console.log(u1.__proto__ === User.__proto__); 
console.log(Function.__proto__ === Object.__proto__); 
console.log(Function.prototype.__proto__ === Object.prototype.__proto__); 
console.log(Function.prototype.__proto__ === Object.prototype); 

基礎(chǔ)鋪墊

JavaScript所有的對象本質(zhì)上都是通過new 函數(shù)創(chuàng)建的,包括對象字面量的形式定義對象(相當于new Object()的語法糖)。

所有的函數(shù)本質(zhì)上都是通過new Function創(chuàng)建的,包括Object、Array等

所有的函數(shù)都是對象。

prototype

每個函數(shù)都有一個屬性prototype,它就是原型,默認情況下它是一個普通Object對象,這個對象是調(diào)用該構(gòu)造函數(shù)所創(chuàng)建的實例的原型。

contructor屬性

JavaScript同樣存在由原型指向構(gòu)造函數(shù)的屬性:constructor,即Func.prototype.constructor --> Func

__proto__

JavaScript中所有對象(除了null)都具有一個__proto__屬性,該屬性指向該對象的原型。

function User() {}
var u1 = new User();
// u1.__proto__ -> User.prototype
console.log(u1.__proto__ === User.prototype) // true

顯而易見,實例的__proto__屬性指向了構(gòu)造函數(shù)的原型,那么多個實例的__proto__會指向同一個原型嗎?

var u2 = new User();
console.log(u1.__proto__ === u2.__proto__) // true

如果多個實例的__proto__都指向構(gòu)造函數(shù)的原型,那么實例如果能通過一種方式,訪問原型上的方法,屬性等,就可以在原型進行編程,實現(xiàn)繼承的效果。

我們繼續(xù)更新一下原型與原型鏈的關(guān)系圖:

原型鏈

實例對象在查找屬性時,如果查找不到,就會沿著__proto__去與對象關(guān)聯(lián)的原型上查找,如果還查找不到,就去找原型的原型,直至查到最頂層,這也就是原型鏈的概念。

就借助面試題,舉幾個原型鏈的例子:

舉例

  1. u1.sayHello():
    u1上是沒有sayHello方法的,因此訪問u1.__proto__(User.prototype),成功訪問到sayHello方法
  2. u2.toString()
    u2,User.prototype都沒有toString方法,User.prototype也是一個普通對象,因此繼續(xù)尋找User.prototype.__proto__(Object.prototype),成功調(diào)用到toString方法

提高

學(xué)完上面那些,大多數(shù)面試題都可以做出來了,例如下面這種

function A() {}
function B(a) {
    this.a = a;
}
function C(a) {
    if (a) {
        this.a = a;
    }
}
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;

console.log(new A().a); //1
console.log(new B().a); //undefined
console.log(new C(2).a); //2

但距離解決文章的最初的面試題還欠缺些什么,比如Function.__proto__ === Object.__proto__、Function.prototype.__proto__ === Object.prototype.__proto__等,接著我們來一一攻克它。

Objcet.__proto__ 、 Object.prototype、Object.prototype.__proto__

  • Object是構(gòu)造函數(shù),在第二部分我們講過所有的函數(shù)都是通過new Function創(chuàng)建了,因此Object相當于Function的實例,即Object.__proto__ --> Function.prototype。
  • Object.prototype是Object構(gòu)造函數(shù)的原型,處于原型鏈的頂端,Object.prototype.__proto__已經(jīng)沒有可以指向的上層原型,因此其值為null
// 總結(jié):
Object.__proto__ --> Function.prototype
Object.prototype.__proto__ --> null

Function.__proto__、Function.prototype、Function.prototype.__proto__

  • Function.prototype是Function的原型,是所有函數(shù)實例的原型,例如上面講的Object.__proto__
  • Function.prototype是一個普通對象,因此Function.prototype.__proto__ --> Object.prototype
  • Function.__proto__: __proto__指向創(chuàng)造它的構(gòu)造函數(shù)的原型,那誰創(chuàng)造了Function那?
    • 猜想:函數(shù)對象也是對象,那Function.__proto__會指向Object.prototype嗎?上文提到,Object.__proto__ --> Function.prototype。如果Function.__proto__ -> Object.prototype,感覺總是怪怪的,到底誰創(chuàng)造了誰,于是我去做了一下測試:

 

實踐證明只存在Object.__proto__ --> Function.prototype

苦思冥想沒得出結(jié)果,難道Function函數(shù)是猴子不成,從石頭縫里面蹦出來的?于是我進行了一同亂七八糟的測試,沒想到找出了端倪。

 

通過上面我們可以得出:Function.__proto__ --> Function.prototype

Function函數(shù)不通過任何東西創(chuàng)建,JS引擎啟動時,添加到內(nèi)存中

總結(jié)

最后將原型與原型鏈方面的知識凝結(jié)成一張圖:

  1. 所有函數(shù)(包括Function)的__proto__指向Function.prototype
  2. 自定義對象實例的__proto__指向構(gòu)造函數(shù)的原型
  3. 函數(shù)的prototype的__proto__指向Object.prototype
  4. Object.prototype.__proto__ --> null

后語

知識的海洋往往比想象中還要遼闊,原型與原型鏈這邊也反復(fù)的學(xué)過多次,我認為應(yīng)該學(xué)的比較全面,比較完善了。但遇到這個面試題后,我才發(fā)現(xiàn)我所學(xué)的只不過是一根枝干,JS里面真的有很多深層次的寶藏等待挖掘。學(xué)海無涯,與君共勉。

最后再附贈個簡單的面試題,提高一下自信:

var F = function () {}
Object.prototype.a = function () {}
Function.prototype.b = function () {}

var f = new F();

console.log(f.a, f.b, F.a, F.b);

// 原型鏈
// f.__proto__ --> F.prototype --> Object.prototype
// F.__proto__ --> Function.prototype --> Object.prototype

到此這篇關(guān)于JavaScript原型與原型鏈的文章就介紹到這了,更多相關(guān)JavaScript原型與原型鏈內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論