原型和原型鍊是JavaScript中的困難點也是重點,以下這篇文章就來帶大家去搞懂原型和原型鏈,希望對大家有幫助!
如果你對原型和原型鏈的了解還停留在一個很淺的、模稜兩可的階段,不妨來看看我的這篇文章,它應該能對你能有所幫助,如果對你有那麼一丟丟幫助的話,歡迎點讚評論加轉發。有問題和疑惑的話也可以在評論區留言,我會第一時間回覆大家,如果覺得我的文章哪裡有知識點錯誤的話,也懇請能夠告知,把錯的東西理解成對的,對我們這個行業來說,是致命的。
之前雖然也常刷原型方面的面試題,但是總是停留在一個很淺的、對知識點模棱兩可的階段,而且經常忘記(這點相信大夥也是這樣,哈哈哈),趁著元旦假期的最後一天(終於摸起了鍵盤),跟著b站一個影片過了下相關方面的知識,對此終於有了一個整體的理解。這裡對其進行了一個整理和歸納。
嗚嗚嗚,本猿在這裡立誓,未來一周,不管多忙,都需要回顧一遍本文,
否則
否則
掘金永遠抽bug。
prototype
:原型__proto__
:原型鏈(連結點)
從屬關係
prototype
:函數的一個屬性-> 不要想的太複雜,其實就是一個普通物件{}__proto__
: 物件上的一個屬性-> 不要想的太複雜,其實就是一個普通物件{}對象的__proto__
保存著物件的建構子的prototype
函數是特殊物件所以__proto__
在函數上也是存在的,且是個function
大家常常忽略忘記的一點:Object
是個方法(建構子),new Object
是個實例物件! ! !
console.log(Object) //typeof Object ==='function' console.log(new Object) //typeof new Object ==='object'
constructor
就是實例化物件的建構子
//test.constructor -> 实例化test对象的构造函数 Test console.log(test.constructor===Test) //true //这里个人理解为永无止境的自身调用自身,求解,没找到相关文章。 console.log(test.constructor.prototype.constructor===Test) //true console.log(test.constructor.prototype.constructor.prototype.constructor===Test) //true //constructor允许更改 function Test2() { this.a=123 } test.constructor=Test2 console.log(test)
function Test(){} let test=new Test() //new完之后 test是个实例对象了 console.log(test.__proto__===Test.prototype) //根据上面的对应关系表 可以知道结果为true //Test.prototype也是一个对象,所以他必须也得有__proto__ //Test.prototype.__proto__已经到达终点了,终点是什么,终点就是Object构造函数,所以下面结果为ture console.log(Test.prototype.__proto__.constructor===Object) //且 按照上面对应关系中的规则和上条的结果,下条结果也是ture console.log(Test.prototype.__proto__===Object.prototype) // //终点为null console.log(Object.prototype.__proto__) //null
對象的__proto__
保存著對象的建構函數的prototype
,prototype
又是個對象,所以也有自己的__proto__
,這樣往復到終點Object.__proto__
,這樣就形成了一個以__proto__
為連結點(為key
)值為建構方法的prototype
物件的一條鏈條, 即為原型鏈。
//__proto__ test{ b:333, a:1, __proto__:Test.prototype={ c:222, b:2, __proto__:Object.prototype={ c:3, __proto__:null } } }
重點:JS中,函數是一種特殊的物件! ! !
記住文章開頭的對應關係表
//函数是特殊对象 所以__proto__是存在的,且是个function console.log(Test.__proto__) //function console.log(Test.prototype) //object
Test
既然是個函數,那麼底層必然也是new Function
實現的,那麼
//对象的__proto__保存着对象的构造函数的prototype console.log(Test.__proto__===Function.prototype) //true 这里是不是和关系表对应上了,能正常理解 const obj={} const obj2=new Object() console.log(Object) //function console.log(typeof Object) //'function'
Function
既然是個建構函數,那麼他是否也應該有__proto__
和prototype
,是的,但這裡有一個特殊的點需要記住。
底層規則規定:Function.__proto__===Function.prototype
是相等的,且兩者回傳的都是一個function,我的理解是Function
自己構造了自己。
//正常来说函数的Test.prototype应该是个object, //Function.prototype是个function,这也是一个特殊的点 typeof Test.prototype==='object' //true console.log(Function.__proto__) // 一个function console.log(Function.prototype) // 一个function //Function既然是函数对象_,那么他的_proto__就指向他的构造函数的prototype,也就是 //Function.__proto__===Function.prototype,自己调自己,这样理解是不是也没毛病。 console.log(Function.__proto__===Function.prototype) //true //Object既然是个构造方法,那么底层也是new Function console.log(Object.__proto__===Function.prototype) //true // 因为Function.__proto__===Function.prototype 所以下面代码是成立的 (Object.__proto__===Function.__proto__)===true
hasOwnProperty
hasOwnProperty
用來判斷是否是物件本身的屬性(非原型鏈繼承過來的)
let test={ a:1, b:2 } Object.prototype.c=3 console.log(test.hasOwnProperty('a')) //true console.log(test.hasOwnProperty('b')) //true console.log(test.hasOwnProperty('c')) //false
in
#in
用來檢查物件是是否包含某個屬性(包含原型鏈上的屬性)
console.log('a' in test) //true console.log('b' in test) //true console.log('c' in test) //true console.log('toString' in test) //true console.log('d' in test) //false
【相關推薦:javascript學習教學】
以上是一文帶你去搞懂JavaScript中的原型和原型鏈的詳細內容。更多資訊請關注PHP中文網其他相關文章!