简介
- 2015 年 6 月 17 日,ECMAScript 6 发布正式版本,即 ECMAScript 2015。
- ES6 是继 ES5 之后的一次主要改进,ES6 增添了许多必要的特性,例如:模块和类,以及一些实用特性,例如 Maps、Sets、Promises、生成器(Generators)等。
- 尽管 ES6 做了大量的更新,但是它依旧完全向后兼容以前的版本,标准化委员会决定避免由不兼容版本语言导致的“web 体验破碎”。结果是,所有老代码都可以正常运行,整个过渡也显得更为平滑,但随之而来的问题是,开发者们抱怨了多年的老问题依然存在。
let 声明变量
let 是新的变量声明
- 如果声明的位置是在代码块中,那么变量只能在代码块里有用
- 代码块,类似于
if
、for 循环
等等。
1 2 3 4 5 6
| if (true) { let a = 1; } console.log(a);
|
变量不提升
不像 var
,这个没有变量提升
所以,必须先声明,再使用
1 2 3 4
| console.log(b); let b;
|
暂时性死区 TDZ
全称:temporal dead zone
声明变量之前不允许使用
1 2 3 4 5 6 7 8 9
| if (true) { typeof temp; let temp;
console.log(temp); }
|
- 注意 TDZ 的区域,从代码块开始,到定义完变量之后,这一小段是 TDZ,
- 引申:在 es6 中
typeof
不是绝对安全了
1 2 3 4 5 6 7 8 9 10 11 12
| var c = 1; function test() { console.log(c); if (true) { let c = 10; } } test();
|
1 2 3 4 5 6 7 8 9 10 11 12
| var c = 1; function test() { console.log(c); if (true) { var c = 10; } } test();
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var a = 1; function test() { console.log(a);
if (false) { var a = 10; } } test();
|
1 2 3 4 5
| let x;
{x} = {x:1} console.log(x);
|
1 2 3 4 5 6 7
| let x;
({ x } = { x: 1 }); console.log(x);
|
const 静态变量 (常量*)
有如下属性
- 不允许重复声明
- 声明的时候赋值
- 声明之后不允许修改
- 跟
let
的作用域一个德行,都是代码块里有效
实质
- const 实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址不得改动
- 对于 简单类型 的数据(数值,字符串,布尔值),存在 栈 中,值就保存在变量指向的那个内存地址。
- 对于 复杂对象(主要是对象和数组),变量指向的内存地址存在 堆 中,保存的是指向,指向的数据怎么变,它管不到
引申
- 栈:大小固定,自动分配,能由系统自动释放掉
- 堆:可变大小,不能自动释放掉
对象冻结
用到了 Object.freeze();
方法
1
| const obj = Object.freeze({ name: "张三" });
|
- 建议前面写上
const
,因为如果你这样,之后也能改变指向,如果你用了 const
,就改变不了了
1 2 3 4 5 6
| var obj = Object.freeze({ name: "张三" }); obj = {}; console.log(obj);
|
1 2 3 4 5 6
| const obj = Object.freeze({ name: "张三" }); obj = {}; console.log(obj);
|
- 冻结之后,如果想要修改内容的话,是不会报错的,但是并不能修改内容(以为对象冻结住了)
- 如果想要修改内容的话,就需要解冻。
1 2 3 4 5
| const obj = Object.freeze({ name: "张三" }); obj["name"] = "小子"; console.log(obj);
|
解构赋值
起步
可迭代的数据都可以解构赋值(数字就不行了)
1 2 3 4 5 6 7 8
| let [a, b, c] = [1, 2, 3]; console.log(a); console.log(b); console.log(c);
|
1 2 3 4
| let a = 1; let b = 2; [a, b] = [b, a]; console.log("a,b", a, b);
|
- 也可以用来当作函数的实参、形参,而且 解构赋值 有个好处,可以传
""
,undefined
,null
,false
这些东西。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
function test_bad(val) { val = val || 0; console.log(val); } test_bad(""); test_bad(undefined); test_bad(null); test_bad(false);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
function test_good([a, b, c = 0, d = 4, e]) { console.log(a); console.log(b); console.log(c); console.log(d); console.log(e); } test_good([false, null, "", undefined, "undefined"]);
|
- 如果想要让 obj2 拿到 obj 的内容,修改 obj2 还不影响 obj,那么可以解构 obj (解构之后就变成了个新的对象),然后在赋值给 obj2
1 2 3 4 5 6 7 8 9
| let obj = { a: 1, b: 2, };
let obj2 = obj;
obj2.a = 10; console.log(obj);
|
…arr 展开运算符
先来一个例子,慢慢理解一下
...arr
一定要保证是在后面,因为它只能解析从某个地方到 数组尾部
1 2 3 4 5 6 7 8
|
let [a, ...arr] = ["ar", 2, 3, 4]; console.log(a); console.log(arr);
|
1 2 3
| let [a, b, ...arr] = ["ar"]; console.log(arr);
|
- 也可以遍历字符串
- 可以设置默认值,如果严格等于 undefined,那么就走默认值(底层是
===
)
1 2 3 4 5 6 7 8 9 10 11 12 13
| let [a = 100, b = "poi"] = [undefined]; console.log(a); console.log(b);
let [a = 100, b = "poi"] = ["undefined"]; console.log(a); console.log(b);
|
1 2 3 4 5 6 7 8 9
| var a = undefined; var b = "undefined";
console.log(a == b);
console.log(a === b);
|
1 2 3 4 5 6
| function test(...arr) { console.log(arr); } test(1, 2, 3, 4);
|
…[] 数组拓展运算符
- 这个就相当于
rest
的逆运算,一个是聚合,一个是拆散,...[1,2,3]
会被拆成 1 2 3
1 2 3 4 5 6 7 8 9 10 11 12
| var f1 = (a, b, c, d) => { console.log(a); console.log(b); console.log(c); console.log(d);
}; f1(1, ...[2, 3, 4]);
|
1 2 3 4 5 6 7 8
| <body> <div>1</div> <div>2</div> <div>3</div> </body> <script> console.log(...document.querySelectorAll("div")); </script>
|
传参
1 2 3 4 5 6 7 8 9 10 11 12 13
| function f1(a, b, c, d, e) { console.log(a, b, c, d, e); }
arr1 = [1, ...[2, 3, 4], 5];
f1.apply(null, arr1);
f1(...arr1);
|
找最大值
1 2 3 4 5 6 7 8 9
| var arr1_1 = [10, 2, 4654, 789, 56, 6, 131, 32];
console.log(Math.max.apply(null, arr1_1));
console.log(Math.max(...arr1_1));
|
与三目运算符结合
1 2 3 4
| var x = 2; var arr2 = [...(x == 1 ? [1, 2, 3] : [4, 5, 6]), "x"]; console.log(arr2);
|
空
空的话,不会报错,控制台里就没有它的打印信息
1 2
| var arr3 = []; console.log(...arr3);
|
模拟深复制
1 2 3 4 5
| const a3 = [3, 4, 5];
const a4 = [...a3]; console.log(a4);
|
模拟 concat
1 2 3 4 5 6 7 8
| var arr3_1 = [1, 2, 3]; var arr3_2 = [4, 5, 6];
console.log(arr3_1.concat(arr3_2));
console.log([...arr3_1, ...arr3_2]);
|
结构解析
- 对象解析当中根据
key
来解析
- let {匹配模式:变量}
1 2 3 4 5 6
| let { c, a } = { b: "6666", a: "555" }; console.log(a); console.log(c);
|
- 数组相当于一个特殊的对象,可以用 下标 当作 key 值去解析
1 2 3 4 5 6 7
| var arr = ["dsada", "ewq", "zxcvc", 16, 18, "135"]; let { 1: fir, [arr.length - 1]: last } = arr; console.log(fir); console.log(last);
|
详细步骤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| var obj = { foo: ["ufo", { sss: "shuai" }], };
let {} = obj;
let { foo } = obj;
let { foo: [a, b], } = obj;
let { foo: [a, { sss }], } = obj;
let { foo: [a, { sss: l }], } = obj; console.log(l);
|
1 2
| var sister = [{ age: [18, { sex: "girl" }] }];
|
1 2 3 4 5
| let { log } = console; log("111");
|
1 2 3 4 5 6
|
const { PI } = Math; console.log(PI);
|
1 2 3 4 5 6 7 8
|
let { foo: fooValue } = { foo: "cszsdad" };
console.log(fooValue);
|
1 2 3 4 5 6 7
| Person.prototype.name = "lsl"; function Person() {} var p = new Person(); let { name: n } = p; console.log(n);
|
1 2 3 4 5 6 7 8
| var sister = [{ age: [18, { sex: "girl" }] }]; let [ { age: [a, { sex: x }], }, ] = sister; console.log(x);
|
惰性求值
1 2 3 4 5 6 7 8
| function f() { throw new Error("this is error"); }
let [x = f()] = [1]; console.log(x);
|
1 2 3 4 5 6 7 8 9
| function f() { throw new Error("this is error"); }
let [x = f()] = [undefined];
console.log(x);
|
模板字符串
- 优点:不需要我们拼接变量(原生的不是得用
+
来拼接成很长的句子嘛)
- 符号:
``
(TAB上面的那个~)
- 想在模板字符串中插入变量的话用
${}
- 还是函数调用的另一种形式
1 2 3 4 5 6 7 8 9 10
| const obj = { name: 18, age: "xiaopang", habit: "sing", }; var str = `my name is ${obj.name} ,age is ${a}`; console.log(str);
|
- 如果你非要在模板字符串中打出
``
这个符号,那么可以用转义字符 \
1 2 3 4 5
| var str1 = `\`\``; console.log(str1);
|
- 这个还可以插标签,可以进行变量的运算,注意写法、还可以插入方法,而且还会 解析换行,你怎样写,就会在页面上解析成相应的样子,包括换行,空格。
1 2 3 4 5 6 7 8 9 10 11 12
| var x = 5; var arr = [1, 2, 3, 4, 5];
$("#test").html(` <ul> <li style="font-size: ${x + 40}px;">1</li> <li>22\`\`</li> <li>${arr.reverse()}</li> <li>${obj.name + x}</li> </ul> `);
|
- 如果当作实参的话,字符串里穿插变量,那么形参中可以接到如下的东西
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| var xx = 1; var yy = 2; var zz = 3; function show(a, b, c, d, e) { console.log(a); console.log(b); console.log(c); console.log(d); console.log(e); } show`this ${xx} is ${yy} a ${zz} iu`;
function show1(a, ...arr) { console.log(a); console.log(arr); }
show1`${xx} is ${yy} a ${zz} this`;
|