ES6箭头函数this和普通函数中的this

480 阅读3分钟

原文链接:www.jianshu.com/p/c1ee12a32…

常见的window属性和方法有alter,document,parseInt,setTimeout,setInterval,localtion等等,这些在默认的情况下是省略了window前缀的。(window.alter = alter),所以下文提到箭头函数解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性),包括setTimeout和setInterval中使用this所造成的问题。

以下都是在非严格模式下讨论
1.普通函数中的this
在JavaScript中,this是在函数执行过程中自动生成的一个内部对象,指的就是当前对象。
js的函数可以多层嵌套,如果内层的想要获得外层的this,可以定义一个变量储存起来
var _this=this
在全局函数中,比如匿名函数,this指向的是window。
例子:

var name=" the window";
var obj = {
    name:'my obj',
    getNameFun:function(){
        return function(){
            return this.name;
        }
    }
}
console.log(obj.getNameFun()());// the window

原因是,匿名函数的执行环境是全局的,而且this只在函数内部起作用。此时的this.name在匿名函数中找不到,所以就从全局中找,找到后打印出来。

上面的例子改写一下

var name=" the window";
var obj = {
    name:'my obj',
    getNameFun:function(){
        var _this=this
        return function(){
            return _this.name;
        }
    }
}
console.log(obj.getNameFun()());//my obj

在getNameFun内将this赋给_this,此时的_this指向的是挂载(调用)的对象,即为obj,在匿名函数中调用_this.name会在obj上查找相应的数据,就不会在全局上查找

函数的执行对象放在window

function test(){
    console.log(this);
}
test();//window

问题:为啥是window,因为没变量声明?

关于setTimeout和setInterval的this指向问题

var obj = {
  func:function(){
    console.log(this);
  },
  say:function(){
    var that = this;
    setTimeout(function(){
      console.log(that)
    });
  }
}
obj.func();//obj
obj.say();//obj

把 var that = this;去掉

var obj = {
  func:function(){
    console.log(this);
  },
  say:function(){
    setTimeout(function(){
      console.log(that)
    });
  }
}
obj.func();//obj
obj.say();//window

问题: setTimeout里执行的函数为啥是window,因为setTimeout就是window下的方法
例子:

window.val = 1;
var obj = {
  val:2,
  dbl:function(){
    this.val*=2;
    val*=2;
    console.log(this.val);
    console.log(val);
  }
}
obj.dbl();//4 2
var func = obj.dbl;
func();//8 8

执行obj.dbl()时,this.val的this指向obj内的val=2;val在obj内没有定义所以从全局上找val=1,因此运算结果为4 2
func的执行对象是window,我们可以此时全局的val已经等于4了,在经过this.val

=2,val
=2的运算,打印的结果就是8 8。
问题:为啥执行func,全局的val等于4,不是2?

2.ES6箭头函数this

箭头函数的this定义:箭头函数的this是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this就继承了定义函数的对象。
所以,这会很好的解决匿名函数和setTimeout和setInterval的this指向问题。不用再去给其变量存储this。

var obj = {
  func:function(){
    console.log(this);
  },
  say:function(){
    setTimeout(()=>{
      console.log(this)
    });
  }
}
obj.func();//obj
obj.say();//obj
var a=1;
function test(){
    console.log(this.a);
    console.log(this);
    this.a=2;
    return ()=>{console.log(this.a);console.log(this);}
}
var x=new test()();
//undefined
//test {}
//2
//test {a: 2}

注:new test()(),第一个括号是返回匿名函数,第二个括号是执行返回的匿名函数