美文网首页
你不知道的JavaScript-函数作用域和块作用域

你不知道的JavaScript-函数作用域和块作用域

作者: 前端小白的摸爬滚打 | 来源:发表于2022-01-25 10:19 被阅读0次

    函数中的作用域

    JS 具有基于函数的作用域,这意味着每一个函数都会为自己创建一个作用域。

    内部作用域可以访问外部作用域的变量,但是外部作用域的变量无法访问内部作用域的变量

    隐藏内部实现

    可以将变量或者函数包裹在函数中,可以做到对函数外部的作用域隐藏这个变量或函数。

    为什么要这样做? --- 最小暴露原则

    规避冲突

    隐藏作用域的另一个好处 - 防止同名标识符之间的冲突

    命名空间

    很多第三方的库都只会暴露一个全局的对象,然后将属性或者方法定义在这个全局的对象中

    模块化

    ES6 import/export/export default

    函数作用域

    在任意代码片段外部添加包装函数,可以将内部的变量和函数定义“隐藏”起来,外部作用域无法访问包装函数内部的任何内容。

    这个方式可以解决一些问题,但是并不理想:

    1. 需要声明一个函数,但这个函数的函数名会污染所在作用域

    2. 必须要调用这个函数才能执行内部的代码

    所以,综上:

    如果函数不需要变量名且可以自动运行,那么效果将更加理想(立即执行函数)

    区分函数声明和表达式最简单的方法是看 function 关键字出现在声明中的位置(不仅仅是一行代码,而是整个声明中的位置)。如果 function 是声明中 的第一个词,那么就是一个函数声明,否则就是一个函数表达式。

    function foo() {} // 函数声明
    (function foo() {}); // 函数表达式,声明中的第一个词是()
    

    匿名和具名

    函数表达式可以是匿名的,但是函数声明则不可以省略函数名

    匿名函数

    缺点:

    1. 匿名函数在栈追踪中不会显示出有意义的函数名,使得调试很困难

    2. 如果没有函数名,当函数需要引用自身时只能使用已经过期的 arguments.callee 引用, 比如在递归中。另一个函数需要引用自身的例子,是在事件触发后事件监听器需要解绑自身。

    3. 匿名函数省略了对于代码可读性 / 可理解性很重要的函数名。

    我们也可以始终给函数表达式一个名字

    立即执行函数表达式

    由于一个函数被包裹在()内,此时就变成了一个表达式,()外面再加上一个()则表示立即执行该函数。

    比如 (function foo(){ .. })()。第一个 ( ) 将函数变成表 达式,第二个 ( ) 执行了这个函数。

    很多人都更喜欢另一个改进的形式:(function(){ .. }())

    两者功能完全一致

    立即执行函数也可以在调用的时候传参

    块级作用域

    with

    with 从对象中创建出的作用域仅在 with 声明中而非外 部作用域中有效。

    try/catch

    try/catch 的 catch 分句会创建一个块作用域,其中声明的变量仅在 catch 内部有效。

    try {
      undefined();
    } catch (e) {
      var err = e;
      console.log(err); // TypeError: undefined is not a function
    }
    console.log(err); // TypeError: undefined is not a function
    console.log(e); // ReferenceError: e is not defined
    

    注意,仅仅是这里的 catch 的 e 参数是局部有效的,但是 catch 块中定义的 var 变量还是全局的

    但是当同一个作用域中的两个或多个 catch 分句 用同样的标识符名称声明错误变量时,很多静态检查工具还是会发出警告。不允许重复定义变量

    let

    let 关键字可以将变量绑定到所在的任意作用域中(通常是 { .. } 内部)。换句话说,let 为其声明的变量隐式地了所在的块作用域。

    但是使用 let 进行的声明不会在块作用域中进行提升。声明的代码被运行之前,声明并不 “存在”。

    const

    const,同样可以用来创建块作用域变量,但其值是固定的 (常量)。之后任何试图修改值的操作都会引起错误。

    小结

    函数(本身就是)和块(需要使用 let/const 定义变量)都可以形成作用域。可以很好的将变量/函数隐藏在块作用域中

    相关文章

      网友评论

          本文标题:你不知道的JavaScript-函数作用域和块作用域

          本文链接:https://www.haomeiwen.com/subject/nfhwhrtx.html