对象功能新增
● Object.is()
//两个值是否为同一个值。返回true或者false
Object.is('foo', 'foo'); // true
Object.is(null, null); // true
Object.is([], []); // false 引用数据类型的内存地址不同
//特例
console.log(+0 === -0); //true
console.log(Object.is(+0, -0)); //false
console.log(NaN === NaN); //false
console.log(Object.is(NaN, NaN)); //true
● Object.assign()
//将另一个对象中可枚举的属性拷贝到原对象中
var obj1 = {a:1,b:2}
var obj2 = Object.assign({}, obj1);//深拷贝
var obj3 = Object.assign(obj1, {});//浅拷贝
var obj4 = {b:3,c:4}
Object.assign(obj1,obj4);//{1,3,4} 重复后者会覆盖前者
● Object.getPrototypeOf()
//获取一个对象的原型(prototype)
var obj = {}
console.log(Object.getPrototypeOf(obj));
console.log(Object.prototype);
console.log(obj.__proto__);
● Object.setPrototypeOf()
//设置一个对象的原型
function animal(){
this.name = "animal"
}
animal.prototype.getname=function(){
console.log(this.name);
}
var dog = new animal();
var obj = {}
Object.setPrototypeOf(obj,dog);
obj.getname();
● Object.keys()** 方法获取所有可枚举属性名
● Object.values()** 方法获取所有的可枚举属性值
● Object.entries()** 方法获取所有的可枚举属性名和属性值键值对
数组功能新增
● Array.from() 方法将类似数组或可迭代对象转为数组
● Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
● Array.prototype.find() 方法返获取元素
● Array.prototype.findIndex()** 方法找到一个元素在数组中的位置
var arr2 = [1,2,3,4,5]
var res = arr2.find((v,k,arr)=>{
if(v>2)
return true
});
console.log(res);
● Array.prototype.includes()方法找到一个元素是否存在于数组中
● Array.prototype.fill(v,start,end)** 方法填充数组
● Array.prototype.keys()** 方法获取数组key
● Array.prototype.values()方法获取数组元素
● Array.prototype.entries()** 方法获取数组中的key、value键值对
for-of(可迭代对象)
一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator接口,就可以用for…of循环遍历它的成员。也就是说,for…of循环内部调用的是数据结构的Symbol.iterator方法。
Symbol
ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol
的原因。
● 提供独一无二的值
● Symbol 值作为对象属性名时,不能用点运算符,要用中括号表示法
● Symbol 值作为对象属性名时,该属性不会出现在for...in
、for...of
循环中
● 它可以有参数,但是参数仅仅为一个描述
description属性:获取 Symbol 的描述
实例:
● 在对象中当做属性名使用
● 消除魔术字符串
方法:
1.Object.getOwnPropertySymbols()方法,该方法返回一个数组,只包含symbol类型
2.Reflect.ownKeys()方法,返回所有的键数组
3.Symbol.for()
它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。
4.Symbol.keyFor()
该方法返回一个已登记的 Symbol 类型值的key
Set集合
Set类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成 Set 数据结构展。Set的成员的不能通过索引的方式访问。
Set 构造函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。
API:
Set.prototype.size 返回Set实例的元素总数
Set.prototype.add(value) 添加某个值,返回Set结构本身,不能添加重复的值
Set.prototype.delete(value) 删除某个值,返回一个布尔值,表示删除是否成功
Set.prototype.has(value) 返回一个布尔值,表示该值是否为Set的元素。
Set.prototype.clear() Set.prototype.values()
Set.prototype.keys() 返回Set 对象中的元素值的一个 Iterator 对象。
Set.prototype.values() 返回Set 对象中的元素值的一个 Iterator 对象。
Set.prototype.entries() 返回Set 对象中的[key, value]的一个 Iterator 对象。
Set.prototype.forEach() 遍历
我们也经常使用Set进行数组去重的操作
Map集合
Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。Map类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。Map 可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。[[key,value],[key,value]]
简单来说,就是在Map中任何的类型的数据都可以为键,值跟Object一致。
● 我们在使用{}时,有可能会出现属性名和原型中的属性名一致的情况,Map不会
● 一个 Map的键可以是任意值,包括函数、对象或任意基本类型。
● Map 中的 key 是有序的。{}无序
● Map 的键值对个数可以轻易地通过size 属性获取,{}需要计算
Map集合在创建时,也可以传递一个数组进行创建,但是需要注意形似为[key,value]
API:
Map.prototype.size 返回Map对象的键/值对的数量。
Map.prototype.set(key, value) set方法设置键名key对应的键值为value
Map.prototype.get(key) get方法读取key对应的键值
Map.prototype.has(key) 某个键是否在当前 Map 对象之中
Map.prototype.delete(key) delete方法删除某个键,返回true
Map.prototype.clear() 清除所有成员
Map.prototype.keys() 返回键名的遍历器
Map.prototype.values() 返回键值的遍历器
Map.prototype.entries() 返回键值对的遍历器
Map.prototype.forEach() 遍历
类(class)
新的class写法只是让对象原型的写法更加清晰更像面向对象编程,通过class关键字,可以定义类。更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。
构造函数
constructor
方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
实例属性和方法
定义在类体中的属性称为实例属性,定义在类体中的方法称为实例方法。
不推荐在实例上定义方法,因为这样做方法会创建在实例上。
原型属性和方法
原型属性和方法顾名思义就是在构造函数的原型对象上存在的属性和方法。
不推荐在实例上定义属性,因为这样做属性的值无法自定义。
静态属性和方法
通过static
关键字来定义静态属性和静态方法。静态属性和静态方法是定义在类上的,所以可以通过类直接访问。在静态方法中,this
指向当前类。
继承
可以通过extends
关键字实现继承,子类中可以没有构造函数,系统会默认提供一个。子类如果提供了构造函数就必须显示调用super。super函数类似于之前的借用构造函数。
class 作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链
1.子类的__proto__属性,表示构造函数的继承,总是指向父类。
2.子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。
super 关键字
● super作为函数调用时,代表父类的构造函数。
● super作为对象时,在普通方法中,指向父类的原型对象
迭代器
迭代器/遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。
如果我们想自定义一个迭代器,必须为对象添加一个Symbol.iterator方法,这个方法必须返回一个 迭代器(iterator) —— 内部一个有next方法的对象。
原始就具有迭代器接口的数据类型有:Array、Map、Set、String、TypedArray、arguments、NodeList
//自定义迭代器
var obj = {
data:[1,2,3,4,5],
[Symbol.iterator](){
var _this = this;
var index = 0;
return {
next(){
if(index<_this.data.length){
return {value:_this.data[index++],done:false}
}else{
return { value: undefined, done: true };
}
}
}
}
}
如何遍历迭代器
● 上个章节我们说到的for…of语法
● 判断done是否为true
promise
Promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理和更强大。简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
Promise对象代表一个异步操作有三种状态: pending(进行中)、fulfilled(已成功)和rejected(已失败)。
状态发生改变之后就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。
原型方法
Promise.prototype.then() 当状态由pending变为fulfilled的时候执行该回调函数
Promise.prototype.catch() 当状态由pending变为rejected的时候执行该回调函数
Promise.prototype.finally() 在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数
Promise.all([p1,p2]) 当p1,p2状态都为fulfilled时候,该实例的状态才为fulfilled
Promise.any([p1,p2]) 只要p1,p2状态有一个变为fulfilled,该实例的状态为fulfilled
Promise.race([p1,p2]) 当p1,p2之中有一个实例率先改变状态,该实例的状态就跟着改变。
Promise.allSettled() ES11新增,所有的承诺都执行完毕后,返回结果数组
Promise.resolve() 用于将现有对象转化为Promise实例fulfilled状态
Promise.reject() 用于将现有对象转化为Promise实例rejected状态
Generator
Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同,Generator 函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
特点
● function关键字与函数名之间有个星号
● 函数内部使用yield表达式
● 可以放置return语句,返回最终的结果
作用
● 交替执行
● 顺序执行
● 与promise结合实现对异步代码的顺序控制
Async
Async函数是generator函数的语法糖,在generator函数的基础上添加了一些更加方便用户操作的新特性。Async函数的执行和普通函数一致,只需要一行代码即可,因为他具有内置的执行。async与await对比*与yield有更好的语义。
特点:
● await关键字只在async函数内有效。
● async函数返回一个 Promise 对象。
● async函数可以实现也是一种异步函数同步化的实现
ES6补充
proxy/reflect
proxy我们可以理解为代理,其含义是在对象操作时,我们可以做一些额外的操作;例如对数据的处理,对构造函数的处理,对数据的验证。
let test = {
name: "小红"
};
test = new Proxy(test, {
get(target, key) {
return target[key]+"哭了";
},
set(target, key, value) {
return Reflect.set(target, key, value)
}
});