ES6学习教程之块级作用域详解


Posted in Javascript onOctober 09, 2017

前言

众所周知ES5之前javascript语言只有函数作用域和全局作用域,使用var来声明变量,var声明的变量还存在变量提升使人困惑不已。我们先来复习一下ES5的var声明,再对比学习let和const 。

var

var声明之函数作用域和全局作用域。

来段代码体会一下:

function getName() {
 if (1 + 1 === 2) {
 var name = 'xixi';
 }

 console.log(name);
}

getName();//xixi

在c或java语言中name本应该只在if块中使用的,但是在if的外面也可以访问到,这个就是 js没有块级作用域的一种体现。这个弊端在for循环中体现的十分明显:

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

console.log(i);// 10

var i的本意是声明个临时变量i,用来遍历数组等,本不应该在for循环的外部访问到,但现在却可以被访问到你说闹不闹心?好一点的程序员会用立即执行函数来模拟块级作用域,原来的我会注意一下尽量不使用相同的变量名?。

(function() {
 for (var i = 0; i < 10; i ++) {
 // ...
 }
})();

console.log(i);// undefined

以上:大家知道了 js 没有块级作用域。

变量可以重复声明

var name = 'xixi';
console.log(name);// xixi
var name= '一步';
console.log(name);// 一步

不报错,困惑不困惑,这个就是变量可以重复声明。

变量提升

function getName() {
 console.log(name);
 var name = 'xixi';
 // ...
}

getName();// undefined

console.log打印name为undefined。为啥不报错呢,对于一直使用js语言的人来说这个现象还好理解,如果是后台转前端的人来说估计得骂人了。这就是所谓的变量提升。简单的向大家解释一下吧。

var name = 'xixi';

这是一条被我们写烂了的语句,包含两个过程:var name; name = 'xixi';分别为变量声明和变量初始化。

变量提升: 无论变量声明var name;处于什么位置,都会被提到作用域的顶部进行。

let

ES6为让变量生命周期更加可控,引入两个非常好的特性let、const。块级作用域、不能重复声明、临时性死区等特性用来解决 var 变量存在的种种问题。

块级作用域

function getName4ES6() {
 if (1 + 1 === 2) {
 let name = 'xixi';
 }

 console.log(name);
}

getName4ES6(); // undefined

终于在{}外面访问不到name了。for循环也变的简单了,大家试一下将for循环的var换成 let.

同一块级作用域内不能重复声明变量

function redefineValue() {
 let name = 'xixi';
 let name = '一步';
}

redefineValue();// Uncaught SyntaxError: Identifier 'name' has already been declared

重复声明会报错

{
 let name = 'xixi';
 console.log(name);// xixi
 {
 let name = 'yibu';
 console.log(name); // yibu
 }
}

注意: 在 ES6中,{}就是一个块级作用域。

临时性死区

function getName4ES6() {
 console.log(name);
 for (let i = 0; i < 10; i ++) {

 }
 let name = 'xixi';
 // ...
}

 
getName4ES6();// Uncaught ReferenceError: name is not defined

在上文ES5中,name还会存在变量提升,值为undefined。ES6中又报错了。怎么解释呢?。。。。这个就是临时性死区的概念,在作用域块中不可以在变量声明前就使用变量,若使用是会出错的。

javascript引擎在发现变量声明时,要么将变量声明提升到作用域的顶部(var声明变量时),要么将变量放在临时性死区中(let、const声明变量时),访问临时性死区中的变量会触发运行时错误。

ES6学习教程之块级作用域详解

const

const和let同样具有块级作用域,不能重复声明,临时性死区的概念。它还具有两个特有的特性:声明的同时必须初始化、变量引用不可以改变。

声明的同时必须初始化

const name;//Uncaught SyntaxError: Missing initializer in const declaration

不赋值,就报错。这个也很好理解const的本意就是用来定义常量,不可变的值。若不在声明时给出初始值以后就再也没有机会了。

值不可变

const name = 'x9x9';
name = 'yyy';// Uncaught SyntaxError: Invalid or unexpected token

那么对象会怎样呢?

const person = {
 name: 'lala',
 age: 40
};

person = {};// VM1042:6 Uncaught TypeError: Assignment to constant variable. at <anonymous>:6:8

引用是不可变的,那我们在看看对象的属性值是什么情况吧~

person.name = 'yoyo';
console.log(person);// {name: "yoyo", age: 40}

没有报错,对象引用不可改变,对象属性可以变更。

let vs const

大家可能会困惑,什么时候使用let,什么时候使用const。let能做的const好像都可以。网上有一种流行做法:能用const就绝不用let,简单粗暴,不过很好用。

