0
点赞
收藏
分享

微信扫一扫

#yyds干货盘点#ES6的this指向哪里

this小测试

下面的这段代码,this指向哪里?

var obj = {
a: function() {
console.log(this);
}
}

var b = obj.a;
b();

结果是this指向window。

一般的,​this​指向函数运行(调用)时所在的执行环境【《JavaScript高级程序设计》4.2节执行环境及作用域】的(变量)对象(简单地,this​指向函数的调用者)

解析

var b = obj.a;    // ==>相当于
var b = function() {
console.log(this);
}

函数调用时(​b();​)其所在的执行环境是全局环境,所以​this​指向全局变量对象​window​

ES6箭头函数

例1【阮一峰《ECMAScript 6 入门》-7.函数的扩展:箭头函数】

我将阮老师的例子代码修改了一下:
(普通函数)

function foo() {
console.log("id1:", this.id);
console.log("this1:", this);
setTimeout(function() {
console.log("id2:", this.id);
console.log("this2:", this);
}, 0);
}

var id = 21;

foo();

// Chrome
// id1: 21
// this1: window
// id2: 21
// this2: window

foo.call({id: 42});

// Chrome
// id1: 42
// this1: {id: 42}
// id2: 21
// this2: window

注意:超时调用(​​setTimeout​​​回调)的代码都是在全局作用域环境中执行的,因此(​​setTimeout​​回调)函数中​​this​​的值在非严格模式下指向​​window​​对象,在严格模式下是​​undefined​​​

例如

var obj = {
console.log(this);
setTimeout(function() {
console.log(this);
}, 0);
}

obj.a();

// Chrome
// {a: f}
// window

我们使用​​foo​​​函数的​​call​​​方法改变了​​foo​​​函数调用时函数体内​​this​​​的指向(​​{id: 42}​​​这个对象),但​​setTimeout​​​回调函数中的this依旧指向​​window​​对象(因为在全局环境中运行)。

接下来再将例1改写一下,将​​foo​​函数中的​​setTimeout​​回调函数改成箭头函数的形式:

例2
(箭头函数)

function foo() {
console.log("id1:", this.id);
console.log("this1:", this);
setTimeout(() => {
console.log("id2:", this.id);
console.log("this2:", this);
}, 0);
}

var id = 21;

foo();

// Chrome
// id1: 21
// this1: window
// id2: 21
// this2: window

foo.call({id: 42});

// Chrome
// id1: 42
// this1: {id: 42}
// id2: 42
// this2: {id: 42}

​foo();​​​的输出结果没有变化,但​​foo.call({id: 42});​​的输出结果改变了。

到底发生了什么?

在这里直接给出结论:
箭头函数根本没有自己的​​this​​,导致内部的​​this​​指向了外层代码的​​this​​,这个指向在定义时就已经确定而不会在调用时指向其执行环境的(变量)对象

注意:因为箭头函数内部的​​this​​​是指向外层代码块的​​this​​(最近的​​this​​,例2中的foo函数)的,所以我们可以通过改变外层代码块的​​this​​的指向从而改变箭头函数中​​this​​的指向(例2中使用了​​foo​​函数的​​call​​方法)。

重新解释例2

因为箭头函数(​​setTimeout​​回调)没有自己的​​this​​,导致其内部的​​this​​引用了外层代码块的​​this​​,即​​foo​​函数的​​this​​,

(要注意:在定义阶段(调用函数前),​​foo​​​函数的​​this​​的值并不确定【《JavaScript高级程序设计》第三版5.5.4函数内部属性】,但箭头函数的​​this​​自定义阶段开始就指向​​foo​​函数的​​this​​了)

又因为使用​​call​​方法改变了​​foo​​函数运行(调用)时其函数体内​​this​​的指向(重新指向对象​​{id: 42}​​)从而使箭头函数中​​this​​的指向发生变化,最后输出例2所示结果。


举报

相关推荐

0 条评论