博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【前端工程师手册】JavaScript之作用域
阅读量:5862 次
发布时间:2019-06-19

本文共 2095 字,大约阅读时间需要 6 分钟。

什么是作用域

来一段《你不知道的JavaScript-上卷》中的原话:

几乎所有编程语言最基本的功能之一,就是能够储存变量当中的值,并且能在之后对这个 值进行访问或修改,这些变量住在哪里?换句话说,它们储存在哪里?最重要的是,程序需要时如何找到它们?这些问题说明需要一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量。这套规则被称为作用域

总之就是作用域就是一套规则,这个规则规定了程序如何去找到变量

词法作用域

先看一个例子:

function func1() {    console.log(index)}function func2() {    var index = 10    func1()}var index = 100func2()    // 100

为啥是100而不是10呢???

因为JavaScript是词法作用域
词法作用域简单地说就是:函数的作用域在声明的时候就决定好了。和词法作用域相对的是动态作用域,动态作用域关注函数从何处调用
上面的代码中,声明func1时,它就处于全局作用域中,所以index就是100,即使执行func1时也是。

函数作用域和块作用域

前面讲了JavaScript是词法作用域,那么什么时候会创建作用域呢???

JavaScript主要是基于函数级别的作用域,也就是每一个函数都会创建一个作用域。为什么说主要呢?因为with和try-catch语句也实现了块作用域,当然了用的很少。

var flag = true;if (flag) {    var num = 10}console.log(num)    // 10

如果有块级作用域的话,此时打印num应该报错

function funcLevelScope() {    var index = 10}console.log(index);    // ReferenceError

因为是函数级别的作用域,所以在函数外面访问不到函数内部的变量

如何模拟块作用域

当然了,第一反应就是在代码外面加上包装函数不就行了,比如这样子:

function scope() {    var flag = true;    if (flag) {        var num = 10    }}console.log(num)    // ReferenceError

但是此时的问题就是多了一个函数包装,且我们可以随意的去运行scope函数,这可能会造成不好的影响。

自执行函数解决了这个问题:

(function scope() {    var flag = true;    if (flag) {        var num = 10    }})()scope()    // ReferenceErrorconsole.log(num)    // ReferenceError

包装函数的声明以 (function... 而不仅是以 function... 开始。尽管看上去这并不 是一个很显眼的细节,但实际上却是非常重要的区别。函数会被当作函数表达式而不是一个标准的函数声明来处理。

作用域内声明提升

变量声明提升

首先明确的是

var x = 10

像这样一句代码可以分为声明和赋值两句:

var xx = 10

明确这个概念再继续学习

console.log(x)    // undefinedvar x = 10

为什么不直接报错呢?

因为上面的代码片段等于:

var x    // 声明提前console.log(x)x = 10

注意到变量的声明提前到了当前作用域的最前面

函数声明提升

hoist()    // hoist!function hoist() {    console.log("hoist!")}

为啥函数会成功执行了,因为上面的代码片段相当于:

function hoist() {    console.log("hoist!")}hoist()

函数声明被提升到了作用域的最前面

那么函数表达式会被提升吗??

hoist()    // TypeErrorvar hoist = function () {    console.log("hoist")}

因为这个相当于:

var hoisthoist()    // TypeErrorhoist = function () {    console.log("hoist")}

变量声明提升和函数声明提升的优先级

先说结论:函数会首先被提升,然后才是变量
看例子:

console.log(x)var x = 10function x() {    console.log('func x')}

显然此时打印的x是一个函数

这是因为上面的代码片段相当于:

function x() {    console.log('func x')}var xconsole.log(x)    // f x(){...}x = 10

所以打印的是函数

参考资料:

转载地址:http://qzgjx.baihongyu.com/

你可能感兴趣的文章
关于nginx upstream的几种配置方式
查看>>
IE9 table显示问题
查看>>
ceph 快照,克隆,cow
查看>>
ImageMagick更改图片格式进而缩小图片
查看>>
需求感太强
查看>>
珠心算测验
查看>>
NFS安装及挂载
查看>>
国内网站监控分析网站
查看>>
Junit系列之六
查看>>
FSMO图形界面转移角色主机
查看>>
Windows server 2012多元化密码策略
查看>>
VI编辑器
查看>>
Spark 启动脚本——sbin/slaves.sh
查看>>
我的友情链接
查看>>
MSC-2015移动安全挑战赛 第二题
查看>>
class卸载、热替换和Tomcat的热部署的分析
查看>>
xxxx已损坏,打不开。您应该推出磁盘映像
查看>>
Centos7升级内核
查看>>
Android4.4 xposed安装失败(the xposed framework is not installed)
查看>>
17 VMware云的配置与管理
查看>>