深入理解javascript函数作用域

简介: 深入理解javascript函数作用域

前言

     上一章我们介绍了有关javascript词法作用域的相关知识,之前我们是概述地把作用域描绘成一个个小“气泡”, 但是并没有过多解释“气泡”的形成,究竟哪些情况下会形成上述的“气泡”呢,其实包括函数作用域和块作用域,这一章我们将就这个函数作用域详细展开

正文

函数作用域

      JavaScript 具有基于函数的作用域,意味着每声明一个函数都会为其自身创建一个气泡,函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复用(事实上在嵌套的作用域中也可以使用)。大家可以看下下面的例子:

640.png

      这里全局作用域下,只有foo一个标识符,而a, b, c, bar都附属于foo的作用域气泡,这些标识符全都无法从全局作用域中进行访问,这就是典型的函数作用域


隐藏内部实现

      函数作用域有一个常见的用途,也就是隐藏内部实现。我们可以把变量和函数包裹在一个函数的作用域中,然后用这个作用域来“隐藏”它们。

      这么做的原因,是因为软件设计过程中有一个最小特权原则,意思就是说指在软件设计中,应该最小限度地暴露必要内容,而将其他内容都“隐藏”起来,比如某个模块或对象的 API 设计。下面我们就一个例子来进一步说明

640.png

      这个例子其实我们可以看到,doSomethingElse其实是doSomething的一部分,也就是私有部分,这样实现的工具类函数其实有一个问题,给予外部作用域对 b 和 doSomethingElse(…) 的“访问权限”不仅没有必要,而且可能是“危险”的,因为它们可能被有意或无意地以非预期的方式使用,从而导致超出了 doSomething(…) 的适用条件。更“合理”的设计会将这些私有的具体内容隐藏在 doSomething(…) 内部,我们看下如果使用函数作用域隐藏内部实现的做法

640.png

      现在,b 和 doSomethingElse(…) 都无法从外部被访问,而只能被 doSomething(…) 所控制。功能性和最终效果都没有受影响,但是设计上将具体内容私有化了,设计良好的软件都会依此进行实现。


规避冲突

      “隐藏”作用域中的变量和函数所带来的另一个好处,是可以避免同名标识符之间的冲突,两个标识符可能具有相同的名字但用途却不一样,无意间可能造成命名冲突。冲突会导致变量的值被意外覆盖。例如下面的例子:

640.png

      就上面的例子,这里bar中的i = 3意外地覆盖了foo中的i,导致程序无线循环执行了,我们需要利用上面说的,尽量避免这种情况的发生


全局命名空间

      变量冲突的一个典型例子存在于全局作用域中。当程序中加载了多个第三方库时,如果它们没有妥善地将内部私有的函数或变量隐藏起来,就会很容易引发冲突。

      这些库通常会在全局作用域中声明一个名字足够独特的变量,通常是一个对象。这个对象被用作库的命名空间,所有需要暴露给外界的功能都会成为这个对象(命名空间)的属性,而不是将自己的标识符暴漏在顶级的词法作用域中。

640.png

模块管理

      利用export和import也可以形成一个类似命名空间的封闭作用域,保持在私有、无冲突的作用域中,这样可以有效规避掉所有的意外冲突。

小结

      函数是 JavaScript 中最常见的作用域单元。本质上,声明在一个函数内部的变量或函数会在所处的作用域中“隐藏”起来,这是有意为之的良好软件的设计原则。但函数不是唯一的作用域单元。块作用域指的是变量和函数不仅可以属于所处的作用域,也可以属于某个代码块(通常指 { … } 内部)。下一篇文章我们将进一步介绍,javascript的块作用域

