js面向對象原型和繼承


js面向對象原型和繼承作用域鏈和閉包

原型

我們都知道,函數創建時瀏覽器會在內存中創建一個對象。很多人在這里都感覺很難理解里面的關系

函數創建的時候,瀏覽器會在內存中創建一個由prototype指向的對象。其實只有當你要將函數作為構造函數使用的時候,創建出來的對象才會發揮作用。
例如:
var obj=new People();
的時候,obj對象就不僅僅使用自己的屬性和方法,它也可以使用People函數創建時生成prototype對象的方法。
而且,Prople的prototype的屬性和方法可以通過 Prople.prototype.屬性名或者方法名創建。

那么也就是說用這種方法可以是對象所使用的屬性和方法更多。
還有一個好處就是減少代碼的重復。當多個對象的屬性或方法相同時,那么讓他們都new一下構造函數。則可以不用每個對象都加上this.屬性。

原型鏈繼承

原型鏈

字面理解就是有原型形成的鏈,讓一個函數的原型等於另一個函數,那么這個函數就另一個函數通過原型串在一起,形成鏈。這樣的方法就可以把n個函數串在一起。


繼承

函數1——>prototype=函數2——>prototype=函數3——>prototype........
按照這樣的鏈,函數1可以通過鏈訪問函數2,函數3等等N個函數,這樣就是繼承。

作用域鏈

要連接作用域鏈,先要知道什么是執行環境。執行環境通俗來講就是代碼要執行的環境,也就是告訴你,環境了有什么,變量,方法之類的,可是使用的對象。最簡單的例子就是全局執行環境,也就是window,所有寫在js的方法,都在window執行環境里。
而每一個函數也有自己的執行環境。


而作用域鏈,可以看做是起作用的鏈,每個函數在創建的時候,都有執行環境,而眾多的函數形成的執行環境會存儲在作用域鏈中,因此作用域鏈就是存儲函數執行環境的。


函數要使用對象的時候,是在作用域鏈中查找的。查找的順序是頂層開始的。
存入的時候都是全局執行環境在頂層的,但是,但函數調用執行的時候,會先提前到頂層,執行完在釋放。所以可以理解為函數的查找是在自身,當沒找到則完上層查找,直到找到為止。

閉包

就是有權訪問另一函數作用域的變量的函數就是閉包。當然了,訪問window的作用域變量是不算的。(函數嵌套肯定就是閉包了,因為里面的函數肯定可以訪問外面函數作用域的變量)。

閉包的經典問題

先看看這段代碼:
var li=document.querySelectorAll('li');
function a(){
for(var i=0;i<li.length;i++){
li[i].onclick=function(){
console.log(i);
}
}
}

輸出結果為點擊出現的全是li.length。要的效果是點擊第一個li出現0...

第一種方法:
var li=document.querySelectorAll('li');
function a(){
for(var i=0;i<li.length;i++){
li[i].index=i;
li[i].onclick=function(){
console.log(li[i].index);
}
}
}

第二種方法:
var li=document.querySelectorAll('li');
function a(){
for(var i=0;i<li.length;i++){
li[i].onclick=(function(i){
return function(){
console.log(i);
}
})(i)
}
}

第三種方法:
var li=document.querySelectorAll('li');
function a(){
for(let i=0;i<li.length;i++){
li[i].onclick=function(){
console.log(i);
}
}
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com