首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

ES6 参数默认值引起的中间作用域

(注意这里的 default value parameter initializers exist,也就是说声明了默认参数值不一定会产生这个作用域,只有初始化了、确实用到了这个默认值,作用域才会产生。)...第二个需要明确的地方是:上面代码中,存在全局作用域、参数作用域、函数作用域,并且这三者的关系如图: image.png 明确这两点之后开始来分析结果。...对于 y 函数,x 不是在其体内声明的,所以这个 x 对它来说是自由变量,根据作用域链查找的规则,此时会查找到参数作用域中的 x ,并赋值为 2。...如果在同一作用域中用 let 重复声明一个变量,则确实会报错,但是根据上面的分析,这里其实是不同的两个作用域,按道理说不应该报错。为什么会报错呢?...网上有很多文章讲到参数默认值,但是提及参数作用域的文章数量很有限,所以最后也基本是依靠知乎上两位老师的回答以及自己的琢磨得出了结论。

53430

JavaScript作用域深度剖析:动态作用域

• 如果 JavaScript 具有动态作用域,理论上,上述代码 foo() 中的 a 输出 3; 因为 foo() 是在 bar() 中调用的, • 为什么会这样?...• 因为当 foo() 无法找到 a 的变量引用是,会顺着调用栈在调用 foo() 的地方查找 a,而不是在嵌套的词法作用域链中向上查找。...由于 foo() 是在 bar() 中调用的,引擎会检查 bar() 的作用域,并找到值为 3 的变量 a。 • 是不是很奇怪?...• 但这其实是因为你可能只写过基于词法作用域的代码,因此对动态作用域感到陌生。如果你只用基于动态作用域的语言写过代码,就会觉得很自然的,而词法作用域看上去才怪怪的。...• 作用域链是基于调用栈的,而不是代码中的作用域嵌套的 特殊字符描述 •问题标注 Q:(question) •答案标注 R:(result) •注意事项标准:A:(attention matters)

