Scope (1) - "这"是啥
白鹤亮翅
在 JavaScript 中,对象的方法访问自身内部的属性,看起来顺理成章:
> module = { x: 100, getX: function() { return this.x; } }
{ x: 100, getX: [Function: getX] }
> module.getX();
100
设全局变量的时候,x 和 this.x 也是互通的:
> x = 10
10
> this.x
10
> this.x = 1
1
> x
1
当场打脸
只要把这个方法提取出来赋给另一个变量,或者当作普通回调传递:
> getX2 = module.getX;
[Function: getX]
同样一个函数,执行结果却完全翻车:
> getX2();
1
见招拆招
getX2() 虽然和 module.getX() 指向同一个函数体,但普通函数内部的 this 并不由定义位置决定,而是取决于被调用的方式(谁在调用它):
- 执行
module.getX()时,调用者是module,所以this指向该对象; - 执行
getX2()时属于独立函数调用,其this指向全局对象(在非严格模式下是global或window,严格模式下则是undefined)。
为了锁死预期的作用域,可以使用 bind() 绑定宿主对象:
> getX3 = getX2.bind(module);
[Function: bound getX]
> getX3();
100
在现代前端开发中,也可以使用 ES6 箭头函数(lexical this)或者类字段方法来避免 this 丢失。