javascript 函数执行上下文
在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));