ES6 添加了 let 和 const 声明,使用 var 声明的变量会成为全局对象的属性,但是使用 let 和 const 声明的变量不会成为全局对象的属性,而会成为变量对象的属性,与全局对象“平级”。因此,使用 ES6 的标准,全局上下文的变量对象就是全局对象;使用 ES6 之前的标准,全局上下文的变量对象包含全局对象和使用 let 和 const 声明的变量,全局对象是全局上下文的变量对象的子集。
var a = 1; var obj = { a: 2, b: function () { console.log(this.a); }, }; var t = obj.b;
obj.b(); // t(); //
// obj 对象的 b 属性存储的是对该匿名函数的一个引用,可以理解为一个指针 // 当赋值给 t 时并没有单独开辟内存空间存储函数,而是让 t 存储一个指针,该指针指向这个函数 // 相当于执行了下面的伪代码
var a = 1; functionfun() { returnthis.a; } // 此函数存储在堆中 var obj = { a: 2, b: fun, // b 指向 fun 函数 }; var t = fun; // 此时的 t 就是一个指向 fun 函数的指针,调用 t,相当于直接调用 fun
console.log(t()); //
1 2 3 4 5 6 7 8 9 10 11 12 13 14
var a = 0; functionfun() { console.log(this.a); } let obj2 = { a: 2, fun: fun, }; let obj1 = { a: 1, fun: obj2, };
obj1.fun.fun(); //
使用 call 或 apply 被调用
当函数使用 call 或 apply 被调用时,由其传入的参数作为 this 值。
1 2 3 4 5 6 7 8 9 10 11 12 13
var a = 0; functionfun() { console.log(this.a); } functionb() { let a = 7; } let c = { a: 9, };
fun.call(b); // fun.call(c); //
作为构造函数被调用
当函数作为构造函数被调用时,那么其中的 this 就代表它即将 new 出来的对象。
箭头函数
箭头函数会捕获其所在上下文的 this 值作为自己的 this 值,其 this 由其所在上下文的 this 所决定。对箭头函数使用 apply 或 call 方法只是传入参数,改变不了 this。
1 2 3 4 5 6
var a = 1; var obj = { a: 2 }; var fun = () =>console.log(this.a);
fun(); // fun.call(obj); //
1 2 3 4 5 6 7 8 9
var a = 1; var obj = { a: 2, b: () => { console.log(this.a); }, };
obj.b(); //
1 2 3 4 5 6 7 8 9 10
var a = 1; var obj = { a: 2 }; functionfun() { var a = 3; let f = () =>console.log(this.a); f(); }
fun(); // fun.call(obj); //
1 2 3 4 5 6 7 8 9 10 11 12
var a = 1; var obj = { a: 2 }; functionfun() { var a = 3; functionf() { console.log(this.a); } f(); }
fun(); // fun.call(obj); //
总结
函数的 color 变量值与 其所在的上下文的作用域链 有关
箭头函数的 this.color 值与 其所在的上下文的 this 有关
标准函数的 this.color 值与 把其当成方法调用的对象 有关
注意:全局上下文的变量对象包含着全局对象和使用 let 和 const 声明的变量和对象。
练习:
1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var color = "red"; // var 声明的变量是函数作用域 const o = { color: "blue", a: function () { console.log(color); // o 只是全局上下文的一个变量,不是块级作用域 console.log(this.color); // 函数作为对象的方法被调用,this 指向调用它的对象 }, b: () => { console.log(color); // o 只是全局上下文的一个变量,不是块级作用域 console.log(this.color); // 此箭头函数被定义在全局上下文 }, };
o.a(); // o.b(); //
2.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
let color = "red"; // let 声明不会成为全局变量的属性 const o = { color: "blue", a: function () { console.log(color); // o 只是全局上下文的一个变量,不是块级作用域 console.log(this.color); // 函数作为对象的方法被调用,this 指向调用它的对象 }, b: () => { console.log(color); // o 只是全局上下文的一个变量,不是块级作用域 console.log(this.color); // 全局变量没有 color 属性 }, };
o.a(); // o.b(); //
3.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 可略过 var color = "red"; // var 声明的变量是函数作用域 { let color = "blue"; // let 声明不会成为全局变量的属性 functiona() { console.log(color); console.log(this.color); } let b = () => { console.log(color); console.log(this.color); };
a(); // b(); // }
4.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 可略过 var color = "red"; // var 声明的变量是函数作用域 { var color = "blue"; // var 声明的变量是函数作用域,会覆盖 functiona() { console.log(color); console.log(this.color); } let b = () => { console.log(color); console.log(this.color); };
a(); // b(); // }
5.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 可略过 var color = "red"; // var 声明的变量是函数作用域 { let color = "blue"; functiona() { console.log(color); console.log(this.color); } let b = () => { console.log(color); console.log(this.color); };
a(); // b(); // }
6.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// 可略过 var color = "red"; // var 声明的变量是函数作用域 { let color = "blue"; functiona() { let color = "black"; console.log(color); console.log(this.color); } let b = () => { let color = "black"; console.log(color); console.log(this.color); };
a(); // b(); // }
7.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// 可略过 let color = "red"; // let 声明不会成为全局变量的属性 { let color = "blue"; functiona() { let color = "black"; console.log(color); console.log(this.color); // 全局变量没有 color 属性 } let b = () => { let color = "black"; console.log(color); console.log(this.color); };
a(); // b(); // }
8.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
var color = "red"; // var 声明的变量是函数作用域 const o = { color: "blue", }; functiona() { console.log(color); // o 只是全局上下文的一个变量,不是块级作用域 console.log(this.color); // 函数作为对象的方法被调用,this 指向调用它的对象 } const b = () => { console.log(color); // o 只是全局上下文的一个变量,不是块级作用域 console.log(this.color); }; o.a = a; o.b = b;