目录
相关文章
|
12天前
|
JavaScript 前端开发
js的作用域作用域链
【10月更文挑战第29天】理解JavaScript的作用域和作用域链对于正确理解变量的访问和生命周期、避免变量命名冲突以及编写高质量的JavaScript代码都具有重要意义。在实际开发中,需要合理地利用作用域和作用域链来组织代码结构,提高代码的可读性和可维护性。
|
11天前
|
自然语言处理 JavaScript 前端开发
[JS]作用域的“生产者”——词法作用域
本文介绍了JavaScript中的作用域模型与作用域,包括词法作用域和动态作用域的区别,以及全局作用域、函数作用域和块级作用域的特点。通过具体示例详细解析了变量提升、块级作用域中的暂时性死区等问题,并探讨了如何在循环中使用`var`和`let`的不同效果。最后,介绍了两种可以“欺骗”词法作用域的方法:`eval(str)`和`with(obj)`。文章结合了多位博主的总结,帮助读者更快速、便捷地掌握这些知识点。
23 2
[JS]作用域的“生产者”——词法作用域
|
12天前
|
JavaScript 前端开发 Java
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
本文介绍了JavaScript中常用的函数和方法,包括通用函数、Global对象函数以及数组相关函数。详细列出了每个函数的参数、返回值及使用说明,并提供了示例代码。文章强调了函数的学习应结合源码和实践,适合JavaScript初学者和进阶开发者参考。
25 2
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
|
13天前
|
前端开发 JavaScript 数据处理
CSS 变量的作用域和 JavaScript 变量的作用域有什么不同?
【10月更文挑战第28天】CSS变量和JavaScript变量虽然都有各自的作用域概念,但由于它们所属的语言和应用场景不同,其作用域的定义、范围、覆盖规则以及与其他语言特性的交互方式等方面都存在明显的差异。理解这些差异有助于更好地在Web开发中分别运用它们来实现预期的页面效果和功能逻辑。
|
12天前
|
JavaScript 前端开发
如何在 JavaScript 中实现块级作用域?
【10月更文挑战第29天】通过使用 `let`、`const` 关键字、立即执行函数表达式以及模块模式等方法,可以在JavaScript中有效地实现块级作用域,更好地控制变量的生命周期和访问权限,提高代码的可维护性和可读性。
|
20天前
|
JavaScript 前端开发
javascript的作用域
【10月更文挑战第19天javascript的作用域
|
11天前
|
前端开发 JavaScript 开发者
除了 Generator 函数,还有哪些 JavaScript 异步编程解决方案?
【10月更文挑战第30天】开发者可以根据具体的项目情况选择合适的方式来处理异步操作,以实现高效、可读和易于维护的代码。
|
25天前
|
JavaScript 前端开发
JavaScript 作用域
JavaScript 作用域是指程序中可访问的变量、对象和函数的集合。它分为函数作用域和局部作用域。函数作用域内的变量仅在函数内部可见,而全局作用域的变量在整个网页中均可访问。局部变量在函数执行完毕后会被销毁,而全局变量则在整个脚本生命周期中都存在。未使用 `var` 关键字声明的变量默认为全局变量。
|
25天前
|
JavaScript 前端开发
JavaScript 函数语法
JavaScript 函数是使用 `function` 关键词定义的代码块,可在调用时执行特定任务。函数可以无参或带参,参数用于传递值并在函数内部使用。函数调用可在事件触发时进行,如用户点击按钮。JavaScript 对大小写敏感,函数名和关键词必须严格匹配。示例中展示了如何通过不同参数调用函数以生成不同的输出。
|
27天前
|
存储 JavaScript 前端开发
JS函数提升 变量提升
【10月更文挑战第6天】函数提升和变量提升是 JavaScript 语言的重要特性,但它们也可能带来一些困惑和潜在的问题。通过深入理解和掌握它们的原理和表现,开发者可以更好地编写和维护 JavaScript 代码,避免因不了解这些机制而导致的错误和不一致。同时,不断提高对执行上下文等相关概念的认识,将有助于提升对 JavaScript 语言的整体理解和运用能力。