个人看法:若变量在后续方法中会被改变,就使用let。一些常量声明使用const, const声明的变量名全部大写。代码中的变量,如果是let声明的就代表其可变,若是const声明的,不论是简单数据类型还是引用类型变量就都不要改变它的值。这样,程序会更加的健壮,大家合作起来也比较方便。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
js判断背景图片是否加载成功使用img的width实现
May 29 Javascript
通过一段代码简单说js中的this的使用
Jul 23 Javascript
jquery弹出框的用法示例(一)
Aug 26 Javascript
jquery实现适用于门户站的导航下拉菜单效果代码
Aug 24 Javascript
正则表达式,替换所有HTML标签的简单实例
Nov 28 Javascript
扩展bootstrap的modal模态框-动态添加modal框-弹出多个modal框
Feb 21 Javascript
JavaScript实现打地鼠小游戏
Apr 23 Javascript
jquery replace方法去空格
May 08 jQuery
JavaScript设计模式之单例模式详解
Jun 09 Javascript
laydate如何根据开始时间或者结束时间限制范围
Nov 15 Javascript
ES6入门教程之Array.from()方法
Mar 23 Javascript
浅谈Layui的eleTree树式选择器使用方法
Sep 25 Javascript
JavaScript实现短信倒计时60s
Oct 09 #Javascript
ES6学习教程之对象字面量详解
Oct 09 #Javascript
AngularJS中的路由使用及实现代码
Oct 09 #Javascript
React如何利用相对于根目录进行引用组件详解
Oct 09 #Javascript
React Native中的RefreshContorl下拉刷新使用
Oct 09 #Javascript
JS实现的全排列组合算法示例
Oct 09 #Javascript
js + css实现标签内容切换功能(实例讲解)
Oct 09 #Javascript
You might like
PHP游戏编程25个脚本代码
2011/02/08 PHP
php 转换字符串编码 iconv与mb_convert_encoding的区别说明
2011/11/10 PHP
如何让搜索引擎抓取AJAX内容解决方案
2014/08/25 PHP
php上传文件并显示上传进度的方法
2015/03/24 PHP
js控制web打印(局部打印)方法整理
2013/05/29 Javascript
js+ajax实现获取文件大小的方法
2015/12/08 Javascript
jQuery实现验证年龄简单思路
2016/02/24 Javascript
JS随机洗牌算法之数组随机排序
2016/03/23 Javascript
jQuery实现按钮点击遮罩加载及处理完后恢复的效果
2016/06/07 Javascript
浅谈js里面的InttoStr和StrtoInt
2016/06/14 Javascript
Js获取当前日期时间及格式化代码
2016/09/17 Javascript
javascript鼠标跟随运动3种效果(眼球效果,苹果菜单,方向跟随)
2016/10/27 Javascript
NodeJS和BootStrap分页效果的实现代码
2016/11/07 NodeJs
JS+html5 canvas实现的简单绘制折线图效果示例
2017/03/13 Javascript
原生JS+Canvas实现五子棋游戏实例
2017/06/19 Javascript
jQuery实现base64前台加密解密功能详解
2017/08/29 jQuery
JS和JQuery实现雪花飘落效果
2017/11/30 jQuery
vue项目中使用lib-flexible解决移动端适配的问题解决
2018/08/23 Javascript
在vue里使用codemirror遇到的问题
2018/11/01 Javascript
node中使用log4js4.x版本记录日志的方法
2019/08/20 Javascript
[04:42]2015国际邀请赛CDEC战队晋级之路
2015/08/13 DOTA
[39:53]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第一场 11.19
2020/11/19 DOTA
Python的Django框架中的数据库配置指南
2015/07/17 Python
numpy.linspace 生成等差数组的方法
2018/07/02 Python
iPython pylab模式启动方式
2020/04/24 Python
超酷炫 CSS3垂直手风琴菜单
2016/06/28 HTML / CSS
悦木之源美国官网:Origins美国
2016/08/01 全球购物
我们的节日元宵活动方案
2014/08/23 职场文书
自愿解除劳动合同协议书
2014/09/11 职场文书
交通肇事罪辩护词
2015/05/21 职场文书
朝花夕拾读书笔记
2015/06/29 职场文书
用php如何解决大文件分片上传问题
2021/07/07 PHP
Mysql存储过程、触发器、事件调度器使用入门指南
2022/01/22 MySQL
Vue操作Storage本地化存储
2022/04/29 Vue.js
Win11运行cmd提示“请求的操作需要提升”的两种解决方法
2022/07/07 数码科技
MySQL事务的隔离级别详情
2022/07/15 MySQL