1.let、const
es6之前只有全局作用域和函数作用域,es6新增块级作用域。let、const 允许创建块级作用域。
let关键词声明变量,特点:代码块内有效、不能重复声明、不存在变量提升。
const声明常量,其实 const 其实保证的不是变量的值不变,而是保证变量指向的内存地址所保存的数据不允许改动。对于复杂类型(对象 object,数组 array,函数 function),这个「常量」并非一成不变的,如:
var a = 2;
{
let a = 3;
console.log(a); // 3
}
console.log(a); // 2
const ARR = [5,6];
ARR.push(7);
console.log(ARR); // [5,6,7]
ARR = 10; // TypeError
2. 数组和对象解构
解构可以避免在对象赋值时产生中间变量
// 数组结构
let [a, b, c] = [1, 2, 3]; // a=1,b=2,c=3
let [a, [[b], c]] = [1, [[2], 3]]; // a=1,b=2,c=3
let [, , d] = [1, 2, 3]; // d = 3
let [e, ...n] =[1, 2, 3]; // e = 1, n = [2,3]
let [a = 1, b] = []; // a = 1, b = undefined
let [a, b, c, d, e] = 'hello'; // a='h' b='e' c='l' d='l' e='o'
// 当解构模式有匹配结果,且匹配结果是 undefined 时,会触发默认值作为返回结果。
let [a = 3, b = a] = []; // a = 3, b = 3
let [a = 3, b = a] = [1]; // a = 1, b = 1
let [a = 3, b = a] = [1, 2]; // a = 1, b = 2
const str = '/foo/sec/thr';
const [, first] = str.split('/');
console.log(first); // foo
// 对象结构
let {name, age} = {name: 'vae', age: 18}; // name='vae' age = 18
let {p: [x, { }] } = {p: ['hello', {y: 'world'}] }; // x = 'hello'
let obj = {p: [{y: 'world'}] };
let {p: [{ y }, x ] } = {p: [{y: 'world'}] }; // x=undefined y='world'
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}; // a=10 b=20 rest={c:30,d:40}
let {a = 10, b = 5} = {a: 3}; // a=3 b=5
let {a: aa = 10, b: bb = 5} = {a: 3}; // aa=3 bb=5
//重命名(命名冲突时解决方法)
const name = 'jack';
const { name: newName } = { name: 'vae', age: 18 };
console.log(name); // jack
console.log(newName); // vae
3.模板字符串
${ ... }
用来渲染一个变量
支持换行
const name = 'tom';
const str = `hello, this is ${name} ------- ${1+3}`; // str = 'hello, this is tom ------- 4'
带标签的模板字符串(可用于调整字符串内顺序)
const name = 'tom';
const gender = true;
function myFunTag(strings, name1, gender1) {
console.log(strings, name1, gender1); // ['hello es2015 ', ' is a ', ''] tom true
return strings[2] + name1 + strings[0] + gender1 + strings[1]; // 可以对字符串顺序进行调整;
}
const str = myFunTag`hello es2015 ${name} is a ${gender}`;
console.log(str); // tomhello es2015 true is a
4.字符串的扩展方法
- includes() 是否包含某个字符串
- startsWith() 是否以某个字符串开头
- endsWith() 是否以某个字符串结尾
- repeat(param) 将字符串重复指定次数返回
- padStart() 用 参数字符串 从头部(左侧)补全原字符串
- padEnd() 用 参数字符串 从尾部(右侧)补全原字符串
const message = 'Error: this is start with arr';
console.log(message.includes(':')); // true
console.log(message.startsWith('Error')); // true
console.log(message.endsWith('arr')); // true
console.log("Hello,".repeat(2)); // 'Hello,Hello,'
/***参数是小数,向下取整***/
console.log("Hello,".repeat(3.2)); // "Hello,Hello,Hello,"
/***参数是 0 至 -1 之间的小数,会进行取整运算,0 至 -1 之间的小数取整得到 -0,等同于0***/
console.log("Hello,".repeat(-0.5)); // ""
/***参数是 NaN,等同于0***/
console.log("Hello,".repeat(NaN)); // ""
/***参数是负数或者 Infinity ,会报错***/
console.log("Hello,".repeat(-1)); // RangeError: Invalid count value
/***参数是字符串,则会先将字符串转化为数字***/
console.log("Hello,".repeat("hh")); // ""
console.log("Hello,".repeat("2")); // "Hello,Hello,"
/***第一个参数是指定生成的字符串的最小长度,第二个参数是用来补全的字符串.默认用空格填充**/
console.log("h".padStart(5,"o")); // "ooooh"
console.log("h".padEnd(5,"o")); // "hoooo"
console.log("h".padStart(5)); // " h"
/***指定的长度 小于或等于 原字符串的长度,则返回 原字符串**/
console.log("hello".padStart(5,"A")); // "hello"
/***原字符串加上补全字符串长度 大于 指定长度,则截去超出位数的补全字符串**/
console.log("hello".padEnd(10,",world!")); // "hello,worl"
5.函数参数默认值
function foo(enable = true, bar) { // enable默认值true
console.log(enable);
console.log(bar);
}
foo(); // true undefined
foo(false); // false undefined
foo(false, 123); // false 123
6.函数剩余参数、对象的新方法
-
Object.assign() 将多个源对象中的属性复制到一个目标对象当中(属于浅拷贝)
-
Object.is 判断值是否相等
function foo(bar, ...args) { // ...args只允许放在最后
console.log(bar); // 1
console.log(args); // [2,3,4]
}
foo(1,2,3,4);
//展开数组
const arr = ['foo', 'bar', 'str'];
console.log(
arr[0], arr[1], arr[2]
);
console.log.apply(console, arr);
console.log(...arr); // foo bar str
const source = {a: 123,b: 234}
const target = {b: 456,c: 567}
const resut = Object.assign(target, source); // 第一个参数为目标对象, 后边参数属性会覆盖前边的
console.log(target);
console.log(resut) // {b: 234, c: 567, a: 123}
console.log(target === resut); // true
console.log(Object.is(+0, -0)); // false
console.log(Object.is(NaN,NaN)); // true
NaN === NaN; // false
7.对象词法扩展
- 允许声明在对象字面量时使用简写语法,来初始化属性变量和函数的定义方法
- 允许在对象属性中进行计算操作
const bar = '123';
const obj = {
name: '1111',
bar, // 等同于bar: bar
method() { // 省略 `function` 关键词简写对象函数
console.log('method');
},
[Math.random()]: '123' //属性可以使用表达式计算值
}
8.Proxy
- Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。即Proxy在目标对象之前添加一个‘拦截器’,任何对该对象的访问都必须先通过这个拦截,因此可以在拦截这对外界的访问进行过滤和改写。
-
一个 Proxy 对象由两个部分组成: target 、 handler 。target 即目标对象, handler 是一个对象,用来定制拦截行为。
-
Proxy支持的拦截操作,共13种:(带?的参数为可选参数)
- get(target, propKey, receiver?):拦截对象属性的读取,比如
proxy.foo
和proxy['foo']
。
target-----目标对象 propKey-----属性名 receiver-----proxy实例本身(即操作行为所针对的对象) - set(target, propKey, value, receiver?):拦截某个属性的赋值操作,比如
proxy.foo = v
或proxy['foo'] = v
,返回一个布尔值。
target-----目标对象 propKey-----属性名 value----属性值 receiver-----proxy实例本身(即操作行为所针对的对象) - has(target, propKey):拦截
HasProperty
操作,即判断是否具有某个属性,返回一个布尔值。
target-----目标对象 propKey-----属性名 - deleteProperty(target, propKey):拦截
delete proxy[propKey]
的操作,返回一个布尔值(如果这个方法抛出错误或者返回false
,当前属性就无法被delete
命令删除)。 - ownKeys(target):拦截对象自身属性的读取操作,包含
Object.getOwnPropertyNames(proxy)
、Object.getOwnPropertySymbols(proxy)
、Object.keys(proxy)
、for...in
循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名。
注意: 使用Object.keys()
时,目标对象上不存在的属性、属性名为 Symbol 值、不可遍历(enumerable
)的属性 这三类属性会被ownKeys()自动过滤,不会返回。 - getOwnPropertyDescriptor(target, propKey):拦截
Object.getOwnPropertyDescriptor()
,返回属性的描述对象或undefined。 - defineProperty(target, propKey, propDesc):拦截
Object.defineProperty
,返回一个布尔值。0
注:(1)如果目标对象不可扩展(non-extensible),则defineProperty()
不能增加目标对象上不存在的属性,否则会报错。
(2)如果目标对象的某个属性不可写(writable)或不可配置(configurable),则defineProperty()
方法不得改变这两个设置。 - preventExtensions(target):拦截
Object.preventExtensions(proxy)
,返回一个布尔值(只能返回布尔值,否则返回值会被自动转为布尔值)。 - getPrototypeOf(target):拦截用来拦截获取对象原型,返回一个对象。如:
Object.getPrototypeOf(),Object.prototype.__proto__,Object.
prototype.isPrototypeOf(),Reflect.getPrototypeOf(),instanceof。 - isExtensible(target):拦截
Object.isExtensible(proxy)
,返回一个布尔值。 - setPrototypeOf(target, proto):拦截
Object.setPrototypeOf(proxy, proto)
,返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。 - apply(target, object, args):拦截函数调用、
call
和apply
操作,比如proxy(...args)
、proxy.call(object, ...args)
、proxy.apply(...)
。
target-----目标对象 object-----目标对象的上下文(this) args------目标对象的参数数组 - construct(target, args,newTarget):拦截 Proxy 实例作为构造函数调用的操作(new命令),比如
new proxy(...args)
。
注:construct()
方法返回的必须是一个对象;它的目标对象必须是函数;construct()
方法中的this
指向的是handler
,而不是实例对象;
target-----目标对象 args------鼓噪函数的参数数组 newTarget------创造实例对象时,new
命令作用的构造函数
Proxy.revocable()
方法返回一个可取消的 Proxy 实例。
使用场景:目标对象不允许直接访问,必须通过代理访问,一旦访问结束,就收回代理权,不允许再次访问。
const person = {name: 'nick',age: 20}
const personProxy = new Proxy(person, {
get(target, property) {
return property in target ? target[property] : undefined;
},
set(target, property, value) {
console.log(target);
console.log(property);
console.log(value);
target[property] = value;
}
})
console.log(personProxy.name);
personProxy.age = 200; // 赋值
personProxy.gender = 'aaa';
var target = function () { return 'I am the target'; };
var p = new Proxy(target, {
apply: function () {
return 'I am the proxy';
}
});
p(); // 'I am the proxy'
var handler = {
has(target, key) {
if (key[0] === '_') {
return false;
}
return key in target;
}
};
var target = { _prop: 'foo', prop: 'foo' };
var proxy = new Proxy(target, handler);
'_prop' in proxy // false
'prop' in proxy // true
阮一峰--ECMAScript6入门 --- 更多关于Proxy的信息
9.Reflect
Reflect也是为了操作对象而提供的新的API,共有13个静态方法,同Proxy.
作用:
- 将
Object
对象的一些明显属于语言内部的方法(比如Object.defineProperty
),放到Reflect
对象上。未来新的方法只部署在Reflect对象上。 - 修改某些
Object
方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)
在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)
则会返回false
。 - 让
Object
操作都变成函数行为。某些Object
操作是命令式,比如name in obj
和delete obj[name]
,而Reflect.has(obj, name)
和Reflect.deleteProperty(obj, name)
让它们变成了函数行为。
10. promise
11. class类
// 传统写法
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
// es6
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
构造方法constructor即对应ES5的构造函数Point。
- 类的数据类型就是函数,类本身就指向构造函数。
- 构造函数的
prototype
属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype
属性上面。 - 类的内部所有定义的方法,都是不可枚举的(non-enumerable)。
- 与 ES5 一样,实例的属性除非显式定义在其本身(即定义在
this
对象上),否则都是定义在原型上(即定义在class
上) - 与 ES5 一样,类的所有实例共享一个原型对象。
- 在“类”的内部可以使用
get
和set
关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
12.类的继承
Class 通过extends
关键字实现继承,
13.静态方法
14. Map(另:map与各类型的转换)
Map 数据结构类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
作为构造函数,Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
操作方法:
- set(key, val) 设置key对应的值为val
- get(key) 读取key对应的值
- has(key) 某个键是否在当前 Map 对象之中
- delete(key) 删除某个键,返回true。若删除失败返回false
- clear() 清除所有成员,没有返回值
遍历方法:
Map.prototype.keys()
:返回键名的遍历器。Map.prototype.values()
:返回键值的遍历器。Map.prototype.entries()
:返回所有成员的遍历器。Map.prototype.forEach()
:遍历 Map 的所有成员。
15.Set
Set
本身是一个构造函数,用来生成 Set 数据结构。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Array.from
方法可以将 Set 结构转为数组。
操作方法:
Set.prototype.add(value)
:添加某个值,返回 Set 结构本身。Set.prototype.delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功。Set.prototype.has(value)
:返回一个布尔值,表示该值是否为Set
的成员。Set.prototype.clear()
:清除所有成员,没有返回值。
遍历方法:(Set
的遍历顺序就是插入顺序)
Set.prototype.keys()
:返回键名的遍历器Set.prototype.values()
:返回键值的遍历器Set.prototype.entries()
:返回键值对的遍历器Set.prototype.forEach()
:使用回调函数遍历每个成员
const set = new Set([1, 2, 3, 4, 4]);
console.log(set); // Set{1,2,3,4}
console.log([...set]) // [1,2,3,4]
console.log(set.size); // 4
// 去除字符串里面的重复字符
[...new Set('ababbc')].join('') // "abc"
const array = Array.from(set); //[1,2,3,4]
16. Symbol (js语言第七种数据类型)
Symbol 表示独一无二的值,最大的用法是用来定义对象的唯一属性名。 Symbol() === Symbol() // false
Symbol
函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol
函数的返回值是不相等的。Symbol('foo') === Symbol('foo') // false
- Symbol 值不能与其他类型的值进行运算,会报错
- Symbol 值可以显式转为字符串。 Symbol('foo').toString() // Symbol(foo)
- Symbol 值也可以转为布尔值,但是不能转为数值。 !Symbol() === false // true
- Symbol 作为属性名,遍历对象的时候,该属性不会出现在
for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。 Object.getOwnPropertySymbols()
方法,可以获取指定对象的所有 Symbol 属性名。Reflect.ownKeys()
方法可以返回对象中所有类型的键名,包括常规键名和 Symbol 键名。Symbol.for()
接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。Symbol.keyFor()
方法返回一个已登记的 Symbol 类型值的key
。
17.for...of循环
for 遍历数组
for...in.. 遍历键值对
数组forEach
for...of 可以遍历任意数组结构数据(对象不可遍历)
(数组、Set、Map 内部都实现了Iterator方法)
18. Iterator迭代器
19.生成器Generator
目的: 在复杂的异步代码中减少回调函数嵌套产生的问题。提供更好的异步编程方案。
20. 模块module
- 个人总结,如有错误请评论指正,共同学习提升。