理解 JavaScript 作用域

上一篇文章中分析了 JS 中的数据类型和变量。这一篇文章将分析作用域,以及回答上一篇文章中变量提升的原因。

什么是作用域

作用域是一套规则,保存着变量,等待被引擎所查找。

var a = 1;
console.log(a);  // => 1
console.log(b);  // => ReferenceError

当打印 a 时,引擎就去作用域中查找 a,找到把结果返回。如果查找失败,那么就会报错。

词法作用域

JS 采用的词法作用域,也可以说是静态作用域。简单来说,词法作用域是由写代码时将变量写在哪里决定的。

先看一段代码:

var a = 1;function fn() {var a = 2;return a;
}fn();  // => 2

当执行函数 fn 时,会返回 2,而不是 1。

作用域查找

JS 引擎会进行两种查找,LHS 和 RHS。怎么理解?L 和 R 可以说代表左和右。什么的左和右?赋值操作的。

这里的赋值操作不一定出现 =,比如参数传递也是一个赋值操作。

当变量出现在赋值操作的左边时,引擎就会对这个变量进行 LHS 查找;当出现在右边时(这个还可以理解为取得变量的源值),就会进行 RHS 查找。

function foo(a) {console.log(a);
}foo(2);

对于变量 a 来说,引擎会进行两次查找,1 次 LHS,1 次 RHS。

调用 foo(),并传入参数 2,这时存在着一个赋值操作即 a = 2,进行一次 LHS 查找。打印 a 时,需要获取 a 的源值,所以进行一次 RHS 查找。

如果查询失败呢?

对于 LHS 来说,给未声明的赋值就会查询失败。

a = 2;

但是我们知道,上面的代码在非严格模式下并不会报错,而变量 a 会被自动创建。

而对于 RHS 来说,直接使用未声明的变量就会报 ReferenceError。

console.log(a); // => ReferenceError

另外,RHS 虽然查询成功,但是却对查询结果进行非法操作,就会报 TypeError。

var foo = 1;
foo(); // => TypeError

作用域链

前面说,作用域是根据名称查找变量的一套规则。而在实际情况中,经常出现多个作用域嵌套的情况。

function foo(a) {console.log(a + b);
}
var b = 2;
foo(2); // => 4

当引擎对 b 进行 RHS 查找时,在当前作用域无法找到,引擎就会在外层作用域中查找,直到找到这个变量,或者直到抵达最外层作用域(全局作用域)为止。

LHS 查找也是如此。

把这样一层一层嵌套的作用域,叫做作用域链。

函数作用域

函数作用域是指,属于这个函数的全部变量都可以在这个函数的范围内使用及复用。

function foo() {var a = 1;
}console.log(a); // => ReferenceError

也就是说,函数外部将无法访问函数内部的变量。

但是这却是非常有用的。我们可以利用函数隐藏内部实现,使其外部无法访问、修改等。

立即执行函数表达式

利用函数作用域,可以将外部作用域无法访问的内容包装起来。但是,带来了额外的一个问题,函数名本身“污染”了所在的作用域。

这时,就提出了 IIFE(立即执行函数表达式)。

(function foo() {// ...
}());

即包装了内部函数,又避免了引入函数名。因为这个函数名无法被外部作用域所访问。

IIFE 的进阶用法是给其传入参数:

(function fn(global) {// ...
})(window);

这样的好处是可以缩短查询时的作用域链。

块作用域

ES6,通过 let 和 const 引入了块作用域。

if (true) {let a = 1;
}
console.log(a); // => ReferenceError

变量提升

上一篇文章中中提到了变量提升。

在 JS 中,var a = 1; 这行代码其实会被看成 var aa = 2,并在两个阶段去执行。

在编译阶段,执行声明操作;在执行阶段,执行赋值操作。

所有的变量声明都会被提升到作用域的顶部,这个过程叫做“提升”。

函数声明也会发生提升,并且函数声明会先于变量提升:

var foo = 1;
function foo () {}typeof foo; // => 'number'

注意,只有函数声明会被提升,而函数表达式不会被提升。

var foo = 1;
var foo = function () {}typeof foo; // => 'function'

小结

这篇文章梳理了 JavaScript 中作用域的基本知识。

接下来会介绍执行上下文和闭包这两个概念,它们与作用域息息相关。

关于

这是我的公众号,记录着我的前端博客,没事儿也分享一些电影、书籍。

欢迎一起交流学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/537426.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Axure原型设计导出到PDF文件

Axure 没有直接导出PDF文件的功能,可以通过Axure 的打印功能,选择PDF打印机,以间接的方式将原型设计导出到pdf文件里。 操作步骤 以Axure9为例 打印 Axure9---文件---打印 不要母版 预览 预览下效果,看下是否有不必要的内容 …

python pca降维_机器学习的降维打击

文章发布于公号【数智物语】 (ID:decision_engine),关注公号不错过每一篇干货。来源 | SAMshare(id:SAMshare)作者 | samshare"本次主要讲解的内容就是特征降维,主要涉及PCA以及一些常见分析方法。"01Index一,PCA降维算…

参加技术培训前的辅导,选得对,学得好

最近几年,每年都会有人问我培训班的事情,我也有培训班经历,在软件行业工作了十多年,每次解答培训班的咨询我都很认真,也很高兴能帮到他人。 决定通过专栏的形式解答培训班常见问题,我把专栏取名“技术培训…

进入IT行业,要不要参加培训班?

IT行业介绍 考虑培训班无非是要入行,那IT行业好不好?IT行业当然好,看看培训班的数量就知道了。现在房产行业好赚钱,每个小区门口好几家中介门店,相同品牌的可能不止1家。不用去看网上的软文,也不用去问百度,看市场的反应,这是真实的反馈。培训班越来越多,课程越来越多…

