热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaScript中作用域的详细介绍(代码示例)

​本篇文章给大家带来的内容是关于JavaScript中作用域的详细介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
本篇文章给大家带来的内容是关于Javascript中作用域的详细介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

几乎所有的编程语言都有作用域的概念,那作用域到底指的是什么呢?作用域就是编程语言在定义变量时,变量如何存储、变量如何访问的一套规则,不同的编程语言的规则大同小异,接下来就来看看这套规则是怎么设定的

编译原理

在传统编译语言中,在代码执行之前都会有一个编译过程:

  • 分词/词法分析:将代码语句分解成有意义的代码块,又叫词法单元。
  • 解析/语法分析:将词法单元转换一个逐级嵌套的具有语法规则的树状结构,又叫抽象语法树(AST)
  • 代码生成:解析AST并转化成机器指令

和传统编译语言不太一样,js的编译和执行并不是分开执行,大多数情况都是编译过程结束就会立刻执行,为了在短时间的编译过程内达到较优性能,js引擎较一般编译器更复杂,现在就让来看js的编译过程,简单的以编译var a = 2为例:

  • 遇到var a,编译器会询问作用域是否已经有一个该名称的变量存在于同一个作用域的集合中。如果是,编译器会忽略该声明,继续进行编译;否则它会要求作用域在当前作用域的集合中声明一个新的变量a
  • 接下来编译器会为引擎生成运行时所需的代码,这些代码被用来处理a=2这个赋值操作。引擎运行时会首先询问作用域,在当前的作用域集合中是否存在一个叫做a的变量。如果否,引擎就会使用这个变量;如果引擎最终找到了a,就会将2赋值给它。否则引擎就会抛出一个异常

词法作用域

作用域一般有两种工作模型,第一种是被大多数编程语言所采用的词法作用域,另外一种叫作动态作用域,如Bash脚本采用的就是动态作用域。词法作用域就是定义在词法阶段的作用域,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,由变量定义位置决定,而动态作用域则是由变量使用的位置来决定的。下面来看个例子:

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

首先来分析一下这里一共存在几个作用域?

  1. 全局作用域,里面存在foo变量
  2. foo函数创建的作用域,里面有a,b,bar变量
  3. bar函数创建的作用域,里面有c变量

接下来再来分析一下变量的查找过程,引擎执行console.log()需要查找a、b、c三个变量的引用,首先从最里面的bar()作用域开始找,引擎无法找到a,因此会再往上到foo()作用域中找,在这里找到了a,停止查找,对于b、c来说查找过程一样。作用域查找始终从运行时最内层开始查找,逐级向外查找,直到遇见第一个匹配的变量为止。

函数作用域

函数作用域指的是属于这个函数的全部变量都可以在整个函数的范围内使用及复用,这是大家都知道的定义,但是函数作用域的存在到底有什么用呢?接下来就一起看看函数作用域的秒用。

隐藏内部实现

隐藏内部实现就是将变量和函数包裹在一个函数的作用域中,达到隐藏的目的,为什么要这么做呢?软件设计中有一个非常有名的原则叫最小暴露原则,指最小限度暴露必要内容,而将其他内容都隐藏起来,比如模块或对象的API设计。用函数作用域来包裹变量和函数来达到最小暴露原则,阻止外部直接访问,来看下面的例子:

function doSomething(a) {
  b = a + doSomethingElse( a * 2 );
  console.log( b * 3 );
}
  
function doSomethingElse(a) {
  return a - 1;
}
var b;
doSomething( 2 ); // 15”

在这段代码中doSomethingElse和b应该是doSomething内部私有的,但是却被暴露出来,这样会导致以预期之外的形式被使用,产生意料之外的结果,更合理的设计应该是将这些私有的内容隐藏在doSomething内部,例如:

function doSomething(a) {
  function doSomethingElse(a) {
    return a - 1;
  }
  var b;
  b = a + doSomethingElse( a * 2 );
  console.log( b * 3 );
}
doSomething( 2 );

这样b和doSomethingElse都无法从doSomething外部访问,但是这样也会存在一些问题,首先在全局作用域中声明了doSomething函数,污染了全局作用,其次,必须通过显示调用才能执行,那么有没有什么办法既不会污染作用域也不需要调用就可以自执行呢?答案就是函数表达式,看下面的例子:

(function doSomething(a) {
  function doSomethingElse(a) {
    return a - 1;
  }
  var b;
  b = a + doSomethingElse( a * 2 );
  console.log( b * 3 );
})(2)

首先来看(function doSomething(){})这是一个函数表达式,和函数声明不同的是用括号包起来的,然后再(function doSomething(a){})()调用传值,这样既能自执行也不会污染作用域,社区给这种用法定义了一个术语:IIFE,代表立即执行函数表达式

块作用域

除Javascript外很多编程语言都支持块作用域,尽管你可能写过很伪块作用域形式的代码,最常见的就是for循环:

for(var i=0; i<10; i++) {
  console.log(i)
}

写这段代码通常是希望变量i在循环内部使用,但是实际上i会被绑定到外部作用域中,要确保没有在作用域的其他地方意外使用i,就只能依靠自觉,这时候块级作用域就显得尤为有用,ES6改变了现状,引入了新的let、const关键字,let关键字可以将变量绑定到所在的任意作用域中,也就是let为其声明的变量隐式地创建了作用域:

for(let i=0; i<10; i++) {
  console.log(i)        
}
console.log(i) // ReferenceError

这时候i就只会在for循环的内部有效

以上就是Javascript中作用域的详细介绍(代码示例)的详细内容,更多请关注 第一PHP社区 其它相关文章!


推荐阅读
  • MySQL5.6.40在CentOS764下安装过程 ... [详细]
  • docker容器的数据管理一:数据卷实现数据的永久化,完全独立于容 ... [详细]
  • 本文介绍了《中秋夜作》的翻译及原文赏析,以及诗人当代钱钟书的背景和特点。通过对诗歌的解读,揭示了其中蕴含的情感和意境。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文描述了作者第一次参加比赛的经历和感受。作者是小学六年级时参加比赛的唯一选手,感到有些紧张。在比赛期间,作者与学长学姐一起用餐,在比赛题目中遇到了一些困难,但最终成功解决。作者还尝试了一款游戏,在回程的路上感到晕车。最终,作者以110分的成绩取得了省一会的资格,并坚定了继续学习的决心。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文整理了常用的CSS属性及用法,包括背景属性、边框属性、尺寸属性、可伸缩框属性、字体属性和文本属性等,方便开发者查阅和使用。 ... [详细]
  • mysql自动打开文件_让docker中的mysql启动时自动执行sql文件
    本文提要本文目的不仅仅是创建一个MySQL的镜像,而是在其基础上再实现启动过程中自动导入数据及数据库用户的权限设置,并且在新创建出来的容器里自动启动My ... [详细]
  • Shell编程(三)bash数学运算
    本文介绍shell中的expr和bash自带的 ... [详细]
  • 我创建了一个SSH密钥,当我以admin身份在GitBash中运行ssh-Tgit@gitlab.com时,我得到W ... [详细]
  • 对于一般的扩展包,我们一般直接pipinstallxxx即可安装,但是unrar直接安装后,发现并不能通过Python程序实现解压的功能& ... [详细]
author-avatar
闲看云天的快乐生活
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有