javascript作用域之块级作用域
栏目: JavaScript · 发布时间: 5年前
内容简介:昨天对函数作用域进行了简单介绍目录看一个栗子
昨天对函数作用域进行了简单介绍
简单回顾
目录
看一个栗子
let d = 4; (function(c) { let a = 1, b = 2 foo2() function foo2() { let a = 11 foo3() function foo3() { console.log(`a:${a}`); //=>11 console.log(`b:${b}`); //=>2 console.log(`c:${c}`); //=>3 console.log(`d:${d}`); //=>4 console.log(`e:${e}`); //Uncaught ReferenceError: e is not defined } } })(3)
上面函数就是下面的简写形式
let d = 4; function foo1(c) { //相同部分省略 } foo1(3)
当然也可以这么写
let d = 4; (function (c) { let a = 1, b = 2; (function () { let a = 11; (function () { console.log(`a:${a}`); //=>11 console.log(`b:${b}`); //=>2 console.log(`c:${c}`); //=>3 console.log(`d:${d}`); //=>4 console.log(`e:${e}`); //Uncaught ReferenceError: e is not defined })() })() })(3)
理论上是可行的,但代码可读性太差
函数创建后立即执行,并传入一个参数=>3
变量的查找是从内向外逐层查找,如果到最外层依然找不到就会抛一个not defined的错
这样就形成了一个作用域链,内层同名变量会覆盖外层的,(有没有想到原型链?)
块级作用域
先普及一个概念:
ECMAScript和JavaScript关系:
ECMAScript是一个国际通过的标准化脚本语言。可以简单理解为:ECMAScript是JavaScript的语言规范,JavaScript是ECMAScript的实现和扩展。
什么是块级作用域?
任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。
在es6标准出来之前,javascript是不存在块级作用域的
一个栗子
{ var name = "郭靖"; console.log(name);//=>郭靖 } console.log(name);//=>郭靖
再看一个不那么hello world的栗子
function foo() { var hisName = "郭靖" for (var i = 0; i < 10; i++) { // 啥也不干 } console.log(i);//=>10 console.log(hisName);//=>"郭靖" } foo(); //console.log(i);//=>Uncaught ReferenceError: i is not defined console.log(hisName); //=>Uncaught ReferenceError: hisName is not defined
通过上面的栗子我们可以发现
在foo内部,在for循环外部,成功的打印出i,这说明使用var声明的变量是不存在块级作用域的
在foo外部,我们打印i或者hisName,都会报Uncaught ReferenceError的错误,i和hisName是foo内部的私有变量,这说明使用var声明的变量存在函数作用域
我们上面介绍了js块级作用域的概念,两个花括号内部定义的内容,外部无法访问的,而javascript又存在函数作用域,
好了,我们可以通过javascript的函数作用域来模拟实现块级作用域
还是上面的栗子
function foo() { (function () { var hisName = "郭靖" for (var i = 0; i < 10; i++) { // 啥也不干 } })() console.log(i);//Uncaught ReferenceError: i is not defined console.log(hisName);//上面报错,这里就不会执行,这里就算执行,也会报错 } foo(); // console.log(i);//=>Uncaught ReferenceError: i is not defined // console.log(hisName); //=>Uncaught ReferenceError: hisName is not defined
这不正是我们昨天讨论的内容吗?立即执行函数,函数执行后,内部变量会被销毁(闭包情况暂不考虑,后面的文章会详细介绍),所以外部就无法访问啦
所以又说到昨天的内容了,为了防止命名冲突我们一般这么写
(function () { var herName = "黄蓉" })() console.log(herName);//Uncaught ReferenceError: herName is not defined
一个简易块级作用域诞生了
ES6中块级作用域
我们现在写代码,如果项目允许使用ES6,那就很少会有人通过函数作用域来实现块级作用域了,因为ES6支持块级作用域
let
说起let,就会情不自禁的将let和var进行比较,
说几个明显的区别
var变量声明提升
看几个栗子,有助于理解
hisName = "郭靖" var hisName console.log(hisName);
undefined?
最后输出“郭靖”
上面的代码经过js引擎编译处理,变成了这样
var hisName hisName = "郭靖" console.log(hisName);
继续看栗子
console.log(hisName); var hisName = "郭靖"
最后输出“undefined”
上面的代码经过js引擎编译处理,变成了这样
var hisName console.log(hisName); hisName = "郭靖"
javascript代码并不是一行一行往下执行的,分为2个步骤:
- 编译(词法解释/预解释)
- 执行
理解了没?如果理解了,继续看一个栗子
var hisName = "郭靖"; function hero() { console.log(hisName); var hisName = "洪七公"; } hero(); console.log(hisName);
先不关心输出什么,我排一下顺序
var hisName = "郭靖"; function hero() { var hisName console.log(hisName); hisName = "洪七公"; } hero(); console.log(hisName);
如果顺序排队了,基本就没什么问题
执行hero函数,打印hisName,声明了,但是没有复制,所以是undefined
到这里,你可能会有一个疑问,js存作用域链,hero内部的hisName是undefined,它不会继续像外层作用域继续查找吗?
当然不会啦,只要声明过,如果没赋值,就存在一个默认值=>undefined
hero()后面的console.log(hisName);//=>郭靖,为什么?
因为函数作用域的作用,hero内部的变量,外部无法访问(暂不考虑闭包),变量首先查找的是同级作用域,同级作用域不存在就会继续向外层查找,但不会向内层查找
通过这三个栗子,我相信,你已经搞懂了javascript的变量提升
let块级作用域
前面说在ES6标准出来之前,是不存在块级作用域的,需要函数作用域进行配合模拟实现块级作用域
let 存在块级作用域,let 不存在变量提升(必须先声明,声明前不能进行赋值等相关操作)
{ hisName = "郭靖";//在这里级报错了Uncaught ReferenceError: hisName is not defined let hisName console.log(hisName); }
再来一个栗子
let hisName = "黄药师"; let herName = "黄蓉"; { let hisName = "洪七公"; { let hisName = "郭靖"; console.log(hisName);//=>郭靖 console.log(herName);//=>黄蓉 } console.log(hisName);//=>洪七公 } console.log(hisName);//=>黄药师
输出也没什么悬念
//=>郭靖 //=>黄蓉 //=>洪七公 //=>黄药师
let 暂时性死区
暂时性死区,听起来好迷糊,其实没什么,
因为let不存变量提升,使用let命令声明变量之前,该变量都是不可用的
其实还是关于变量提升的问题
const?
关于const在块级作用域上,和let保持一致,不在此赘述
END
以上所述就是小编给大家介绍的《javascript作用域之块级作用域》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 图解词法作用域与作用域链
- javascript静态作用域和动态作用域
- JavaScript系列之作用域和作用域链
- 【7】JavaScript 函数高级——作用域与作用域链
- 深入学习js之——词法作用域和动态作用域
- 深入理解Javacript, 从作用域与作用域链开始
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。