Kubernetes在上汽集团云平台及AI方面的应用

2019独角兽企业重金招聘Python工程师标准>>> 帆一尚行成立于2015年,是上汽集团的全资子公司,建设有上海、南京、郑州(在建)三个数据中心,拥有超过4000台物理服务器,10PB的数据存储,总…

我的Java培训经历

此文讲述我的Java开发培训经历,来解答关心的培训费、培训节奏、就业等问题。 我在2010年参加达内Java培训,如今再回首那段时光,虽然辛苦,但很值得!(后悔参加培训班,大部分原因是冲动&#xff0…

python跨函数调用变量_对python中不同模块(函数、类、变量)的调用详解

首先,先介绍两种引入模块的方法。 法一:将整个文件引入 import 文件名 文件名.函数名( ) / 文件名.类名 通过这个方法可以运行另外一个文件里的函数 法二:只引入某个文件中一个类/函数/变量 需要从某个文件中引入多个函数或变量时&#xff0c…

软件培训技术选哪个?

要培训了,培训技术怎么选? 技术需慎重选 女怕嫁错郎,男怕入错行。后悔参加培训班,因为技术没选好的占比很高。 技术没选好会有什么影响? 近的影响是就业!远的影响是发展! 对于程序员来说,技术就是立身之本,需要慎重选择! 我在《要不要参加培训班?》文章中介绍…

django安装_技术大牛详解:Django框架之环境安装

黑马程序员视频库播妞微信号:boniu236传智播客旗下互联网资讯、学习资源免费分享平台虚拟环境安装:开发中问题:如何在同一台主机中,要开发多个不同的项目,而且需要用到同一个包的不同版本?尝试分析:在开发过…

安装 Alibaba Cloud Toolkit

IntelliJ IDEA版 JetBrains 插件市场下载 Eclipse 版 Eclipse 插件市场仓库下载 (推荐)URL 地址在线安装Maven 版 在 POM 文件中依赖 PyCharm、PhpStorm、RubyMine 和 WebStorm 版 公测中官网https://toolkit.aliyun.com 交流群(钉钉) 交流群&#xff08…

软件Java前端大数据培训机构怎么选?

先看这篇文章《要不要参加培训班》。 选技术就像选另一半,那选培训机构就是选另一半的家庭。另一半家庭好与不好,与婚后幸福生活息息相关。 选培训机构的几个维度: 1.成立时间 2.专业性 3.市场普及率 成立时间 成立久的不一定好,比如北大某鸟 成立不足3年的,不要选…

Chrome浏览器多开,亲测有效

原理 指定不同的用户目录,就可以实现多开。即:"--user-data-dir" 指定不同的目录。 操作 新建用户目录文件夹 要开几个,就新建几个,文件夹名随意。 复制chrome快捷方式 修改目标路径 每个快捷方式,修改…

培训时常犯的学习误区与应对方法

和在学校里上课一样,同一位老师教,同班同学成绩不同。同学之间的资质都是差不多的,因学习方法不同,学习心态不同,课后努力程度不同导致的成绩差异。 本文介绍下培训时容易犯的学习误区和误区的应对方法。 误区1 不懂不明白的地方,非要打破铁锅问到底。 应对方法 培训…

超越培训班同学的独门绝技

​​​​​​​本文讲3个独门绝技,十多年苦练多得,只传有缘人。 ​​​​​​​ 不订阅,就是不给看 绝技1 -----权益保护线----- -----权益保护线----- -----权益保护线----- -----权益保护线----- -----权益保护线----- 写CSDN博文 CSDN上有不少参加培训班的…

DataQ数据对象为空的解决方法

问题 在dataq上面创建周期任务的时候发现了这么一个问题,配置好目标源之后,数据对象的下拉选项中是空的,如下图。 原因 是因为目前无法使用自动创建目标表功能,需要自己去dataworks上面先自己创建好。 措施 1.创建目标表 2.创…

pythonifnotnone_使用 if x is not None 还是if not x is None

使用 if x is not None 还是if not x is None呢? 谷歌的风格指南和PEP-8都使用if x is not None,那么它们之间是否存在某种轻微的性能差异呢?通过测试发现没有性能差异,因为它们编译为相同的字节码:Python 2.6.2 (r262…

Java工具实现无水印批量下载

自媒体时代是指以个人传播为主,以现代化、电子化手段,向不特定的大多数或者特定的单个人传递规范性及非规范性信息的媒介时代,人人都有麦克风,人人都是记者,人人都是新闻传播者。这种媒介基础凭借其交互性、自主性的特…

proxmox集群节点崩溃处理

问题描述在现有集群加入一个物理节点,接着再此节点创建ceph监视器、创建OSD。从宿主机系统执行ceph osd tree查看状态,创建起来的几个OSD状态都正常(up),从proxmox管理界面看也是这样。突然不知道什么原因,…

python csv转excel_将Excel文件转为csv文件的python脚本

将Excel文件转为csv文件的python脚本 #!/usr/bin/env python __author__ "lrtao2010"Excel文件转csv文件脚本 需要将该脚本直接放到要转换的Excel文件同级目录下 支持xlsx 和 xls 格式 在同级目录下生成名为excel_to_csv.csv 的文件,采用UTF-8编码import…

前端多图片上传怎么控制顺序_Web前端经典面试题有哪些 如何能走向高薪之路...

Web前端经典面试题有哪些?如何能走向高薪之路?Web前端在近几年是越来越火热了,很多人看到了前端的高薪资,更看到了前端行业的发展前景,所以纷纷投入到学习前端技术学习中来。下面给大家总结整理一些Web前端经典面试题&…