es6basic

ES6 新增声明方式与各种扩展

为了提高开发效率,语言设计者从原生上支持了许多快捷高效的新操作。故推出称为新一代标准 ES6

let 和 const

let

块级作用域

let 声明的变量只在当前块有效,适用于 for 循环、if 条件句等等

  • 另外,es6 规定块级作用域必须要有大括号,否则就认为没有块级作用域

  • 在 for 循环中,定义循环变量的地方可以为父作用域,而循环体又可以为子作用域

1
2
3
4
5
6
7
8
9
10

for(let i = 0; i < 3; i++) {
let i = "Great";
console.log(i);
}
// Great
// Great
// Great
console.log(i);
//Uncaught ReferenceError: i is not defined

没有变量提升

  • 用 var 来定义变量时,有时存在提升,即可以在声明之前调用不报错但会返回 undefined ;但是 let 不行,必须在声明之后使用,否则就会报错

  • ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错

  • 另一方面,若是由 var 声明的变量又被 let 重新声明,那么在这次重新声明之前调用也会报错,这被称为暂时性死区,typeof 使用在声明之前也会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
console.log(a);//undefined  
console.log(b);//Uncaught ReferenceError: b is not defined
var a = 3;
let b = 7;
//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
var c = 3;
console.log(c);//3
c = 5;
console.log(typeof c);//number
if(true) {
c = 0; // Uncaught ReferenceError: Cannot access 'c' before initialization
let c = 4;
}

不允许重复声明

在同一作用域里,不允许重复声明一个变量

1
2
3
4
5
6
7
8
9
10
11
12
13
var a = 1;  
let a = 3;// dentifier 'a' has already been declared
if(true) {
let a = 5;
console.log(a);// 5
let c = 4;
let c = 7;// dentifier 'c' has already been declared
}

function G(arg) {
let arg = 1;
}
G(3);// Identifier 'arg' has already been declared

建议多使用 let 命令,因为它与 var 的作用几乎相同,但是 let 的规定更严格,也更符合先声明后使用的规则

const

  • 一经定义就要赋值,赋值后不能再次改变其值

  • 与 let 一样,存在块级作用域,并且也要在声明之后使用,没有变量提升,存在死区现象

  • 但是如果定义的是对象常量,则可以改变对象的属性,因为 const 此时存的是对象的指针,并不是其中所以属性的值

globalThis

用来获取当前宿主环境的全局作用域对象

解构赋值

数组-变量-的解构赋值

传统的赋值很繁琐,利用解构赋值可以像 python 那样快速赋值;同时还允许使用默认值类似函数的参数默认值

1
2
3
4
5
6
7
8
9
10
11
12
13
//原始  
let a = 1;
let b = 2;
let c = 3;

//解构赋值
let \[a, b, c\] = \[1, 2, 3\];
console.log(a, b, c);//1 2 3

//默认值
let \[x, y = 15\] = \[13\];
let \[x1, y1 = 15\] = \[13, 17\];
console.log(x, y, x1, y1);//13 15 13 17

对象的解构赋值

与数组解构类似,甚至可以嵌套赋值非常方便

1
2
3
4
5
6
7
8
9
10
11
let {name, age, getName, obj, obj: {number}} = {  
name: 'Great',
age: 21,
getName(s) { //es6简写
return s;
},
obj: {
number: 17
},
};
console.log(name, age, getName('tiga'), obj, number);//Great 21 tiga {number: 17} 17

字符串解构赋值

1
2
3
let \[a,b,c,d,e\]  = "Great";  
let {length: len} = "Tiga";
console.log(a,b,c,d,e,len);//G r e a t 4

字符串扩展

模板字符串

使用反撇号 ` ,可当做普通字符串,也可以在其中嵌套任何 JS 表达式包括调用函数

1
2
3
4
5
6
7

1
2
3
4
5
6
7
var a = 1;  
console.log(\`${a \* 10} 减去 ${a \* 5} 等于 ${a \* 10 - a \* 5}\`);//10 减去 5 等于 5

function Great(s) {
return s;
}
console.log(\`我叫${Great('Greatiga')}\`);//我叫Greatiga

函数扩展

参数默认值

允许在参数传递时设置参数默认值,当调用函数没用提供参数时就用默认参数,否则还是用提供的参数

  • 设置参数默认值后,默认值会形成一个自己的作用域直到参数初始化完毕
  • 比如 (x = 1) 实际上执行的是 (let x = 1)
1
2
3
4
5
function Person(name = 'Great', age = 21) {  
console.log(name, age);
}
Person();// Great 21
Person('Tiga', '3000');// Tiga 3000

rest 参数

其实就是对象展开符,形式 …变量,rest 参数后不能再有其他参数

1
2
const k = (...arg) => arg.sort();  
k(1,0,4,2,9,7);// (6) \[0, 1, 2, 4, 7, 9\]

箭头函数

简化了函数原来的写法

  • 如果箭头函数不需要参数或者多个参数,可以使用圆括号包裹
  • 如果函数体多于一条语句,那么可以用大括号包裹起来,但是需要用 return 语句返回
1
2
3
4
5
6
7
8
9
10
console.log(\[1,2,3\].map(item => item \* 10));// \[10, 20, 30\]  
let sum = (x, y) => {
if(x) {
return y;
}
else {
return x + y;
}
}
console.log(sum(1,2));// 2
  • 箭头函数的 this 指向初始化它的时候的执行对象,并非是调用它的时候的执行对象;这一点与普通函数不同
  • 不能当成构造函数,使用 new 会报错
  • 不能使用 arguments 对象,可以使用 rest 参数代替
1
2
3
4
5
6
7
8
9
10
11
let x = 21;  
var sum = function(){
console.log(this.x);
setTimeout(() => {
console.log(this.x);
},1000);
}
sum.call({x : 3000});
//3000
//1s 后
//3000

数组和对象的扩展

数组扩展

数组扩展运算符

这个对于对象同样适用。同时只有函数调用时才能适用圆括号包裹,否则会报错

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
32
33
34
35
36
37
38
39
40
41
42
let x = [1, 2, 3, 4, 5];  
console.log(...x);//1 2 3 4 5

let y = [...x];
console.log(`可以使用克隆${y}`);//可以使用克隆1,2,3,4,5

let z = [0, ...x, 6];
console.log(`可以简洁的合并数组${z}`);//可以简洁的合并数组0,1,2,3,4,5,6

let [a, b, ...c] = x;
console.log(\`可以简洁的拆分数组\n a: ${a} \n b: ${b} \n c: ${c}`);
// a: 1
// b: 2
// c: 3,4,5
```

### Array.from() 和 Array.of()

* Array.from() 用于将类数组转换为真的数组
* Array.of() 用于将一组值转换为数组

## 对象扩展 "对象扩展")对象扩展
--------------------

### super关键字

> 指向当前对象的原型对象,只能在对象的内部方法中使用

### 对象扩展运算符

> 用法与数组类似

### 对象的复制拷贝

> 使用 **Object.assign()**,但只是浅拷贝

```javascript
let a = {x : 13};
let b = {y : 17};
let c = {z : 19};
Object.assign(c, a, b);
console.log(c);//{z: 19, x: 13, y: 17}

新增对原型对象的操作

主要用来替代 __proto__

  • Object.setPrototypeOf(obj, prototype) 设置某一个对象的原型对象
  • Object.getPrototypeOf(obj) 获取某一个对象的原型对象
Author: Greatiga
Link: http://example.com/es6/es6basic/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.