哪里调用this就指向哪里。this指向依赖于调用时的位置和调用方法,而非创建时的位置。
全局上下文
默认情况下,全局上下文环境的this指向于window对象。
var a = 1;
console.log(this.a); // 1
console.log(this == window); // true
值得注意的是,在ES6中let关键字声明定义的全局变量,不挂在顶层对象window中
let a = 1;
console.log(this.a); // undefined
console.log(this == window); // true
函数上下文
在分析函数上下文之前,我们先来了解下调用位置。JavaScript引擎在执行代码时按照顺序执行,则全局上下文(global text)应当首先进入调用栈。之后才是函数上下文进栈,当函数被调用时则进行出栈。
举个例子
function foo(){
foo2();
}
function foo2(){
foo3();
}
function foo3(){
console.log("i am foo3");
}
foo();
如上这段代码,最开始是全局上下文首先入栈,而后foo入栈,看到foo中还调用foo2则继续进栈,同理入栈foo3。根据栈后进先出的原则,则foo3首先被弹出栈,而后foo2、foo依次出栈。该函数上下文所在栈元素的前一个元素,则为调用位置。而实际上,需要结合调用方式来判定。
var a = 1;
function foo(){
var a = 2;
foo2();
}
function foo2(){
var a = 3;
console.log(this.a); // 1
foo3();
}
function foo3(){
console.log(this.a); // 1
console.log("i am foo3");
}
foo();
此处为函数独立调用,所以this实际指向于window
普通函数调用
在非严格模式下,普通函数的this指向于window
var a = 1;
function foo(){
console.log(this.a);
}
而在严格模式下,普通函数的this是undefined
'use strict'
var a = 1;
function foo(){
console.log(this); // undefined
console.log(this.a); // 报错
}
foo();
嵌套函数调用
var a = 1;
function foo(){
return function(){
var a = 2;
console.log(this.a);
}
}
foo()(); // 1
var f = foo();
f(); // 1
对象中的函数调用
在一个函数上下文中,this由调用者提供,由调用函数的方式来决定。如果调用者函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。
var a = 1;
function getA(){
return this.a;
}
var obj = {
a:2,
foo:getA
}
console.log(obj.foo()); // 2
如果函数独立调用,那么该函数内部的this,则指向undefined。但是在非严格模式中,当this指向undefined时,它会被自动指向全局对象。
var a = 1;
function getA(){
return this.a;
}
var obj = {
a:2,
foo:getA
};
var f = obj.foo;
console.log(f()); // 1
需要注意的是,这仅是针对函数上下文而言。
var a = 1;
function getA(){
return this.a;
}
var obj = {
a:2,
b:this.a,
foo:function(){
return this.a;
}
};
console.log(obj.b); // 1
console.log(obj.foo()); // 2
call/apply调用
使用call/apply调用时,this作用域指向call/apply的第一个参数对象。call/apply本身差别不大,主要差别就是call传递的形参是一个一个的,而apply是一整个数组传。
var song = 'hello';
function sing(){
console.log(this.song);
}
var obj = {
song:'let it go'
};
sing.call(obj); // let it go
构造函数调用
this指向被创建的对象
var age = 13;
function Animal(age){
this.age = age;
}
var dog = new Animal(12);
console.log(dog.age); //12
DOM事件处理函数调用
this指向于触发事件的DOM元素
var ele = document.getElementById("id");
ele.addEventListener("click",function(e){
console.log(this);
console.log(this === e.target); // true
})
箭头函数调用
箭头函数调用应当是this指向在函数调用里面的特例了,在箭头函数中,会捕获其所在上下文的this值,作为自己的this值。简单来说,就是包裹箭头函数的第一个普通函数中的this。
function foo() {
setTimeout(()=>{
console.log(this.a);
},100)
}
var obj = {
a: 2
}
foo.call(obj); // 2
总结
确定This指向时,首先找到函数调用位置及调用方式
- 由
new
调用:绑定到新创建的对象 - 由
call
或apply
、bind
调用:绑定到指定的对象 - 由上下文对象调用:绑定到上下文对象
- 默认:全局对象
参考文章:https://github.com/axuebin/ar...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。