[ES6系列-04]再也不乱“哇”了:用 let 与 const 替代 var
【原创】码路工人 Coder-Power
大家好,这里是码路工人有力量,我是码路工人,你们是力量。
今天的内容是,关于 JavaScript 中定义变量的变化(其实不确切,函数,常量表示被冷落)。
首先,回顾下 var
定义存在的问题
1. 哇。。var 好乱。。
1.1 可以重复定义
/* eg.0
* multi-definition of var-variable
*/
//--------------------------------------
var band = "The Beatles"
var band = "The Scorpions"
console.log(band) // Scorpions
//--------------------------------------
以上代码没有报错,而是打印出了第二次定义的内容Scorpions
。这..在C#
等其它语言中必然是无法想象的。
JS:哎悲惨的童年,往事不堪回首。虽然被设计的简陋粗糙了些,但用起来方便啊,通过努力,一样成为Web时代的高富帅。现在有钱了,美容养生造起来~~~
1.2 可以先使用后定义
/* eg.1
* use before be definied
*/
//--------------------------------------
age = 18
console.log(age) // 18
var age = 10
console.log(age) // 10
//--------------------------------------
这就是变量提升啦。在编译的时候,会先将var
定义的变量放到最上面,但这时候值并没有,还是undefined
,赋值顺序为 18->10,所以有了一上例示例注释中的打印结果。
这里,还有一个优先级的问题,
function > variable
,即函数大于普通变量。
1.3 没有块级作用域
/* eg.2
* [var]use before variable be definied
*/
//--------------------------------------
function foo() {
var band = "Michael Learn To Rock"
}
console.log(band) // Michael Learn To Rock
//--------------------------------------
块级作用域应该有:
if(boolVal){ 这里 }
,for(...){ 这里 }
,还有function(){ 这里 }
,其实即使不是函数直接一对花括号也是产生块级的地方。
var
没有块级作用域,意味着在块级外面也能够访问。上例中的结果说明了这一点。
IIFE(Immediately Invoked Function Expression) 立即执行函数了解一下(这个准备在后面的文章中单独介绍)。
然后咱们来看看 ES6 带来了什么
2. let const 来拯救
2.1 let
和const
都有块级作用域
码麻再也不担心我在暗处受伤害了:
限定在块级作用域内不会被外部访问修改。
/* eg.3
* can not access out of block
*/
//--------------------------------------
// eg.3.1
function music() {
let band = "Mr. Big"
const songs = ["The chain", "To be with you", "Wild world"]
this.data = {
band,songs
}
}
console.log(band, songs)
// Uncaught ReferenceError: band is not defined
//--------------------------------------
上面的打印直接报错,函数外是不能访问到内部用let/const
声明的变量/常量的。
扩展一下:但可以绑定到对象属性上,属性本身外部可见。如下面的示例(在上例的基础上):
// eg.3.2
let m = new music()
console.log(m.data)
// { band: 'Mr. Big', songs: [ 'The chain', 'To be with you', 'Wild world' ] }
2.2 let
和const
都有不存在变量提升
不给糖就捣蛋。要想使用先定义。
/* eg.4
* [let/const]use after be definied
*/
//--------------------------------------
// eg.2.1
band = "Queen"
let band
// Uncaught ReferenceError: Cannot access 'band' before initialization
// eg.2.2
song = "Bohemian Rhapsody"
const song
// Uncaught SyntaxError: Missing initializer in const declaration
//--------------------------------------
未定义先使用?直接报错给你看。(看,报的错还不一样,下面还会提到)
2.3 let
和const
都不能重复定义
/* eg.4
* [let/const]can not defined duplicately
*/
//--------------------------------------
// eg.4.1
let band = "Guns&Rose"
let band = "Nirvana"
// Uncaught SyntaxError: Identifier 'band' has already been declared
// eg.4.2
const song = "November Rain"
const song = "Smells Like Teen Spirit"
// Uncaught SyntaxError: Identifier 'song' has already been declared
//--------------------------------------
简单的规则无需解释。我就是你的唯一!
2.4 let 定义变量
/* eg.5
* [let/const]can not defined duplicately
*/
//--------------------------------------
let singer = "Bob Dylan"
console.log(singer) // Bob Dylan
singer = "Bryan Adams"
console.log(singer) // Bryan Adams
//--------------------------------------
变量确实是可变的。
注:像字符串与数值,栈中存放地址,堆中保持常量池,比较两个字面量的时候,比的是地址所以会全等(===),而再次给变量赋值的时候,改变的是地址指向,常量池中的原字符串/数值还是存在的(等没有引用会回收)。
关于 ==
与 ===
可以看之前发的另一篇[传送][AboutEqual]。
2.5 const 定义常量
JS: 终于咱也有常量了(
C#
里也叫const
)
2.5.1 常量定义后不可变
/* eg.6
* use before be definied
*/
//--------------------------------------
// eg.6.1
const band = "The Eagles"
band = "The Beatles"
// TypeError: Assignment to constant variable.
// eg.6.2
const age = 18
age = 10
// TypeError: Assignment to constant variable.
//--------------------------------------
以上两个小例子中,说明字符串或数值的常量在定义后都是不能再改变的。
注意:这里不可变是指简单类型,复杂类型/对象里面的成员/属性是可以改变的。
/* eg.7
* change the value of const-object's property
*/
//--------------------------------------
const person = {
name = "Eagles",
age = 18
}
console.log(person)
// { name: 'Eagles', age: 18 }
person.name = "Chicken"
person.age = 10
console.log(person)
// { name: 'Chicken', age: 10 }
//--------------------------------------
以上打印结果显示,const
对象的属性name/age
修改成功。
2.5.2 常量在且仅在定义时赋值(=定义时必须赋初始值,赋值后不能改)
/* eg.8
* exception on define const
*/
//--------------------------------------
const foo
foo = "bar"
// SyntaxError: Missing initializer in const declaration
//--------------------------------------
不用解释,报异常了。定义const
必须给值。(上面已经提到过了,就当加深印象再说一遍吧)
(示例中好像暴露了部分播放历史。。感兴趣的同学可以搜搜瞧下)
希望对你能有帮助,下篇再见。
欢迎关注分享,一起学习提高吧。
[ES6系列-04]再也不乱“哇”了:用 let 与 const 替代 var的更多相关文章
- Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- [js高手之路] es6系列教程 - 对象功能扩展详解
第一:字面量对象的方法,支持缩写形式 //es6之前,这么写 var User = { name : 'ghostwu', showName : function(){ return this.nam ...
- [js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解
接着上文[js高手之路] es6系列教程 - 迭代器与生成器详解继续. 在es6中引入了一个新的循环结构for ....of, 主要是用来循环可迭代的对象,那么什么是可迭代的对象呢? 可迭代的对象一般 ...
- ES6 系列之 Babel 是如何编译 Class 的(下)
前言 ES5 寄生组合式继承 function Parent (name) { this.name = name; } Parent.prototype.getName = function () { ...
- ES6系列之箭头函数
本系列是在平时阅读.学习.实际项目中有关于es6中的新特性.用发的简单总结,目的是记录以备日后温习:本系列预计包含let/const.箭头函数.解构.常用新增方法.Symbol.Set&Map ...
- JavaScript进阶系列04,函数参数个数不确定情况下的解决方案
本篇主要体验函数参数个数不确定情况下的一个解决方案.先来看一段使用函数作为参数进行计算的实例. var calculate = function(x, y, fn) { return fn(x, y) ...
- 委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理
委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链.本篇的话题包括:委托链是怎样形成的,如何调用委托链方法,以及委托链异常处理. □ 调用返回类型为 ...
- php从入门到放弃系列-04.php页面间值传递和保持
php从入门到放弃系列-04.php页面间值传递和保持 一.目录结构 二.两次页面间传递值 在两次页面之间传递少量数据,可以使用get提交,也可以使用post提交,二者的区别恕不赘述. 1.get提交 ...
- C#程序集系列04,在程序集包含多个module的场景下理解关键字internal
本篇在一个程序集包含多个module的场景下体验internal的含义. →查看F盘as文件夹下的文件→删除MainClass.exe→把MyFirstModule和MySecondModule组装到 ...
随机推荐
- 数据库SQL语言从入门到精通--Part 5--E-R图(实体联系图)用来描述数据库图例
数据库从入门到精通合集(超详细,学习数据库必看) E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型.属性和联系的方法,用来描述现实世界的概念模型. ...
- USACO Training Section 1.1 坏掉的项链Broken Necklace
题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 n=29 的二个例子: 第一和第二个珠子在图片中已经被作记号. 图片 A ...
- muduo网络库源码学习————线程特定数据
muduo库线程特定数据源码文件为ThreadLocal.h //线程本地存储 // Use of this source code is governed by a BSD-style licens ...
- Mariadb 主主复制
两台server1 192.168.1.189 && server2 192.168.1.226 安装mariadb数据库 yum -y install mariadb maria ...
- VUE生命周期中的钩子函数及父子组件的执行顺序
先附一张官网上的vue实例的生命周期图,每个Vue实例在被创建的时候都需要经过一系列的初始化过程,例如需要设置数据监听,编译模板,将实例挂载到DOM并在数据变化时更新DOM等.同时在这个过程中也会运行 ...
- Spring官网阅读(十五)Spring中的格式化(Formatter)
文章目录 Formatter 接口定义 继承树 注解驱动的格式化 AnnotationFormatterFactory FormatterRegistry 接口定义 UML类图 FormattingC ...
- js函数传递参数的方式------传值与传递指针
原则: 1. 基本类型:传值 2. 对象:传递指针 应用场景之一: 用jq选择器获取某个div后(例如:element),准备进行某些修改,之后添加到页面中去. 采取例一的方式,append后发现修改 ...
- Day_11【集合】扩展案例5_对list集合对象中的元素进行反转,求最大值最小值,求元素i在list集合中首次出现的索引,将oldvalue替换为newvalue
分析以下需求,并用代码实现 定义MyArrays工具类,该工具类中有以下方法,方法描述如下: 1.public static void reverse(ArrayList<Integer> ...
- SAP登录消息提醒
1功能说明 在相应用户登录时,给其提示相关信息. 2功能实现 2.1函数实现 在函数NAVIGATION_SET_START_TCODE中注册要监听的用户和程序的事务代码,当用户登录时,将自动运行 ...
- RMQ问题总结,标准RMQ算法的实现
RMQ问题:对于长度为N的序列,询问区间[L,R]中的最值 RMQ问题的几种解法: 普通遍历查询,O(1)-O(N) 线段树,O(N)-O(logN) DP,O(NlogN)-O(1) RMQ标准算法 ...