在js里,每個函數都有一個執行的上下文,我們可以通過this來訪問。
如:
全局函數
function test(){
var local = this;
}
我們發現local等於window(dom根對象),也就是說全局函數實際上是window的一個屬性。
同理全局變量也是如此。
比如 var name = ‘phil’; 我們可以通過window[‘name’]或者window.name 來訪問。
而當函數是某一個對象的屬性的時候,該函數的上下文就是該對象。
var student = {};
student.age = 20;
student.getAge = function(){
return this.age;
}
當有函數嵌套的時候,事情就變得稍微復雜點了。
var seq = [1,2,3,4];
for(var i in seq){
var name = ‘phil’ + i;
window.setTimeout(function(){
$('p’).apend(name);
},i*1000)
}
有人可能認為輸出是phil1phil2phil3phil4,實際上結果是phil4phil4phil4phil4
因為函數window.setTimeout(實際上我們常常會省略掉window)的上下文實際上是window,而函數體中的name實際上就是window.name
他的值就是最后一次循環后的值phil4。
那如果我們需要的結果是phil1phil2phil3phil4那該怎么寫:
var seq = [1,2,3,4];
for(var i in seq){
var name = ‘phil’ + i;
var obj = {};
obj.name = name;
obj.setTimeout = function(){
var local = this; // 該方法是對象obj的屬性方法,所以this就是obj
window.setTimeout(function(){
$('p’).apend(local.name); // 此處千萬不可以用this,因為此處的this實際上是window。
},i*1000)
}
}
call和apply通常用來修改函數的上下文,函數中的this指針將被替換為call或者apply的第一個參數
//定義一個人,名字為jack
var jack = {
name : "jack",
age : 26
}
//定義另一個人,名字為abruzzi
var abruzzi = {
name : "abruzzi",
age : 26
}
//定義一個全局的函數對象
function printName(){
return this.name;
}
//設置printName的上下文為jack, 此時的this為jack
print(printName.call(jack));
//設置printName的上下文為abruzzi,此時的this為abruzzi
print(printName.call(abruzzi));
print(printName.apply(jack));
print(printName.apply(abruzzi));
只有一個參數的時候call和apply的使用方式是一樣的,如果有多個參數:
function setName(value){
this.name = value;
}
setName.apply(jack, ["Jack Sept."]);
print(printName.apply(jack));
setName.call(abruzzi, "John Abruzzi");
print(printName.call(abruzzi));
