1. 程式人生 > >js面向物件原型和繼承

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); } } }