在普通函数中的this:
this的值是在执行的时候才能确认,定义的时候不能确认!为什么呢 —— 因为this是执行上下文环境的一部分,而执行上下文需要在代码执行之前确定,而不是定义的时候。
1、this总是代表它的直接调用者,比如:obj.fun,那么fun中的this是obj
2、如果没有直接调用者,默认情况下(非严格模式)this为window对象(举例:回调函数里的this如果没有做特殊处理,则指向window),严格模式中('use strict'),this为undefined
var obj = {
aa:'obj___aa',
b(fn){
fn()
}
}
function c(){
console.log(this.aa)
}
var aa = 'window___aa'
obj.b(c)
//打印window___aa,obj.b回调里的this指向window
3、使用call、apply、bind硬绑定this。
function foo(something) {
console.log( this.a, something );
return this.a + something;
}
var obj = { a:2 };
var bar = foo.bind( obj ); //bind返回了一个新的函数,这个函数指定了this指向obj
var b = bar( 3 ); // 2 3
4、使用new 调用构造函数创建对象时this指向创建的新对象
- 创建(或者说构造)一个全新的对象。
- 这个新对象会被执行 [[ 原型 ]] 连接。
- 这个新对象会绑定到函数调用的 this。
- 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。
- 函数是否在 new 中调用(new 绑定)?如果是的话 this 绑定的是新创建的对象。var bar = new foo()
- 函数是否通过 call、apply(显式绑定)或者硬绑定调用?如果是的话,this 绑定的是指定的对象。var bar = foo.call(obj2)
- 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上下文对象。var bar = obj1.foo()
- 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined,否则绑定到全局对象。var bar = foo()
ES6中的this:
箭头函数不会使用以上四种规则,而是根据词法作用域来决定this,具体来说,箭头函数会继承外层函数调用的 this 绑定(无论this绑定是什么),即继承父级的this,这个父级是什么意思呢?
注意:this一旦被捕获,就不再发生变化,任何方法都改变不了其指向,如 call() , bind() , apply()
先来理解执行上下文,具体请看执行上下文和作用域。
在JS中,调用函数时会创建一个“上下文对象”,调用函数内部的函数时,它与父级以及祖先级的上下文对象形成了执行上下文栈,而这个父级就是指箭头函数所在执行上下文栈上的上一个“上下文对象”,有点绕口,通过一个例子来说明:
TIPS:关于作用域请查看js之作用域和内存问题
var a=100;
var b = {
a:1000,
b:{
a:1,
c:{
a:22,
getA:()=>{
console.log(this.a);
}
}
}
}
执行b.b.c.getA();
最后执行的结果是100,为什么呢,因为执行getA时,作用域链中的第一个对象是getA函数本身的上下文对象,上一层对象就是顶层的window对象的上下文对象,它的this是指向window的。
再来看一个例子:
var a=100;
var b = {
a:1000,
b:{
a:1,
c:{
a:22,
getA:()=>{
console.log(this.a);
}
},
d:function(){
return {
getA:()=>{
console.log(this.a);
}
}
}
}
}
执行b.b.d().getA();
最后结果为1。
此时的作用域链为getA -> d -> window,getA为箭头函数,因此它的this指向的就是作用域链中的d函数,而d函数中的this指向的是b.b对象,因此this.a就是b.b.a,所以结果为1
箭头函数与普通函数的区别详解