17010
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    小茶配音 | 吊打JavaScript之执行环境与作用域的区别与联系​

    作用域控制着变量和参数的可见性与生命周期。 块级作用域概念,任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。...作用域 作用域是指在程序中定义变量的区域,作用域规定了如何查找变量,对当前执行代码对变量的访问权限。 关于词法作用域和动态作用域 词法作用域就是静态作用域,而相对于词法作用域就是动态作用域。...词法作用域是函数的作用域在函数定义的时候决定的,而动态作用域是在函数调用的时候决定的。...每个环境都是可以向上搜作用域链的,但是任何环境都不能通过向下搜索作用域而进入另一个执行环境。 当我们在某个环境中需要读取而引用一个标识符代表某种特定含义的时候,必须通过搜索来确定该标识符。...标识符解析是沿着作用域链一级一级地搜索标识符的过程,从作用域链的前端开始,向后回溯,直到找到标识符为止,找不到,会导致错误发生。

    38620

    为什么编译原理被称为龙书?

    还有一个问题是声明的作用域(scope),如果能够通过阅读程序就能确定一个声明的作用域,那么这个语言就是静态作用域(static scope),或者说是 词法作用域(lexical scope)。...否则这个语言使用的是 动态作用域(dynamic scope)。动态作用域的指向对象是几个声明中的一个,并不惟一。...静态作用域和块结构 大多数编程语言都提供了作用域这么一个结构,比如 Java 中的 private,protected,public 等关键字的使用,提供了有效的作用域控制。...但是在 C 中,我们可以传递一个指针,使得变量的值能够被修改。 引用传递 在 引用传递(call-by-reference) 中,实际参数的地址作为相应的形式参数的值被传递给调用者。...在被调用者的代码中使用形式参数,实现方法是沿着这个指针找到调用者指明的内存位置。因此,改变实际参数相当于改变了形式参数。

    1.4K30

    深入理解JS作用域链与执行上下文3

    图片作用域链:其实,我们知道,JS 用的是 词法作用域 的。关于 其他作用域 不了解的童鞋,请移步到我的《谈谈 JavaScript 的作用域》,或者百度一下。...思考以下代码,并回顾 词法作用域,结合 [[Scope]] 属性思考,你就能理解 词法作用域 的原理,var testValue = 'outer';function foo() { console.log...在这里,找到 bar 函数作用域,另外有趣的是,Closure 就是闭包的意思 。...图片证明,全局作用域链是在 全局执行上下文初始化时 就已经确定的:我们来做一个有趣的实验,跟刚才,按照我描述的方法,你可以找到 [[Scope]] 属性。那这个属性是在什么时候被确定的呢???...我们知道,如果作用域链越深, 0 => 1 => 2 => ... => n,我们调用的是 全局变量,它永远在最后一个(这里是第 n 个),这样的查找到我们需要的变量会引发多大的性能问题?

    50020

    万字干货!详解JavaScript执行过程

    词法作用域 词法作用域就是指作用域是由代码中函数声明的位置来决定的,所以词法作用域是静态的作用域,通过它就能够预测代码在执行过程中如何查找标识符。...在ES6之前都没有块级作用域,ES6之后我们可以用let const来声明块级作用域,有这两个词法环境是为了实现块级作用域的同时不影响var变量声明和函数声明,具体如下: 首先在一个正在运行的执行上下文内...,作用域块中通过let声明的变量,会被存放在词法环境的一个单独的区域中,这个区域中的变量并不影响作用域块外面的变量,比如在作用域外面声明了变量b,在该作用域块内部也声明了变量b,当执行到作用域内部时,它们都是独立的存在...其实,在词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出,这就是词法环境的结构。...再接下来,当执行到作用域块中的console.log(a)这行代码时,就需要在词法环境和变量环境中查找变量a的值了,具体查找方式是:沿着词法环境的栈顶向下查询,如果在词法环境中的某个块中查找到了,就直接返回给

    1.1K40

    深入理解JS作用域链与执行上下文

    图片作用域链:其实,我们知道,JS 用的是 词法作用域 的。关于 其他作用域 不了解的童鞋,请移步到我的《谈谈 JavaScript 的作用域》,或者百度一下。...思考以下代码,并回顾 词法作用域,结合 [[Scope]] 属性思考,你就能理解 词法作用域 的原理,var testValue = 'outer';function foo() { console.log...在这里,找到 bar 函数作用域,另外有趣的是,Closure 就是闭包的意思 。...图片证明,全局作用域链是在 全局执行上下文初始化时 就已经确定的:我们来做一个有趣的实验,跟刚才,按照我描述的方法,你可以找到 [[Scope]] 属性。那这个属性是在什么时候被确定的呢???...我们知道,如果作用域链越深, 0 => 1 => 2 => ... => n,我们调用的是 全局变量,它永远在最后一个(这里是第 n 个),这样的查找到我们需要的变量会引发多大的性能问题?

    48840

    深入理解JS作用域链与执行上下文_2023-02-23

    作用域链: 其实,我们知道,JS 用的是 词法作用域 的。 关于 其他作用域 不了解的童鞋,请移步到我的《谈谈 JavaScript 的作用域》,或者百度一下。...思考以下代码,并回顾 词法作用域,结合 [[Scope]] 属性思考,你就能理解 词法作用域 的原理, var testValue = 'outer'; function foo() { console.log...在这里,找到 bar 函数作用域,另外有趣的是,Closure 就是闭包的意思 。...证明,全局作用域链是在 全局执行上下文初始化时 就已经确定的: 我们来做一个有趣的实验,跟刚才,按照我描述的方法,你可以找到 [[Scope]] 属性。 那这个属性是在什么时候被确定的呢???...我们知道,如果作用域链越深, 0 => 1 => 2 => ... => n,我们调用的是 全局变量,它永远在最后一个(这里是第 n 个),这样的查找到我们需要的变量会引发多大的性能问题?

    49420

    你不知道的JavaScrpit(上卷) 随记(一)

    找不到会抛出一个异常 LHS 与 RHS LHS: 变量出现在赋值操作的左侧(试图找到变量的容器本身) RHS: 变量出现在右侧(其实就是查询取到这个变量的源值) 为什么区分LHS和RHS很重要: 因为在变量还没声明时这两种查询的行为是不同的...词法作用域 词法作用域(其实就是静态作用域)是由你在写代码时将变量和块作用域写在哪里来决定的。 作用域会在查找到第一个匹配的标识符时停止,从最内层的向全局作用域查询,会有屏蔽效应。...欺骗词法: eval 通常用来执行动态创建的代码,如果包含声明类语句就可能会对词法作用域进行一定程度的修改(严格模式除外) new Function()的最后一个参数也可以是代码字符串 但是 都不提倡...再以o2为词法作用域,进行LHS查询, 没有找到向上查询也没有找到,所以创建了一个全局变量 */ 其实就是LHS引用,然后把2赋值给它。 实际是根据你传递给它的对象凭空创建了一个全新的词法作用域。...显然现在我们拥有更多词法作用域了,但是这样也不行。为什么呢?疑问作用域是空的,它要获取i最后还是会到全局中去拿。

    86141

    JavaScript之执行环境与作用域的区别与联系​

    作用域控制着变量和参数的可见性与生命周期。 块级作用域概念,任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。 ​ ? ​ ? ​...作用域 作用域是指在程序中定义变量的区域,作用域规定了如何查找变量,对当前执行代码对变量的访问权限。 关于词法作用域和动态作用域 词法作用域就是静态作用域,而相对于词法作用域就是动态作用域。...词法作用域是函数的作用域在函数定义的时候决定的,而动态作用域是在函数调用的时候决定的。...每个环境都是可以向上搜作用域链的,但是任何环境都不能通过向下搜索作用域而进入另一个执行环境。 当我们在某个环境中需要读取而引用一个标识符代表某种特定含义的时候,必须通过搜索来确定该标识符。...标识符解析是沿着作用域链一级一级地搜索标识符的过程,从作用域链的前端开始,向后回溯,直到找到标识符为止,找不到,会导致错误发生。

    82320

    阶段二:浏览器中JavaScript的执行机制

    :var缺陷以及为什么要引入let和const ES6之前没有块级作用域 变量提升使得变量容易在不被察觉的情况下被覆盖掉。...在函数的作用域内部,let声明的变量并没有被放到词法环境中去。 在词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域后,就会把该作用域内部的变量压到栈顶。...当一段代码中使用了一个变量,首先在"当前的执行上下文"的词法环境中查找该变量,若没有找到,继续在变量环境中去查找该变量。...如何它依旧没有找到,那么JavaScript引擎就会继续在outer所指向的执行上下文中查找。 我们就把这个查找变量过程的链条称为作用域链。...词法作用域 词法作用域是指作用域是由代码中函数声明的位置来决定的,所有词法作用域是静态的作用域,通过它能够预测代码在执行过程中如何查找标识符。

    55430

    深入理解JavaScript作用域

    a = 2 操作可能很容易被你忽略掉,这操作发生在 2 被当做参数传递给 foo 函数时,2 会被分配给参数 a,为了给参数 a (隐式地) 分配值,需要进行一次 LHS 查询。...词法作用域 词法作用域是你在写代码时将变量写在哪里来决定的。编译的词法分析阶段基本能够知道全局标识符在哪里以及是如何声明的,从而能够预测在执行过程中如果对他们查找。...JavaScript编译阶段是找到找到所有声明,并用合适的作用域将他们关联起来(词法作用域核心内容),所以就是包含变量和函数在内的所有声明都会在任何代码被执行前首先被处理。...const也是可以用来创建块级作用域变量,但是创建的是固定值。 作用域链 JavaScript是基于词法作用域的语言,通过变量定义的位置就能知道变量的作用域。全局变量在程序中始终都有定义的。...总结 作用域就是一套规则,用于确定在哪里找以及怎么找到某个变量。 词法作用域在你写代码的时候就确定了。JavaScript是基于词法作用域的语言,通过变量定义的位置就能知道变量的作用域。

    70830

    this 之谜揭底:从浅入深理解 JavaScript 中的 this 关键字(一)

    它的值为 NaN。如果你发现为什么是这么个奇怪的结果,那你肯定会有 “为什么它的值是 NaN, 而不是其他值?” 的疑惑。...• 其实,this 在任何情况下都不指向函数的词法作用域。...• 此外,编写这段代码的开发者还试图使用 this 联通 foo() 和 bar() 的词法作用域,从而让bar() 可以访问 foo() 作用域里的变量 a。...这是不可能实现的,你不能使用 this 来引用一个词法作用域内部的东西。 this 到底是什么 • 说了这么多,那 this 到底是一个什么样的机制呢?...而 this 就是这样一个属性,会在函数执行的过程中被用到。 小结 • 学习 this 的第一步要明白 this 既不指向函数自身也不指向函数的词法作用域。

    11710

    JavaScript执行机制:变量提升、作用域链、词法作用域、块级作用域、闭包和this

    如果找不到,它会继续在外层作用域查找,直到找到这个变量或者到达全局作用域。这种由内到外的查找顺序形成了作用域链。 作用域链的主要作用是保证变量的正确访问。...通过作用域链,JavaScript引擎可以在多层嵌套的作用域中找到正确的变量。...这是因为作用域链的查找机制。 1.2 词法作用域 词法作用域是JavaScript中作用域的静态结构。词法作用域是在代码编写时就确定的,与代码的执行无关。...换句话说,词法作用域是由函数的嵌套结构决定的,而不是函数的调用方式。 词法作用域使得JavaScript引擎可以在编译阶段就确定变量的查找顺序。这种静态结构有助于提高代码的可读性和可维护性。...当baz函数被调用时,它可以访问foo函数作用域内的变量x,即使foo函数已经执行完毕。这是因为词法作用域的静态结构。 1.3 块级作用域 块级作用域是指由大括号{}包围的代码块内的作用域。

    15211

    关于 JS 闭包看这一篇就够了

    更准确的来说,LHS是为了找到变量的容器本身从而可以进行赋值,而RHS则是获取某个变量的值。...,但可以在上级作用域(全局作用域)中找到,而c在整个作用域链中都没有找到,所以抛出了ReferenceError异常。...2.3 词法作用域 作用域共有两种主要的工作模型。第一种是最为普遍的,被大多数编程语言所采用的「词法作用域」,也可以被叫做 「静态作用域」,另一种则称为「动态作用域」(如Bash脚本)。...词法作用域查找只会查找一级标识符,比如a,b等,如果代码中引用了obj.name,词法作用域查找只会试图查找obj标识符,找到这个变量后,对象属性访问规则会接管对name属性的访问。...2.4 欺骗词法作用域 Javascript中有两种机制可以欺骗词法作用域,,分别是eval和with,但「欺骗词法作用域会导致性能下降」,所以不建议使用。

    44220

    还担心面试官问闭包?

    谈谈闭包之前,我们先说说作用域 这里我们要说的作用域指的是词法作用域。词法作用域即为定义在词法阶段的作用域。换句话说,就是你写代码时将变量和块作用域写在哪里所决定的。...引擎无法在这一层作用域中找到变量a,因此引擎会去上一级嵌套作用域foo(...)中查找,如果找到了,则即使用。 如果a,c 都存在作用域bar(...)...简单理解词法作用域的概念,其实也就是我们常说的作用域,关于JavaScript中欺骗词法以及更多关于词法作用域的介绍,请翻阅《你不知道的JavaScript》。...总之,从上面的代码中,我们可以看到闭包的有趣的三个概念 内部函数的参数包含在闭包中 作用域之外的所有变量、即便是函数声明之后的那些声明,也都包含在闭包中....深入到引擎内部原理中,内置的g工具函数setTimeout持有对一个参数的引用,引擎调用这个函数,在例子中就是内部的timer函数,而词法作用域在这个过程中保持完整。这就是闭包。

    46810

    js作用域、作用域链和它的一些优化

    内容对于几乎所有的编程语言来说,最基本的功能之一,就是储存变量当中的值并且能在之后对这个值进行访问和修改。这种能力的引入,是程序的状态存在的基础。...这就是我们可以在函数执行声明语句前调用函数的原因。另外,函数的词法环境在被创建时,对应函数的参数会被初始化在环境记录中,并且会被赋值上调用函数时的所传值或者函数参数的默认值。...作用域链作用域可以嵌套,嵌套在内部的作用域可以访问外部的作用域所声明的变量和函数。通过上面词法环境的介绍,我们大概清楚,作用域的这种嵌套关系是通过词法环境的外部词法环境引用outer来关联实现的。...其中,变量name作为函数参数属于当前函数作用域的局部变量,变量可以直接从当前函数的词法环境functionLexicalEnvironment中查找到并返回相关信息。...这个变量的引用会沿作用域链一直查找到全局词法环境globalLexicalEnvironment中,从中查找到并返回相关变量信息。

    1.7K00

    js作用域、作用域链和它的一些优化_2023-02-28

    内容 对于几乎所有的编程语言来说,最基本的功能之一,就是储存变量当中的值并且能在之后对这个值进行访问和修改。这种能力的引入,是程序的状态存在的基础。...另外,函数的词法环境在被创建时,对应函数的参数会被初始化在环境记录中,并且会被赋值上调用函数时的所传值或者函数参数的默认值。...作用域链 作用域可以嵌套,嵌套在内部的作用域可以访问外部的作用域所声明的变量和函数。通过上面词法环境的介绍,我们大概清楚,作用域的这种嵌套关系是通过词法环境的外部词法环境引用outer来关联实现的。...其中,变量name作为函数参数属于当前函数作用域的局部变量,变量可以直接从当前函数的词法环境functionLexicalEnvironment中查找到并返回相关信息。...这个变量的引用会沿作用域链一直查找到全局词法环境globalLexicalEnvironment中,从中查找到并返回相关变量信息。

    64120

    作用域和闭包

    RHS 查询与简单地查找某个变量的值别无二致,而 LHS 查询则是试图找到变量的容器本身,从而可以对其赋值。 # 作用域嵌套 当一个块或函数嵌套在另一个块或函数中时,就发生了作用域的嵌套。...因此,在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层的作用域(也就是全局作用域)为止。...换句话说,可以把变量和函数包裹在一个函数的作用域中,然后用这个作用域来“隐藏”它们。 为什么“隐藏”变量和函数是一个有用的技术? 有很多原因促成了这种基于作用域的隐藏方法。...持有对一个参数的引用,这个参数也许叫作 fn 或者 func ,或者其他类似的名字。引擎会调用这个函数,在例子中就是内部的 timer函数,而词法作用域在这个过程中保持完整。...这就是闭包 本质上无论何时何地 ,如果将函数(访问它们各自的词法作用域)当作第一级的值类型并到处传递,你就会看到闭包在这些函数中的应用。

    72020

    JS学习系列 02 - 词法作用域

    大多数语言采用的都是词法作用域,少数语言采用动态作用域(例如 Bash 脚本),这里我们主要讨论词法作用域。 2. 词法 大部分标准语言编译器的第一个工作阶段叫作词法化。...都是分别定义在全局作用域中的函数,它们是并列的,所以在 foo1 的作用域链中并不包含 foo2 的作用域,虽然在 foo2 中调用了 foo1,但是 foo1 对变量 a 进行 RHS 查询时,在自己的作用域没有找到...,引擎会去 foo1 的上级作用域(也就是全局作用域)中查找,而并不会去 foo2 的作用域中查找,最终在全局作用域中找到 a 的值为 2。...因为 eval("var a = 10;") 在 foo 的作用域中新创建了一个同名变量 a,引擎在 foo 作用域中对 a 进行 RHS 查询,找到了新定义的 a,值为 10,所以不再向上查找全局作用域中的...复制代码 如上所示,我们对 c 进行 LHS 查询,因为在 with 引入的新作用域中没有找到 c,所以向上一级作用域(这里是全局作用域)查找,也没有找到,在非严格模式下,在全局对象中新建了一个属性

    1.1K30
    领券