1.3 this 关键字
this
是一个标识符,会被赋值以指向”当前“对象。目的是为了让你能从语言层面使用这个特性辅助编程,而不需要深入到语法层。不过,这个 当前 对象指向哪里,就没那么好判断了,大侠接坑。
this
不会绑定到...
this
会被绑定到…
总而言之,this
绑定的判定法则为:
- 90%的情况下,
this
会被绑定至函数调用所在的对象上:函数调用 -> 函数调用标识.
-> 其前的对象 - 仅与函数调用时刻有关,而非函数定义或声明等无关。详见完整规则5
更加完整的规则为:
- 全局调用(
fn()
):默认绑定到全局对象(浏览器下是window
,NodeJS 下是global
) - 作为对象的属性/方法(
object.fn()
):这种最简单直接、符合直觉,就是绑定到该对象object
上 - 不是对象的属性,但要调用该函数(
fn.call(onAnother, {})
):这种也好理解,被调用的函数不是作为对象的属性,没有一个指向对象的this
,因此手动指定其绑定到另一个对象onAnother
上 - 规则2与规则3同时出现(
object.fn.call(onAnother, {})
):规则3优先。即此时依然绑定到onAnother
上 setTimeout(fn, 1000ms)
:答案是,与setTimeout
实现方式有关。因为fn
中的this
绑定到哪里,完全取决于其被调用时是以什么方式被调用,而这是取决于setTimeout
方法的实现的。待会细论- 不在函数之中被使用(
console.log(this)
):答案也是取决于 JS 引擎的实现。本来按照词法作用域规则,JS 引擎会一直向上查找this
这个变量,查不到就返回ReferenceError
。但坑就坑在,由于历史原因,有些 JS 引擎会默认帮你绑定到全局对象上去(比如 Chrome 56.0+ 的 V8 5.6+ 引擎),好在现代的引擎已经修正了这个问题(比如 NodeJS 6.9.4 用的 V8 5.1+引擎)。但更坑就坑在,你不知道哪些引擎已经修复了,你的容器用的是哪个引擎。该特性最好少用
规则5中提出了一个重要的问题:回调。传入给回调的函数,你不知道对方会如何调用,因此必须限制 this 关键字的使用,以使代码尽可能少因为对方调用方式而受影响。从你这端进行对象调用是没有用的,因为 this 的绑定仅与运行时被调用的地方有关系。比如:
function fn() { ... } var object = {}; object.method = fn // makes no difference setTimeout(fn, 1000) setTimeout(object.method, 1000)
最佳实践
需要注意,有些令人困惑的特性可以使用 strict mode 禁用,或已在 ES6 中被修复。需要学习
- http://stackoverflow.com/a/16227099/4993983
- inner function cannot access this
- ES6 to the rescue
- MDN: Operator this
- 中文世界似乎只有这篇文章提到了
this
关键字的最佳实践:http://blog.csdn.net/fudesign2008/article/details/37875471 。不过我觉得并不好,也过于简单,到了产出的时候了。主要从可读性(第一直觉)与理解层面(不需要深入到语法层面来理解)来衡量这个最佳实践
- What are closures
- Why we need it/How it solves specific problems
- Any scenarios of using
- Other programming language implementation and difference?
- 绑定规则的官方文档?
- JavaScript: The good parts
- this 调用规则的流程图
参考资料
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论