javascript - Kyle Simpson 的 YDKJS 中的动态范围和 `this`

标签 javascript scope this dynamic-scope

在他的(伟大的)系列书籍中“You don't know JS" ,凯尔·辛普森 (Kyle Simpson) 指出动态作用域和这种机制是“近亲”,他还说:

"the this mechanism is kind of like dynamic scope." (YDKJS, Scope and Closure, Appendix A)

是什么阻止他说这个简单明了的动态作用域?

此外,在《 this & Object Prototypes 》一书中,也是 YDKJS 系列的一部分,据我所知,Kyle 在讨论this< 时并没有提到一次动态作用域 正在工作,所以我有点惊讶为什么他决定不进一步进行类比......有人知道为什么吗? 谢谢

最佳答案

我 claim 的原因this只是“有点像”动态作用域,实际上并不是动态作用域,它基于以下两个观察结果:

  1. 使用对象引用 ( this.foo = 1 ) 显式访问“范围上下文”的美感不同于通过词法变量引用 ( foo = 1 ) 隐式访问它。充其量,这使得两个系统的“范围”是平行的,而不是相同的。但实际情况与表面看起来有更多不同!

  2. 但更重要的是,动态作用域传统上被定义为基于调用堆栈的作用域链。也就是说,在动态作用域中,要按顺序查询哪些“作用域上下文”的决定正是当前的函数调用堆栈。但是this本身并不基于调用堆栈,而只是基于堆栈中最近调用的方式。

    考虑这种情况:foo()来电 bar() , bar()来电 baz() ,以及 baz()引用x baz() 中 undefined variable .

    • 在词法范围内,查找将是 baz() ,那么无论 baz() 的外部范围是什么是,等等。 bar()foo()根本不会被查询,除非它们碰巧是 baz() 的词法周围范围。 .

    • 在动态范围内,调用堆栈 foo() -> bar() -> baz() 作用域链,所以 baz()咨询后,则bar() ,然后foo() ,无论这 3 个函数按词法存在于代码库中的哪个位置。

    • 现在,考虑相同的场景,但是 this.xbaz()里面的引用。调用堆栈foo() -> bar() -> baz()与解决 this.x 并不特别相关。相反,唯一重要的是如何baz()被调用。如果调用站点是 baz() ,“默认绑定(bind)”规则适用。如果是this.baz() ,“隐式绑定(bind)”规则适用。如果是baz.call(..) ,“显式绑定(bind)”规则适用。如果是new baz() ,适用“新绑定(bind)”规则。就是这样。

    实际上,这不是唯一的事情,这只是做出的第一个决定。一旦确定了哪个对象(又名范围上下文对象)this指出,现在唯一重要的是该对象的原型(prototype)链,因为这是将按照原型(prototype)链链接的顺序查询的“范围”。

<小时/>

摘要:

  • 在词法作用域中,定义函数的位置是唯一确定使用哪些上下文以及以什么顺序来解析变量引用的因素。

  • 在动态作用域中,调用自的函数是唯一确定使用哪些上下文以及以什么顺序解析变量引用的因素。

  • this基于上下文,函数的定义位置和调用位置都不相关。因此,this既不是词法作用域也不是动态作用域。

    这里唯一重要的是如何调用调用堆栈(堆栈顶部)中的当前函数。嗯,这是确定从哪个作用域链开始查找的唯一重要因素。但是,一旦确定了该对象,现在就由该对象的原型(prototype)链完全定义范围解析。

关于javascript - Kyle Simpson 的 YDKJS 中的动态范围和 `this`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44748400/

相关文章:

javascript - redux-actions Typescript 声明一个 Action

javascript - JS如何访问函数外的变量

javascript - 为什么我不能使用 $(this) jQuery 选择器

javascript - 使用 jQuery 确定用户是否已将完整 URL 复制并粘贴到浏览器中?

javascript - 带功能的 ionic 自动完成取消标签

javascript - 如何从 ui bootstrap 的 uibModal.open 设置组件输出绑定(bind)

c++ - 在模板类函数定义中使用 "this"指针 -- 表达式必须具有 (pointer-to-) 函数类型

ruby - 范围和 'self' 关键字

javascript - 需要解释 javascript 中的范围问题

javascript - JQuery:在 .each() 循环中使用 "this"