開始從js的this對象說起,this對象就是函數執行的環境對象。
我們來看下面的代碼:
<code>var
name="Jack"
;function
GetName
() {console
.log(this
.name); }var
obj = {name
:"Tom"
}; obj.GetNames=GetName; GetName(); obj.GetNames();/<code>
運行結果
結果分析說明
GetName函數是在全局環境中定義,所以直接調用函數this就指向了全局環境,所以輸出Jack。
之後我們定義了一個obj對象,然後也定義了一個屬性GetNames,並賦值了GetName這個函數的指針。(注意函數不加後面()的時候,那時候就不是調用,那只是一個包含函數指針的變量)
由於函數執行環境變成了obj對象,所以this只想就指向了obj,所以自然就輸出了“Tom”。
函數擴展this對象
es5提供了三個函數非繼承的方法,可以直接改變this的指向,但是在書中說是擴充函數作用域,但是我認為改變this指向更貼切一點。
因為如果是擴充函數作用域,就不用加this來訪問,但是我測試的是,必須加上this才能訪問到擴充的作用域。
三個方法分別為:apply,call,bing,用法都比較簡單,作用也都是改變函數的this指向,下面我就用代碼來簡單說明一下。
1:apply
<code>var
name="Jack"
;function
GetName
() {console
.log(this
.name); }var
obj = {name
:"Tom"
}; GetName.apply(obj,["param1"
,"param2"
]);/<code>
apply方法接受兩個參數,第一個參數就是運行函數的作用域,可以理解為就是this,第二個就是參數數組,可以為Array的實例或者是數組,如果沒有參數,可不傳。
運行結果自然也是輸出“Tom”。
2:call
<code>var
name="Jack"
;function
GetName
() {console
.log(this
.name); }var
obj = {name
:"Tom"
}; GetName.call(obj,"param1"
,"param2"
);/<code>
call和apply唯一不同的在於參數的傳遞,call就不止接受兩個參數,參數的多少看你的父函數需要多個參數,因為call必須要把參數逐個傳進去,不能使用數組或者是Array。
3:bind
<code>var
name="Jack"
;function
GetName
() {console
.log(this
.name); }var
obj = {name
:"Tom"
};var
Clone_GetName=GetName.bind(obj); Clone_GetName();/<code>
bind方法只需要傳入一個參數,那就是this,然後返回一個函數,我們可直接調用。
這三個方法功能都是相同,都是改變this指向,只是使用形式上有一點不同,大家可靈活運用。