ES6快速指南
let/const
-
let 变量声明标识,与var类似,但是***let***声明的变量只在所在的代码块中有效,不存在作用域提升
{ var a = 20; let b = 10; } console.log(a); // 20; console.log(b); // Uncaught ReferenceError: b is not defined
-
同一个名称的变量再同一个作用域内只能用let申明一次, 被var 声明过的变量可以被let二次声明,但是被let声明过的变量不允许再被var 二次申明
var b = 10; var b = 20; let a = 1; let a =2; // Identifier 'a' has already been declared var b = 30; // Identifier 'a' has already been declared
箭头函数
es6 允许 使用 =>
定义函数,他与function声明的函数功能无异,但是他具有一下特点
-
箭头函数内部的this只与函数声明位置的上下文有关,不会不会随着调用者改变
function hello() { setTimeout(() => { console.log("arrow::,this.a); },1000) setTimeout(function (){ console.log("function:",this.a); },1000) } let obj = { a:1,hello }; obj.hello(); // arrow: 1 // function: undefined // 由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向 hello.call({ a:100},hello); // arrow: 100 // function: undefined
-
箭头函数的函数体如果只有一行,可以省略{},这一行的执行结果将作为函数的返回值 (与C#中的lamda表达式类似)
let foo = () => 'bar'; foo(); // bar;
-
箭头的函数的参数列表如果只有一个参数可以省略(),如果没有参数就必须带()
let hello = name => console.log("hello,",name,"!"); hello("world"); // hello, world !
-
箭头函数不再有 arguments, super, new.target,caller,callee 隐式参数。
(function() { console.log(...arguments); })("a","b"); // a b (() => { console.log(...arguments); })("a","b"); // Uncaught ReferenceError: arguments is not defined let hello = () => { console.log(hello.caller) }; hello(); // 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
解构语法
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
```javascript
// 数组解构
let [a,b,c] = [1,2,3,4];
console.log(a,b,c); // 1 2 3
// 对象解构
let { foo,name } = {foo:"bar", name:"bug4j"};
console.log(foo, name) // bar bug4j
```
解构语法实际是上可以堪称上是一种模式匹配复制,只要 = 左右的模式解构匹配上了,就可以正确的给变量复制
let [a,[[b]],[c]] = [1,[[2,3,4]],[5],6];
console.log(a,b,c); // 1 2 5
= 左右的模式不要求完全匹配,如果模式没有匹配上,则变量的值为undefined,
let [a, b, c ] = [1,2];
console.log(a,b,c); // 1 2 undefined
对象解构只对属性名称和嵌套关系进行匹配,与顺序无关
… (spread) 运算符
-
对于数组(set),spread 运算符用来将一个数组转为用逗号分隔的参数序列
let arr = [1,2,3,4,5]; let set = new Set(["a","b"]); console.log([...arr,...set]); // 1 2 3 4 5 a b
-
对于key-value对象,可以将目标对象自身的所有可遍历的(enumerable)、分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面
let obj = { foo:"bar"}; let obj1 = { ...obj,"hello":"world"}; console.log(obj1); // {foo: "bar", hello: "world"}
-
配合解构语法使用,可以将目标对象在当前解构表达式中没有被读取的可枚举属性拷贝到指定的变量中
let { a,b,...c} = { a:1,b:2,x:3,y:4 }; console.log(c);// {x: 3, y: 4}
-
spread和解构语法一样,只是对目标对象属性进行浅拷贝
let obj = { a:1,b:{ c:2,d:3} }; let { b } = obj; let obj1 = { ...obj,d:100}; console.log(obj.b === b); // true console.log(obj.b === obj1.b); // true
-
key-value对象中使用spread运算符时, 后面(右边或者下边)的表达式中出现的属性会覆盖 前面(左边或者上边)表达式中的属性值
let a = { a:1,b:2}; let b = { a:3,c:4}; let obj = { ...a,...b,c:"c" }; console.log(obj); // {a: 3, b: 2, c: "c"}
-
spread 运算符只能处理对象中可枚举的属性
let obj = { a:1,b:2}; Object.defineProperty(obj,"c",{ value:"c",enumerable:false}); console.log(obj); // {a: 1, b: 2, c: "c"} console.log({ ...obj }); // {a: 1, b: 2}
对象属性定义简化操作
在定义对象时,如果对象属性名称与赋值变量名称一致时,允许简化:
let App = defineAsyncComponent(() => import App from '@/App.js');
let components = {
App };
new Vue({
components }).mount("#app");
// 相当于
let components = {
App:App };
new Vue({
components:components }).mount("#app");
可选运算符与可选运算符链和空值运算符
通常情况下,一个对象如果有多层属性嵌套,在读取这个对象内部的一个属性值时,我们都需要判断这个属性的上一层属性是否为null从而避免空指针错误:
let obj = {
a:{
b:{
c:1 } } };
let val = obj.a.b.c; // 可能会报错
let val1 = ((obj.a || {
}).b || {
}).c; // 不会报错
// 或者
val1 = (obj.a && obj.a.b && obj.a.b.c) ? obj.a.b.c : undefined;
// 或者 使用三元运算符 ? :
一旦对象属性层级较深,这种判断就很乱容易出错,es6 提供一个 可选运算符(?.
)来解决这种问题:
let obj = {
a:{
b:{
c:1 } } };
let val = obj.a?.b?.c;
// 或者
val = obj.a?.["b"]?.["c"];
可选运算符也可以用于函数的判断调用:
let obj = {
};
obj.hello?.(); // undefined
// 如果obj中存在hello,单数hello并不是一个函数,任然会报错
函数的可选参数(参数默认值)和可变参数
-
参数默认值
es6之前如果调用函数时,某个参数没有传值,会给这个参数分配undefined, 想要有默认值只能采用一下方法:
function hello(x,y) { x = x || 1; y = y || 2; }
这种方法有个缺点,如果 x 的值 为 false, 0 或者 “”, x 也会被赋予默认值0
function hello(x) { x = x || 1; console.log(x); } hello(false); // 1 hello(0); // 1 hello(""); // 1
要避免这种问题,实际上只能先判断是否为这些产生干扰的值,
es6 允许为函数参数设置默认值来解决这个问题:
function hello(x,y = 0) { console.log(x + y); } hello(2); // 2
可选参数的位置虽然没有语法限制,但是一般在形参列表的末尾,如果不在末尾,实际上参数是不可以省略的,省略会导致可选参数后面的参数取值不符合预期
-
可变参数
在java中,允许方法将不确定个数的多个同类型参数归并成一个指定类型的数组参数,es6中也允许类似的操作,不同的是,由于javascript 是一种弱类型的语言,可变参数的类型并没有特别规定:
(function(x,y,...rest) { console.log(rest); })(1,2,3,"a",{ foo:"bar"},false); // [3, "a", { foo:"bar" }, false]
可选参数后面不能在声明其他参数,否则会报错
字符串新增方法
- includes(), startsWith(), endsWith()
- repeat()
- padStart(),padEnd()
- trimStart(),trimEnd()
- matchAll()
- replaceAll()
字符串模板
字符串模板允许直接申明一个多行字符串,并且可以通过${}
在字符串中插入变量
es6 之前,在js中的写法:
var str = "<div>" +
"<div class='label'>姓名:</div><div class='value'>"+ name +"</div>" +
"<div class='label'>年龄:</div><div class='value'>"+ age +"</div>" +
"</div>"
使用es6模板字符串:
let str = `<div>
<div class='label'>姓名:</div><div class='value'>${
name }</div>
<div class='label'>年龄:</div><div class='value'>${
age + 1 }</div>
</div>`;
模板字符串可以嵌套,${}
中可以书写任何有效的es6表达式:
let adultActivities = ["抽烟","喝酒","烫头"];
let childrenActivities = ["好好学习"]
let str = `你的年龄为:${
age },你是个${
age >= 18 ? `成年人, 你可以${
adultActivities.join(",")}啦` : `未成年,你可以${
childrenActivities.join(",")}`}!`;
数组新增方法
Array.from(): 将类数组解构转换为数组
Array.of(): 将一系列值包装到一个数组中
find() 和 findIndex() : 元素搜素
includes(): 判断数组是否包含元素
flat(),flatMap(): 数组降维打击
旧版本的方法 : some(), every(), filter(), reduce(),shfit(),splice(),pop():
let arr1 = Array.from($("div"));
let arr2 = Array.of(1,"a",2);
let arr3 = [1,2,[3,[4,5,[6,7]],8]].flat(3); // [1, 2, 3, 4, 5, 6, 7, 8]
let n = [1,2,3,4].find(n => n>=3 ) // 3
let index = [0,1,2,3,4].find(n => n>=3 ) // 4
let incls = [0,1,2,3,4].includes(6) // false;
let someRes = [0,1,2,4].some(n => (n %