js面向物件原型和繼承
阿新 • • 發佈:2018-11-28
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);
}
}
}