资讯专栏INFORMATION COLUMN

js作用域

wmui / 1530人阅读

摘要:词法作用域定义与查找词法作用域就是定义在词法阶段的作用域,简单来说词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此大部分情况下当词法分析器处理代码时会保持作用域不变此例中一共由三个逐级嵌套的作用域包含这整个全剧作用域,其中只

词法作用域 定义与查找

词法作用域就是定义在词法阶段的作用域,简单来说词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此大部分情况下当词法分析器处理代码时会保持作用域不变

function foo(a) {
  var b = a * 2;
  function bar(c) {
    console.log(a, b, c)
  }
  bar(b * 3)
}
foo(2) // 2, 4, 12

此例中一共由三个逐级嵌套的作用域:

包含这整个全剧作用域,其中只有一个标识符:foo

包含着foo所创建的作用域,其中有三个标识符:a、bar和b

包含着bar所创建的作用,其中只有一个标识符:c

作用域查找过程

当引擎执行console.log(a, b, c)声明时,它首先会从最内层的bar()函数作用域开始查找,在这里找到了c

因为无法找到a和b,因此会到再上一层的foo()作用域去查找

作用域查找会在找到第一个匹配的标识符时停止
无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置决定

函数作用域

函数作用域指的是属于这个函数的全部变量都可以在整个函数的范围内使用及复用,包括嵌套的作用域,这种设计方案非常有用。

隐藏内部实现

在软件设计中,应该最小限度地暴露必要内容,而将其他内容都隐藏起来,这个原则在如何在如何选择作用域来包含变量和函数也同样适用,例如:

var b;
function one(a) {
  b = a + another(a)
  console.log(b)
}
function another(a) {
  return a*2
}

one(2) // 6

在这段代码中,给予外部函数b和another访问权限不仅没有必要,而且可能会被以非预期的方式使用,因此更加合理的设计会将这些内容隐藏在one()内部,例如:

function one(a) {
  function another(a) {
    return a*2
  }
  var b
  b = a + another(a)
  console.log(b)
}
one(2) //6

这样设计b和another()都无法从外部被访问,功能和最终效果都没有受影响,但是设计上将具体内容私有画

立即执行行数表达式

通过前面的介绍已经知道,在任意代码片段外部添加包装函数,可以将内部变量和函数定义隐藏起来,外部作用域无法访问包装函数内部的任何内容。例如:

var a = 0
function ex() {
  var a = 1
  console.log(a) // 1
}
ex();
console.log(a)// 0

虽然这样可以解决一部分问题,但是并不理想,会将ex这个变量污染全局作用域,并且需要调用才能运行其中的代码,javascript提供了解决问题的方案:立即执行函数表达式(IIFE)

var a = 0;
(function () {
  var a = 1
  console.log(a) //1
})();
console.log(a) //0

此时就不会有函数名泄漏到全局作用域,并且会自动执行,同时外部的作用域也无法直接访问立即执行函数内的变量

块作用域

事实上javascript在ES6之前并没有块作用域的概念,但是其他很多编程语言都支持块作用域,ES6之前javascript循环:

for (var i=0; i<3; i++) {
  console.log(i) //0, 1, 2
}
console.log(i) //3 

虽然我们的代码看起来i只会在for循环内部使用,但是很不幸,i会被泄漏到全局的作用域中,污染全局作用域,即使这并是我们本意,但是在ES6改变了现状,引入了新的let关键字,提供了除var以外的另一种变量声明方式,let可以将变量绑定到所在的任意作用域中,即为其声明的变量隐式地劫持了所在的作用域

for (let i=0; i<3; i++) {
  console.log(i) //0, 1, 2
}
console.log(i) // i is not defined

以上内容是个人的一点总结,如果有错误或不严谨的地方,欢迎批评指正,如果喜欢,欢迎点赞收藏

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91869.html

相关文章

  • js闭包的本质

    摘要:也正因为这个闭包的特性,闭包函数可以让父函数的数据一直驻留在内存中保存,从而这也是后来模块化的基础。只有闭包函数,可以让它的父函数作用域永恒,像全局作用域,一直在内存中存在。的本质就是如此,每个模块文件就是一个大闭包。 为什么会有闭包 js之所以会有闭包,是因为js不同于其他规范的语言,js允许一个函数中再嵌套子函数,正是因为这种允许函数嵌套,导致js出现了所谓闭包。 function...

    qianfeng 评论0 收藏0
  • JavaScript之变量及作用

    摘要:所以的作用域是静态作用域,也叫词法作用域。总结是一门基于词法作用域静态作用域的语言,会沿着作用域链像气泡一样向外部寻找变量声明。又是函数作用域的语言,在中,使用和关键字后,能让变量处于块作用域中,而且不存在声明提升。 本文共 1700 字,读完只需 7 分钟 概述 变量,编程语言中我们用来模拟现实概念的工具,比方说,变量可以表示对象,数组,数字,字符。既然是工具,那么就用工具的适用范围...

    Faremax 评论0 收藏0
  • Js基础知识(三) - 作用与闭包

    摘要:是词法作用域工作模式。使用可以将变量绑定在所在的任意作用域中通常是内部,也就是说为其声明的变量隐式的劫持了所在的块级作用域。 作用域与闭包 如何用js创建10个button标签,点击每个按钮时打印按钮对应的序号? 看到上述问题,如果你能看出来这个问题实质上是考对作用域的理解,那么恭喜你,这篇文章你可以不用看了,说明你对作用域已经理解的很透彻了,但是如果你看不出来这是一道考作用域的题目,...

    lemanli 评论0 收藏0
  • Js基础知识(三) - 作用与闭包

    摘要:是词法作用域工作模式。使用可以将变量绑定在所在的任意作用域中通常是内部,也就是说为其声明的变量隐式的劫持了所在的块级作用域。 作用域与闭包 如何用js创建10个button标签,点击每个按钮时打印按钮对应的序号? 看到上述问题,如果你能看出来这个问题实质上是考对作用域的理解,那么恭喜你,这篇文章你可以不用看了,说明你对作用域已经理解的很透彻了,但是如果你看不出来这是一道考作用域的题目,...

    XFLY 评论0 收藏0
  • Js基础知识(三) - 作用与闭包

    摘要:是词法作用域工作模式。使用可以将变量绑定在所在的任意作用域中通常是内部,也就是说为其声明的变量隐式的劫持了所在的块级作用域。 作用域与闭包 如何用js创建10个button标签,点击每个按钮时打印按钮对应的序号? 看到上述问题,如果你能看出来这个问题实质上是考对作用域的理解,那么恭喜你,这篇文章你可以不用看了,说明你对作用域已经理解的很透彻了,但是如果你看不出来这是一道考作用域的题目,...

    tanglijun 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<