2015年刚公布的ECMAScript增加了很多新的特性,可以说又进一步增强了javascript。当然其中还有很多特性还没有真正在浏览器中实现,有些特性直接在javascript中使用还需要启用严格模式(例如chrome浏览器)。不过相信时间的推移,ES 6会被越来越多的浏览器所支持。
let 关键字
ES 6中新增了let关键字用来声明变量,而声明出来的变量只在声明的代码块中有效,从而弥补了javascript没有块级作用域的缺陷。不仅如此,在for循环中,每次循环中定义的函数内部都能准确引用这次循环中产生的变量:1
2
3
4
5
6
7
8var arr = [];
for(let i=0; i < 10; i++){
arr[i] = function(){
console.log(i);
};
}
arr[7]();
和var声明变量的方式不同,let声明变量时不存在变量的提升问题。也就是说,通过let声明的变量必须先声明,然后才能使用。这也意味着typeof操作符不再是百分之百安全的操作了。
暂时性死区
只要某个代码块中存在let关键字声明变量,该变量就属于当前代码块,在变量被真正声明以前,该变量是不能被访问的,否则报错(存在暂时性死区,即使代码块外部存在同名变量)。即使该代码块外部已经存在使用let或者var声明了同名的变量,也不会对代码块内部造成影响,同样内部也不会对外部产生影响。该代码块内依然使用的是内部声明的变量,但不允许内部在声明变量之前就使用该变量。
在某个代码块中多次使用let声明同一个变量,也不允许var和let混合声明同一个变量。1
2
3
4
5
6let a = 12;
if (true) {
let a = 1;
console.log(a); // 1
}
console.log(a); // 12
对于函数的声明也是如此。内外的代码块不会相互影响(即使进入了内部代码块也不会对外部代码块产生影响),函数的作用域只是该函数声明所在的代码块中。1
2
3
4
5
6
7function (){console.log("I am outside.");}
function(){
if(true) {
function (){console.log("I am inside.");}
}
fn(); // "I am outside."
}();
const 关键字
const关键字也是用来声明常量的。一旦声明该常量,则赋给该常量的值就不能再发生改变。const声明常量时,必须立即初始化,而不能等到以后再赋值。const声明的常量和let一样,只在变量声明的代码块中有效,不存在提升的问题,也存在暂时性死区,只能在声明后使用,在同一代码块中不能出现同名变量重复声明。
对于常量值是一个引用对象时,常量只能保证指向的对象所在的内存地址不变,但不能保证对象内部数据不会发生改变。也就是说,常量引用的对象的属性和方法是可以修改的。
ES 6中也规定了采用let、const和class关键字声明的全局变量不属于全局对象的属性。
解构赋值1
2
3
4
5
6
7
8
9
10
11
12let [a,b,c] = [1,2,3];
let [d,[e],f] = [4,[5,6],7]; // d = 4; e = 5; f = 7
let [g, ...h] = [1,2,3,4]; // g = 1; h = [2,3,4]
let [i,j, ...k] = [1,2]; // i = 1; j = 2; k = []
let {l,m} = {m: 1,l: 2}; // l = 2; m = 1
let {l: n,m: o} = {m: 1,l: 2}; // n = 2; o = 1
let {p: [x, {y}]} = {p: ["hello", {y: 3}]}; // x = "hello";y = 3
let [q = true] = []; // q = true
let {r = 4} = {}; // r = 4
let {s: t = "hello"} = {}; // t = "hello"
let {u: v = 5} = {u:null}; // v = null
let {w: {z = 6}} = {}; // 报错,因为获取到的w属性值为undefined,然后再获取undefined的z属性则会报错
解构赋值的应用场景
交换变量的值
例如:1let [x, y] = [y, x];
可以从函数返回多个值
例如:1
2
3
4
5
6
7
8
9
10
11function (){
return [1, 2];
}
let [x, y] = fn(); // x = 1; y = 2
function func(){
return {
x: 3,
y: 4
};
}
let {x, y} = func(); // x = 3; y = 4
提取json数据
例如:1
2
3
4
5
6var json = {
fruits: ["apple", "pear"],
id: "v587",
date: new Date()
};
let {id, date, fruits} = json; // id = "v587"; fruits: ["apple", "pear"]; date: "Sat May 07 2016 21:14:16 GMT+0800"
函数参数的默认值1
2
3
4
5
6
7
8
9var fn = function(url, {
async = true,
cache = true,
complete = function (){
...
}
}) {
...
};
模板字符串
模板字符串使用反引号(`)标识,它既可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中插入变量:1
2
3var who = "hb";
var what = "javascript";
console.log(`${who} is learning ${what}`); // "hb is learning javascript"
如果使用模板字符串表示多行字符串,模板字符串中的所有空格和缩进都会保留在输出中:1
2
3
4
5
6console.log(`
javascript
javascript is powerful
good good study, day day up`);
//
javascript
//
javascript is powerful
// good good study, day day up
模板字符串中通过“${}”来嵌入变量,大括号中可以是任意的javascript表达式,包括运算,对象属性,函数调用等等。
标签模板
标签模板其实是函数调用的一种参数,它的形式类似于这样:1tag`string template`
标签名其实就是自定义用来处理模板字符串的函数的名称,后面跟的模板字符串就是待处理的字符串。自定义的模板字符串处理函数格式如下:1
2function tag(stringArr, ...values){
}
假设待处理的模板字符串是 `Hello ${a + b} world ${a * b}`,其中a和b的值分别是5和10。则调用模板字符串处理函数时,传入的stringArr的值为["Hello ", " world ", ""],传入的values的值为[15, 50],接下来就可以在函数中对模板字符串做我们想要的处理,然后返回新的字符串。
标签模板的一个重要应用就是用来过滤HTML字符串,防止用户恶意的输入。