ECMAScript 6 常用特性整理
说明
看了 阮一峰 老师的 ECMAScript 6 入门,决定将之前一直使用到的 ES6 重新整理一遍。
1. let 和 const
-
用法类似 var
用来声明变量,但是声明的变量只在命令所在的代码块中有效
-
不存在变量提升
-
暂时性死区, 在变量用 let 声明前的代码中 只要使用到变量,就会报错
-
不允许重复声明变量
-
const 声明的是一个只读的常量,声明后值不可以改变
-
对于对象和数组来说,变量指向内存地址,保存的只是一个指针,const 声明的变量可以保证指针不变,但是指向的数据结构发生变化就是不可控的
2. 块级作用域
-
let 和 const 声明的变量存在块级作用于, ES6 允许块级作用域的任意嵌套,外层的作用域无法读取内层作用域的变量
-
应该避免在块级作用域内声明函数,如果需要声明函数,要使用函数表达式
3. 变量的解构赋值
解构赋值等号的右边需要时可遍历结构
1. 数组的解构赋值
let [a, [b], d] = [1, [2, 3], 4];
console.log(a, b, d);
let [f] = 121212;
console.log(f);
let [foo = true] = [];
console.log(foo);
let [x = 1] = [undefined];
let [y = 1] = [null];
console.log(x, y);
function f () {
console.log('aaa');
}
let [x = f()] = [1];
console.log(x);
let [x = 1, y = x] = [];
console.log(x, y);
let [x, y = x] = [1];
console.log(x, y);
let [x = y, y = 1] = [];
console.log(x, y);
- 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
- 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
2. 对象的解构赋值
let {a: aa} = {a: 1, b: 2};
console.log(aa);
let a = 12;
let [a] = [1, 2, 3];
console.log(a);
let a = 12;
let b;
[a] = [1, 2, 3];
({b} = {b: 1});
console.log(a, b);
let {0: fir, 1: sec} = [1, 2, 3];
console.log(fir, sec);
3. 字符串的解构赋值
let [a, b] = 'hello';
console.log(a, b);
let {length: len} = 'hello';
console.log(len);
4. 函数参数的解构赋值
function f([a,b]) {
return a + b;
}
console.log(f([1, 2]));
function f ({x = 'x', y = 'y'} = {}) {
console.log([x, y]);
}
f();
f({});
f({x: 1});
function f ({x, y} = {x: 'x', y: 'y'}) {
console.log([x, y]);
}
f();
f({});
f({x: 1});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
4. 字符串扩展
模板字符串
`hello hello`
`
hello hello
hello
`
`hello ${name} hello`
更多字符串方法 javascript字符串方法汇总
5. 数值的扩展
1. Number.isFinite() 是否为有限的
Number.isFinite(1);
Number.isFinite(NaN);
Number.isFinite(Infinity);
Number.isFinite(true);
2. Number.isNaN() 是否为 NaN
Number.isNaN(NaN);
Number.isNaN(15);
3. Number.parseInt(), Number.parseFloat() 移植到 Number 上了
4. Number.isInteger() 判断值是否为整数
Number.isInteger(3.3);
Number.isInteger(3.0);
5. Math.trunc() 除去数字的小数部分,返回整数部分 (内部使用 Number 方法装换为数值)
Math.trunc(123.22);
Math.trunc('123.22');
Math.trunc(true);
Math.trunc(null); 0
Math.trunc(undefined);
Math.trunc({});
Math.trunc([]);
Math.trunc('a123');
6. 数组的扩展
1. Array.from() 将类数组对象转换为真正的数组
let obj = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
}
const arr = Array.from(obj);
console.log(arr);
function f () {
const args = Array.from(arguments, (x) => x + '--add');
console.log(args);
}
f('a', 'c');
2. Array.of() 将一组数值转化为数组
const arr = Array.of(12,12,12);
console.log(arr);
3. find() findIndex() 找到第一个符合条件的数组成员,参数是一个回调函数,数组成员依次执行回调,直到第一个返回值为true的成员,然后返回此成员或者所在index,没有则返回undefined
const member = [22, 323, 424, -12, 0].find((value, index) => {
return value < 0;
})
console.log(member);
const member = [22, 323, 424, -12, 0].findIndex((value, index) => {
return value < 0;
})
console.log(member);
7. 函数的扩展
ES6 中的函数参数可以设置默认值,函数进行声明初始化的时候,参数会形成一个单独的作用域,初始化结束后这个作用域就会消失,这种行为在不设置参数默认值时是不存在的
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2)
let foo = 'outer';
function bar(func = x => foo) {
let foo = 'inner';
console.log(func());
}
bar();
1. rest 参数, 有点类似逆向的扩展运算符
function f (...args) {
console.log(args);
}
f(1, 2, [11, 22], function () {
console.log('in');
});
2. 扩展运算符, 将一个数组转为用逗号分隔的参数序列。
function f (a, b) {
console.log(a, b);
}
const arr = [123, 456];
f(...arr);
const arr1 = ['a', 'b', 'c'];
const arr2 = [1, 2, 3];
const arr = [...arr1, ...arr2];
console.log(arr);
const arr1 = ['a', 'b', 'c'];
const [fir, ...sec] = arr1;
console.log(fir, sec);
const arr1 = ['a', 'b', 'c'];
const [...fir, sec] = arr1;
console.log(fir, sec);
const arr = [...'hello'];
console.log(arr);
- 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
- 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
3. 严格模式
ES6 中的 严格模式可以设置成全局的,但是在函数中的严格模式需要函数参数不包含 默认值、解构赋值、扩展运算符,否则会报错
4. 箭头函数, 简化回调函数
- 函数体内的 this 对象 就是定义时所在的对象,不是使用时的对象
- 不可以当做构造函数,也就是不也已使用 new 命令
- 不可以使用 arguments 对象,不存在,可以用 rest 参数 代替
- 不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数
let f = x => x;
let f = () => 'test';
let f = (a, b) => a + b;
let f = (a, b) => {
let num = a + b;
return num;
}
8. 对象的扩展
let foo = 'foo';
let obj = {foo: foo};
let obj = {foo};
const obj = {
method(){
console.log('method');
}
}
1. ES6 允许表达式作为对象的属性名或者方法名
let prop = 'foo';
let obj = {
[prop]: true,
['a' + 'b']: 123
};
console.log(obj);
let prop = 'foo';
let obj = {
[prop]() {
console.log('obj.foo function');
}
}
obj.foo();
let foo = 'bar';
let bar = 'abc';
let obj = {
[foo]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
2. Object.is() 比较两个值是否相等,基本与 === 差不多
NaN === NaN
-0 === +0
Object.is(-0, +0)
Object.is(NaN, NaN)
3. Object.assign() 实现浅拷贝,用于合并对象,将源对象的所有可枚举属性,复制到目标对象
let target = {a: 1, b: 2};
let source1 = {b: 4, c: 8};
let source2 = {c: 6};
const a = Object.assign(target, source1, source2);
console.log(a);
console.log(target);
const defaultVal = {
level: 1,
type: 'html'
}
function f (options) {
options = Object.assign({}, defaultVal, options);
return options;
}
console .log(f({level: 2}));
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
4. 对象的扩展运算符
let {x, y, ...d} = {x: 'x', p: 'p', y: 'y', c: 'c'};
console.log(d);
let a = {x: '1212', y: '1222'};
let b = {z: 'zzz', y: '12ed'};
let ab = {...a, ...b};
console.log(ab);
9. Set
- Set 数据结构类似数组,但是成员的值都是唯一的,没有重复的值,可以用来数组去重
const set = new Set([1, 2, 1, 3 ,2 , 5]);
console.log([...set]);
set.add(123);
set.add(2);
console.log([...set]);
let arr = [1, 2, 1, 3 ,2 , 5, '5'];
const output = [...new Set(arr)];
console.log(output);
let arr = [1, NaN];
let set = new Set(arr);
console.log(set.size);
set.add(NaN);
const output = [...set];
console.log(output);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- set 实例的方法
let set = new Set([1, 2, 3, 2, 5]);
console.log(set.size);
set.add(8);
set.delete(5);
set.has(8);
set.clear();
for (let item of set.keys()) {
console.log(item);
}
for (let item of set.values()) {
console.log(item);
}
for (let item of set.entries()) {
console.log(item);
}
set.forEach((item, i) => {
console.log(item, i);
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- set 实现并集、交集、差集
let a = new Set([1, 2, 3]);
let b = new Set([4, 2, 3]);
const union = new Set([...a, ...b]);
console.log(union);
const intersect = new Set([...a].filter(x => b.has(x)));
console.log(intersect);
const diff = new Set([...a].filter(x => !b.has(x)));
console.log(diff);
10. Map
Object 对象是键值对的集合,但是传统上只能用 字符串做键,而 Map 结构上类似 Object 也是键值对的集合,但是键的范围不限制于字符串,各种类型的值都可以作为键,如果键的值是引用类型则,键实际上是指针指向的地址
const a = new Map();
const o1 = {name: 'xiaoming'};
const o2 = {name: 'xiaoming'};
a.set(o1, 'this is xiaoming');
console.log(a.has(o1));
console.log(a.get(o1));
console.log(a.get(o2));
o1.age = 23;
console.log(a.get(o1));
a.delete(o1);
console.log(a.has(o1));
const b = new Map([
['name', 'xiaoming'],
['age', 90]
])
console.log(b.has('name'));
console.log(b.has('age'));
console.log(b.size);
b.clear();
console.log(b.has('name'));
const b = new Map([
[{name: 'firstName'}, 'xiaoming'],
['age', 90]
])
for (let key of b.keys()) {
console.log(key);
}
for (let value of b.values()) {
console.log(value);
}
for (let item of b.entries()) {
console.log(item);
}
b.forEach(function (value, key, map) {
console.log(value, key);
})
- 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
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 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
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
11. Class
JavaScript 中,生成实例对象的传统方法是通过构造函数,es6 引入 Class 作为对象的模板,通过 Class 定义类,但是 es6 的 Class 只是一个语法糖,他只是在写法上更像面向对象编程的语法而已,es6 的类可以看做是构造函数的另外一种写法
class Parent {
constructor(x, y) {
this.attrs = {
a: 'a'
};
}
state = {
name: 'state name'
};
show() {
}
static classAttr = 'class attr';
static classMethod() {
console.log('static');
}
}
Parent.classMethod();
console.log(Parent.classAttr);
const parent = new Parent();
console.log(Parent.name);
console.log(parent.state);
console.log(parent.attrs);
console.log(parent.__proto__ === Parent.prototype);
console.log(parent.__proto__.constructor === Parent);
console.log(Parent.prototype);
const MyClass = class me {
getClassName() {
return me.name
}
}
const a = new MyClass();
console.log(a.getClassName());
- 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
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 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
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
类的继承,(extends)
- es5 的继承,实质上是先创建子类的实例对象 this ,然后将父类的方法添加到 this 上
- es6 的继承机制完全不同,实质上是先创建父类的实例对象 this (所以必须先调用super方法),然后再用子类的构造函数修改 this,子类中只有调用了 super 方法之后 才可以使用 this 关键字
class Parent {
constructor(name) {
this.name = name;
}
logName(newName) {
console.log(newName);
}
}
class Child extends Parent {
constructor(age, name) {
super(name);
this.age = age;
}
logAge() {
console.log(this.age)
}
logName() {
console.log('this is in Child');
}
logInfo() {
this.logName(this.name);
super.logName(this.name);
this.logAge();
}
}
console.log(Child.prototype.constructor === Child);
const child = new Child(20, 'xiaobai');
child.logInfo();
- 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
- 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
更多文章