c lambda表达式 select 改变字段名称_JS 中 lambda 表达式中的 this 到底如何理解

bdbed2f693f37f30df3a22c04ad92e50.png

本文缘起于 箭头函数中this的指向,《ECMAScript6入门》勘误 ,本是此文下的两则评论。无奈作者删评关评,遂为此写一文。

原文作者通过各种情况的试探,得出一个结论“箭头函数中的this指向箭头函数定义时所在作用域中的this”。这种说法其实不算错,但和其他类似讨论的文章一样,将箭头函数中的 this 作为一个特殊的规则去记忆,并没有深入原理,于是将结论复杂化了。然而,lambda 表达式中 this 的设计是很符合逻辑的,理解的 lambda 的意义,就明白了为什么会这样,并不需要这种死记硬背。

词法作用域和动态作用域

在讨论 this 的指向这个问题的时候,本质上是对作用域的讨论。于是乎,首先需要明晰词法作用域和动态作用域这两个概念。

let 

问,两次打印分别输出什么。答,均是 1 。明白了这个问题就明白了词法作用域。

函数 foo,定义于全局,在全局执行了一次,在函数 bar 内部执行了一次。执行 foo 的时候,访问了 a 这个变量,先会在函数内部查找,但 foo 内部并没有声明 a ,于是在定义的位置向上查找。逐次类推,直到全局,否则报错。foo 定义于全局,于是乎返回了全局变量 a 的值。至于第二次在 bar 内部执行的时候,由于规则是在定义处向上查找,bar 内的局部变量 a 对于 foo 而言并没有什么影响。

对于词法作用域而言,一旦函数定义,所有变量都是确定的,不会因执行的位置/方式而改变。但是当访问 this 的时候,情况却大不一样了。

调用一个函数有四个方式:

function 

在这四个方式下,this 的指向均不同。以函数方式调用,this 指向 window;以构造函数的方式调用,this 指向所构造的实例对象;以对象方法的方式调用,this 指向其所在的对象;通过它们的 apply/call 方法间接调用,this 的指向取决于传入的参数。而这就是 JavaScript 中的动态作用域。

关于 lambda 表达式

lambda 表达式相对于函数,其实主要拥有两个特征。其一,能捕获外部变量;其二,能作为值传递。在 JS 中,对于一般的函数其实拥有这两个特征。函数的词法作用域保证了函数可以进行捕获外部变量,而函数是一个对象则让函数可以作为值进行传递。但在其他的语言中或许并不是这样,所以有一种论调就是在 js 中 lambda 表达式其实就是一个语法糖罢了,没什么意义。

慢着,在 JS 中能真的捕获所有的外部变量吗?似乎并不是这样,首先 js 中任何一个函数都有一个固定的变量 arguments 来表示这个函数的入参,次之除了词法作用域外还存在动态作用域 ,于是 this 这个值也没办法捕获了。

JS 中为了让函数更为符合 lambda 表达式的定义,于是去掉了其中的动态作用域以及 arguments。于是有了如今 lambda 表达式的设计,当访问 this/arguments 的时候,会根据词法作用域的规则去查找——“在定义的位置向上查找,逐次类推,直到全局,否则报错”。

总而言之

很多人通过各种情况试探出的拗口结论——“箭头函数中的this指向箭头函数定义时所在作用域中的this”,本是管中窥豹。将 lambda 表达式中的 this 的指向作为 this 又一一种特殊情况死记硬背的行为可以休矣。 lambda 表达式中的 this 之所以如此表现如此仅仅只是因为 lambda 表达式中不存在动态作用域而套用了词法作用域罢了。当调试一个 lambda 表达式的时候,只要知道出现 this 跟一般的变量/常量标识符的查找的方式是一样的就行了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值