ES6的this

MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this

js的function关键词定义函数体内的this指向在定义的时候是不确定的,只有在定义的函数被调用的时候才会赋予里面的this一个指向,而这this指向的是直接调用者。

什么是直接调用者呢?比如我要调用a对象的b方法,那么这个时候b的直接调用者就是a,b内的this指向就是a。

又比如我要调用a对象的b属性的c方法,那么c的直接调用者就是b。a通过b间接调用了c方法。

算了,这么写着太乱了,直接举例子:

1
2
3
4
function x() {
return this;
}
x(); //window

直接使用函数的话则会指向全局对象,浏览器环境下是window。在node环境下则是global。

而如果在strict模式下则会指向undefined

1
2
3
4
5
6
let a = {
b : function() {
return this;
}
}
a.b(); //返回的是a对象
1
2
3
4
5
6
7
8
let a = {
b : {
c : function() {
return this;
}
}
}
a.b.c(); //返回的是b对象。
1
2
3
4
5
6
7
let a = {
b : function() {
return this;
}
}
let c = a.b;
c(); //返回的是全局对象 window/global

最后一个虽然调用的函数还是定义在a里面的b,但是直接调用者其实还是全局对象,let c = a.b中把定义的函数赋值给了c。

1
2
3
setTimeout(function(){
console.log(this);
},100); //window
1
2
3
4
5
6
function x(){
setTimeout(function(){
console.log(this);
},100);
}
x(); //window
1
2
3
4
5
6
7
8
let x = {
y : function() {
setTimeout(function(){
console.log(this);
},100);
}
}
x.y(); //window

这里可以看出在setTimeout内使用function定义的闭包实际上都会由window来直接调用。

然后还有一种情况就是new。

js中通过function定义的方法其实都是一个Function的实例。

比如:

1
2
3
4
5
6
function Fn(){
this.x = 'aaa';
}

let x = new Fn();
console.log(x); //Fn {x: "aaa"}

可以看到在Fn中this的指向变成了他自自己,所以在尝试输出x的过程中有一个属性叫x,这个x是在Fn()内的this.x = 'aaa'定义的。

实际上在let x = new Fn()的过程中,new操作符改变了Fn()中this的指向,将他指向了新创建的对象。

1
2
3
4
5
6
7
8
9
function Fn(){
this.x = 'aaa';
return {
y : 'bbb'
}
}

let x = new Fn();
console.log(x); //{y: "bbb"}
1
2
3
4
5
6
7
function Fn(){
this.x = 'aaa';
return 'bbb';
}

let x = new Fn();
console.log(x); //Fn {x: "aaa"}

至于这是为什么的话。。不太清楚(x,可能跟new有关,可能要另外写一篇。

唔。。看了一下官方的文档:

在箭头函数出现之前,每一个新函数根据它是被如何调用的来定义这个函数的this值:

  • 如果是该函数是一个构造函数,this指针指向一个新的对象
  • 在严格模式下的函数调用下,this指向undefined
  • 如果是该函数是一个对象的方法,则它的this指针指向这个对象
  • 等等

然后function部分写完了就是箭头函数了,算是一种特殊的匿名函数。语法:

1
2
3
(parm) => {
//do something
}

那么在匿名函数里面,this指向的是哪里呢?

箭头函数中,this与封闭词法环境的this保持一致。在全局代码中,它将被设置为全局对象

什么叫封闭词法环境呢?我不明白

我的理解就是箭头函数的this被设置为他被创建时的环境。他被创建的环境是y内的z。而z的this指向y,所以它的this也是y。

比如下面的代码。我的箭头函数写在setTimeout()内,然后他的上一层对象应该是x.y

1
2
3
4
5
6
7
8
9
10
let x = {
y : {
z : function() {
setTimeout(() => {
console.log(this);
},100);
}
}
}
x.y.z() //返回的是y对象。

说实话,还是有些不太明白,这篇文章还需要经过修改(x