《趣说前端》— 第一篇

前言

关于 this 指向问题,网上的资料很多,面试问的也很多,似懂非懂的人也很多。

有人觉得女生的心思很难猜,也就有人觉得 this 的指向问题比女生的心思更难猜。

  • 女生的心思其实很简单 —— 希望不猥琐的你用心去关注她(和帅没有很大关系,当然帅加分)。

  • this 的指向问题也不难 —— 谁调用就指向谁。

到底谁是调用者

结论先行:this 的指向是谁调用就指向谁;即调用之前,this 还不知其指向。

讨论谁是调用者之前先说 this 的作用:

this 是函数内部两个特殊对象之一,拥有这个对象可以改变显式传递的弊端,即可将函数定义的更加简洁和易于复用。

接下来重点讨论谁是调用者

var name = '小生方勤';function consoleName() {    console.log(this.name);}var test = {  name: '方小勤',  method: function() {    consoleName();  }};test.method();

上面这个笔试题相信你已经有了答案,现在可以带着你刚才的思考切入下面的解释。

四种情况的调用

想知道 this 指向就需要找到调用者。有人认为调用者并不好确定,其实大体只有四种情况,我一一介绍。

  1. 直接调用的默认绑定, this 指向一定是全局对象(浏览器的话是 window)。在严格模式下其值会是 undefined。

  2. 对象调用的隐式绑定, this 指向就是这个调用的对象。

  3. call()/apply() 方式的显式绑定, this 指向传入的对象。

  4. new 方式的绑定规则, this 指向这个构造出的新对象。

第一种 & 第二种:

let name = '小生方勤';function consoleName() {    console.log(this.name);}let test = {  name: '方小勤',  method: function() {    console.log(this.name);   // 方小勤    consoleName();            // 小生方勤  }};test.method();  

开头题目的答案就在这里。

虽然 test.method() 的调用方式使 method 内部使用的 this 会指向 test,但实际调用的是 - 直接调用 consoleName();所以 this 的指向还是全局对象 window。

所以输出的是:

通过这个例子,你对第一种和第二种的绑定方式应该就懂了。

第三种:

let name = '小生方勤';let test = {  name: '方小勤',  method: function() {    console.log(this.name);  }};test.method.apply(window);  // '小生方勤'

隐式绑定和显式绑定一起使用的时候,显式绑定的优先级更高。

第四种:

function consoleName(name) {    this.name = name;}let useNname = new consoleName('小生方勤');console.log(useNname.name)      // 小生方勤

通过这个例子想必你对 new 方式中 this 的指向问题也明白了,即构造函数(consoleName)中的 this 会绑定到实例(useNname)上。

优先级

关于优先级我画了一张图直观的来说明这个问题:

箭头函数补充

箭头函数比较特殊,不受上面四条规则的约束。箭头函数的 this 根据外层函数确定。

而且箭头函数的 this 一旦被绑定,就无法改变。

思考题

以下代码输出什么,原因是什么?欢迎评论区留言。

function consoleName() {    return (name) => {        console.log(this.name);    }}let testOne = {  name: '小生方勤',};let testTwo = {  name: '方小勤',};let text = consoleName.call( testOne );text.call( testTwo );

参考

  1. 《JavaScript 高级程序设计》

  2. 《你不知道的 JavaScript》上

NOT THE END

该系列首发于同名公众号【小生方勤】,扫码关注即可订阅(可进交流群)。

彩蛋:你若发现这个系列文章有错别字,每个字 5 元红包的有偿纠正费(只限最早告知我的读者[微信号:wqhhsd])。

©著作权归作者所有:来自51CTO博客作者mb5ff592736e0cf的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 动画:浅谈后台 MVC 模型与 MVVM 双向绑定模型
  2. 数据结构与算法——最小生成树
  3. PHP中如何形成static::与new static()的静态绑定
  4. 详解PHP面向对象之后期静态绑定
  5. jQuery 事件绑定方法(bind hover toggle live.... )、删除事件方法
  6. JQuery UI datepicker在绑定到类时不起作用
  7. jQuery中的bind绑定事件与文本框改变事件的临时解决方法
  8. jQuery+EasyUI实现treegrid/datagride所绑定列只能够输入数字,且
  9. 绑定和解除相同javascript函数的目的是什么?

随机推荐

  1. android listview优化几种写法 详细出处
  2. 使用Android-UIL,如何停止下载?
  3. ViewPager的滑动禁止和滑动启动
  4. android发送通知及更新通知
  5. PacketReader 如何实现smack数据监听机制
  6. 第一个Android程序
  7. android中Appwidget的使用
  8. 在谷歌中映射V2…fragment.getMap()返回n
  9. 不同Android版本设备正确获取屏幕分辨率
  10. Android开发——联系人中几种常见的mimet