ECMAScript 2015(ES6)
一般说的ES6泛指ES2015之后的新功能和特性,ES2016、ES2017、ES2018等
let和const块级作用域
let:
- let 作用域在块儿中;
- 无变量提升,使用前必须声明;
const:
- 声明一个恒量、常量
- 一单声明内存指向不可修改(只读)
- 其他同let
数组与对象的解构
看代码
const arr = [100, 200, 300]
const [foo, bar, baz] = arr
console.log(foo, bar, baz)
// 100, 200, 300
-----------------对象----------------
const obj = { name: 'zce', age: 18 }
const { name } = obj
console.log(name)
// zce
------------------------------------
// const name = 'tom'
// const { name: objName = 'jack' } = obj
// console.log(objName)
// zce
模板字符串
``符号前可加标签,类似将字符串传入一个函数,参入如下
const name = 'tom'
function myTagFunc (strings, name) {
console.log(strings, name)
return strings[0] + name + strings[1]
}
const result = myTagFunc`hey, ${name}`
console.log(result)
// [ 'hey, ', '' ] tom
// hey, tom
- String.startsWith(’’);是否以什么开始
- String.endsWith(’.’);是否以什么开始
- String.includes(’’);是否包含什么
函数参数默认值
// 默认参数一定是在形参列表的最后
function foo (enable = true) {
console.log(enable)
}
foo('2');
foo(false)
------------------------------
// 剩余参数
// function foo () {
// console.log(arguments)
// }
function foo (first, ...args) { //利用...
console.log(args)
}
foo(1, 2, 3, 4)
扩展运算符(spread)
const arr = ['foo', 'bar', 'baz']
console.log(...arr)
// foo bar baz
箭头函数
注意:this.指向,其相当于一个变量永远指向该箭头函数外层的this;
MDN解释:(箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this)
对象的扩展
const bar = '345', str = 'methods';
const obj = {
bar, // 属性名与变量名相同,可以省略: bar
method1 () { }, // 方法省略写
[str]: 123 // 可直接用方括号创建动态属性名
}
console.log(obj)
Object.assign()
Object.assign();方法用于将所有可枚举属性的值从一个或多个源对象(source)分配到目标对象(target)。
它将返回目标对象。方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
Object.assign(target,source,source,…)
Proxy(对象代理器)
同Object.defineProperty()
// 对象代理器
const per = {
name: 'zhangsan',
age: 18
}
const perProxy = new Proxy(per,{
get(target, prop) { // 读取监听
// console.log(target, prop)
return prop in target ? target[prop] : '默认值'
},
set(target, prop, value, ) { // 设置监听
// console.log(target, prop, value);
target[prop] = value;
}
})
// perProxy及为代理对象
perProxy.gender = 23;
console.log(perProxy.abc);
对比 Object.defineProperty()
1、相比defineProperty,Proxy有更多的操作,defineProperty只能监视属性的读写;
Proxy的操作
- get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy[‘foo’]。
- set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy[‘foo’] = v,返回一个布尔值。
- has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
- deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
- ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for…in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
- getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
- defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
- preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。
- getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。
- isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。
- setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
- apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(…args)、proxy.call(object, …args)、proxy.apply(…)。
- construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(…args)。
2、Proxy更好的对数组对象的监视,
push()、pop()、。。。
3、Proxy以非侵入的方式监管了对象的读写
不需要对对象本身做任何操作,用另一个对象去监管他,而defineProperty不行,或很麻烦。
注意:Proxy代理后对象后,原对象中的this都指向该Proxy
Reflect
是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与proxy handlers的方法相同。Reflect不是一个函数对象,因此它是不可构造的。
它的方法与Proxy完全相同,其意义在于提供了一套统一的操作对象的API。
Promise
Class类
class Person {
constructor (name) {
this.name = name
}
say () { //实例方法
console.log(`hi ${this.name}`)
}
static age() { }//静态方法
}
const p = new Person('tom')
----------------------------------
// 继承
class Student extends Person {
constructor (name, number) {
super(name) // 父类构造函数指向父类,将父类需要的参数传给父类
this.number = number
}
hello () {
super.say() // 调用父类成员
console.log(`my school number is ${this.number}`)
}
}
const s = new Student('jack', '100')
s.hello()
Set
它类似于数组,但是成员的值都是唯一的,没有重复的值。
经常被用来去重
const arr = [1, 2, 1, 3, 4, 1]
const result = Array.from(new Set(arr))
---------------或者----------------
const result = [...new Set(arr)]
Map
对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。
可以用任意值作为键的特殊对象。
Symbol
表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
避免创建对象方法是键值重复,覆盖
注意
1、使用Symbol作为对象的属性名时,只有Object.getOwnPropertySymbols()才能拿到;
2、Symbol.for可以创建相同的Symbol值
const s1 = Symbol.for('foo')
const s2 = Symbol.for('foo')
console.log(s1 === s2) //true
Symbol.for(true) === Symbol.for('true') //true 内置调用toString方法转为字符串
3、Symbol在ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。
例如:Symbol.toStringTag
const obj = {
[Symbol.toStringTag]: 'XObject'
}
console.log(obj.toString()) //[object XObject] 改变toString返回值,使用Symbol.toStringTag不会和其他方法重复
这个11值在使用方可更加熟悉。
for…of…
新的遍历方法,以后会作为所有数据结构的统一遍历方法;
const arr = [100, 200, 300, 400]
for (const item of arr) {
console.log(item)
break;
}
// 100 200 300 400
// 1、可以使用break;直接跳出循环
// 2、Set和Map数据均可遍历
// 3、普通对象不可遍历(无Symbol.iterator接口或方法)
Iterator(遍历器或者迭代器)
它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
const obj = {
life: ['吃饭', '睡觉', '打豆豆'],
learn: ['语文', '数学', '外语'],
work: ['java','node']
}
/*
* 使用Symbol.iterator可迭代器封装一下,
* 1、一方面是普通对象可遍历
* 2、另一方面,为对象添加统一的对外遍历接口,是业务方调用者不用关注对象对数据结构的变化
*/
obj[Symbol.iterator] = function(){
this.alllist = [...this.life, ...this.learn, ...this.work];
let len = this.alllist.length, index = 0, that = this;
return { // iterator
next() { // next方法
return {
value: that.alllist[index],
done: index ++ >= len
}
}
}
};
for(let item of obj){
console.log(item);
}
Generator (生成器)函数的语法
- Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。
- Generator 函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。
- 执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
- 形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
function* Hgenerator(){ //用*号表示 Generator 函数
console.log('111');
yield 111; //用yield可多次返回并且遇到yield就暂停执行,直等到下次在调用
console.log('222');
yield 222;
console.log('333');
yield 333;
return 444
}
let HG = Hgenerator();
console.log(HG.next()); // 用next方法调用,可以迭代语句调用
console.log(HG.next());
console.log(HG.next());
console.log(HG.next());
console.log(HG.next());
-------------结果---------------
111
{ value: 111, done: false }
222
{ value: 222, done: false }
333
{ value: 333, done: false }
{ value: 444, done: true }
{ value: undefined, done: true }
ECMAScript 2016
数组的查找
Array.prototype.includes
// 查找数组元素NaN也可查找
const arr = ['foo', 1, NaN, false]
console.log(arr.includes('foo'))
console.log(arr.includes(NaN))
指数运算符 **
210 等于 1024
console.log(Math.pow(2, 10)) // 1024
console.log(2 ** 10) // 1024
ECMAScript 2017
const obj = {
foo: 'value1',
bar: 'value2'
}
// 1、Object.values ------ 获取对象的值,对应Object.keys()
console.log(Object.values(obj)) // [ 'value1', 'value2' ]
// 2、Object.entries -------- 获取对象的键值对 配合循环使用
console.log(Object.entries(obj)) // [ [ 'foo', 'value1' ], [ 'bar', 'value2' ] ]
3、Object.getOwnPropertyDescriptors
返回指定对象所有自身属性(非继承属性)的描述对象。
该方法的引入目的,主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题。
const p1 = {
firstName: 'Lei',
lastName: 'Wang',
get fullName () {
return this.firstName + ' ' + this.lastName
}
}
const p2 = Object.assign({}, p1)
p2.firstName = 'zce'
console.log(p2.fullName) // Lei Wang 无法正确拷贝get属性,还是原值
const descriptors = Object.getOwnPropertyDescriptors(p1)
const p3 = Object.defineProperties({}, descriptors)
p3.firstName = 'zce'
console.log(p3.fullName) // zce Wang 可以拷贝get属性
4、String.prototype.padStart 和 String.prototype.padEnd
字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。
第一个参数为长度,第二个参数为补全值
'abc'.padEnd(16, '-') // abc-----
'55'.padStart(3, '0') // 055
5、在函数参数中添加尾逗号
function foo ( bar, baz, ) { }