相关阅读
this指向问题
首先来看下面的例子,不同的写法,可能有不同的结果
var obj = {
foo: function() { console.log(this.bar); },
bar: 1
};
var foo = obj.foo;
var bar = 2;
obj.foo() // 1
foo() // 2
造成不同结果的原因,在于函数里使用到了this,obj.foo()是在obj的环境执行,因此拿到的是obj的bar。而一旦var foo = obj.foo, foo()就变成在全局环境执行。
那函数的运行环境到底是怎么决定的?
var obj = {foo: 5};
上面的代码将一个对象赋值给变量obj,JS引擎会先在内存里生成一个对象{foo: 5},再把内存地址赋值给obj。 原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。上面例子的foo属性,实际上是以下面的形式存在的: obj -> foo -> [[value]]:5 [[writable]]:true [[enumerable]]: true [[configurable]]: true
那如果属性的值是一个函数,like:
var obj = { foo: function() {}};
这时引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性value属性
由于函数是一个单独的值,所以它可以在不同的环境(上下文)执行, 而this就是用于在函数体内部获得当前的运行环境
var f = function() {
console.log(this.x);
}
var x=1;
var obj = {
f:f,
x:2
}
//单独执行
f(); // 1
//obj环境执行
obj.f(); //2
上述代码中,函数f在全局环境执行,this.x指向全局环境的x
在obj环境执行,this.x指向obj.x
this上下文
全局上下文
无论是否在严格模式下,在全局执行环境中(在任何函数体外部),this都指向全局对象, 严格模式时指向undefined,非严格模式下,自动指向全局对象(浏览器中就是window)
函数上下文
在函数内部,this的值取决于函数被调用的方式。 函数的调用方式有哪些:
- 在全局环境或是普通函数中直接调用
- 作为对象的方法
- 使用apply和call
- 作为构造函数
直接调用
var a = 1;
var obj = {
a: 2,
b: function () {
function fun() {
return this.a
}
console.log(fun());
}
}
obj.b();//1
fun函数虽然在obj.b方法中定义,但它还是一个普通函数,直接调用在非严格模式下指向全局对象。 当函数独立调用的时候,在严格模式下它的this指向undefined,在非严格模式下,当this指向undefined的时候,自动指向全局对象(浏览器中就是window)。
作为对象的方法
var a = 1;
var obj = {
a: 2,
b: function() {
return this.a;
}
}
console.log(obj.b())//2
var t = obj.b;
console.log(t());//1
作为对象的方法调用-〉obj.b(),这个时候this指向调用它的对象,就是obj。var t = obj.b时,这个时候就不是作为对象的方法调用,相当于函数独立调用。
使用call和apply
改变函数执行上下文
作为构造函数
this代表它即将new出来的对象
箭头函数
箭头函数,不可以用call和apply改变this, 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值