ES6的一些新东西也用过一段时间,也是用到什么就学什么,没有认真的整理过,最近认真地看了阮一峰老师的《ES6标准入门》这本书,想着要认真的做下笔记,整理一番,如果有不对的地方,欢迎指点更正。
let命令
let是es6新增的用于声明变量的命令,其用法类似var,但是所声明的变量只在let所在的代码块内有效,其基本用法如下:
{
let a = 10;
var b = 1;
}
a // ReferenceError:a is not defined.
b // 1
以上变量a和b都是在代码块内声明,但a在代码块外无效,而b有效,再看一下在for循环中的使用区别:
//例子a
// 使用var声明变量 i
var a = [];
for(var i = 0;i < 10; i++) {
a[i] = function() {
console.log(i);
}
}
a[6](); // 10
// 例子b
// 使用let声明变量i
var a = [];
for(let i = 0;i < 10; i++) {
a[i] = function() {
console.log(i);
}
}
a[6](); // 6
在例子a中,变量i是var声明的,在全局范围内都有效,所以全局只有一个变量i,即i最后值为10;
而在例子b中,变量i是使用let声明,i只会在本轮循环中有效,所以每次循环i都是一个新的变量,因此每个i的值都不一样。
另外:for循环有个特别之处,即设置循环变量的那一部分是父作用域,而循环体内部是一个单独的子作用域。
for(let i = 0;i < 10;i++){
let i = 'abc';
console.log(i); // abc
//没有报错,说明循环体的i并没有在此作用域中声明(因为同一变量在同一作用域内不可重复声明,见特性部分)
}
let命令的一些特性:
1、不存在变量提升
//var情况下
console.log(a); //输出undefined
var a = 2;
//let情况下
console.log(b); //报错ReferenceError
let b = 2;
以上代码中,var命令会有“变量提升”,而let命令并不存在“变量提升”,而是要求必须先声明才能使用,所以使用let代替var来声明变量更合理,养成更好先声明在使用的编程习惯。
2、不允许重复声明
let命令不允许在相同作用域内重复声明同一个变量
//报错
function fn(){
let a = 1;
var a = 2;
}
//报错
function fn(){
let a = 1;
let a = 2;
}
//报错
function fn(arg){
let arg = 1;
}
//不报错
function fn(arg){
{
let arg = 1;//此时变量arg在该代码块的作用域中
}
}
3、暂时性死区
只要会计作用域中存在let命令,那么它所声明的变量就“绑定”这个区域,不在受外部干扰(及时外部也声明了同样的变量)
let tmp = 1;
if(true) {
tmp = 2; //ReferenceError
console.log(tmp); //ReferenceError
let tmp;
console.log(tmp); //undefined
tmp = 3;
console.log(tmp); // 3
}
如以上代码,由于使用let声明的变量在该作用域内,不在受外部影响,且没有“变量提升”和不可重复声明,所以在变量声明之前是不能使用该变量,是成为“暂时性死区”;
一些比较隐蔽的“死区”:
function fn(x=y,y=2){
return x +y;
}
fn();//报错,因为在把y赋值给x时,y并没有定义
let x = x; //ReferenceError: x is not defined
暂时性死区的本质是:只要进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用变量。
const 命令
const声明一个常量,一旦声明,常量的值就不能改变,这也意味着,const一旦声明常量,就必须立即初始化,不能留到以后赋值。
const PI = 3.14159;
PI //3.14159
PI = 3; //TypeError:Assignment to constant variable
const与let命令一样,其所声明的变量不会提升,不能重复声明,同样存在暂时性死区,只能在声明后使用。
本质
const实际上保证的并不是变量的值不变,而是变量指向的那个内存地址不得改动,对于简单类型的数据(数值、字符串、布尔值)而言,值就保存在变量指向的内存中,因此等于常量;但对于复合类型的数据(主要是对象和数组)而言,变量只想的内训地址保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,这完全不能控制,因此在将一个对象声明为常量时需要非常小心。
来栗子:
const foo = {};
// 为foo添加一个属性,可以成功
foo.prop = 1;
foo.prop // 1
//将foo指向另一个对象,则会报错
foo = {}; // TypeError:"foo" is read-only
同样,使用const声明数组也一样
const arr = [];
a.push('hello'); // 可执行
a.length = 0; //可执行
a = ['world']; // 报错