ES6笔记(纯干货)

10 篇文章 11 订阅
5 篇文章 3 订阅

一、Symbol

新的数据类型,表示独一无二的值

通过symbol函数生成

let s=Symbol();

对象属性名的两种表示方法:1、原有字符串表示。2、Symbol表示

Symbol可接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台输出,或者是转为字符串时比较容易区分

如果Symbol的参数是一个对象,则会调用toString方法将其转换成为字符串,然后生成一个Symbol值

Symbol值不能与其他类型的值进行运算,否则会报错

Symbol值可以显式的转为字符串

let sym=Symbol('My Symbol');
String(sym);	//'Symbol(My Symbol)'
sym.toString();	//'Symbol(My Symbol)'

Symbol值也可以转换成为布尔值,但是不能转换为数值

let sym=Symbol();
Boolean(sym);	//true
!sym;			//false
Number(sym);	//TypeError

Symbol值作为对象的属性名时不能使用点运算符,只能用方括号

在对象内部使用Symbol值定义属性时,也只能用方括号

let sym=Symbol();
let a={};
a.sym='Hello';
a[sym];		//undefined
s['sym'];	//'Hello'

Symbol类型的值还可以定义一组常量,保证这些常量都是不相等的

(一)属性名遍历

Object.getOwnPropertySymbols():返回一个数组,成员是当前对象的所有作用属性名的Symbol值

Reflect.ownKeys():以数组的形式返回所有键名,包括常规键名和S也Symbol键名

以Symbol值作为属性名的属性不会被常规方法遍历得到(可为对象定义一些非私有但又希望只用于内部的方法)

Symbol.for():可重新使用同一个Symbol值

​ 参数:一个字符串

​ 作用:搜索有没有以该参数作为名称的Symbol值,若有则返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值

Symbol.for()与Symbol都可以生成新的Symbol

区别:前者会被登记在全局环境中供搜索,后者不会

Singleton模式:调用一个类,并且在任何时候都返回同一个实例

(二)内置的Symbol值

对象的Symbol.hasInstance属性指向一个内部方法,对象使用instanceof运算符是会调用这个方法,判断该对象是否为某个构造函数的实例

class Myclass{
    [Symbol.hanInstance](foo){
        return foo instanceof Array;
    }
}
[1,2,3] instanceof new Myclass;	//true

对象的Symbo.isConcatSpreadable属性等于一个布尔值,表示该对象在使用Array.prototype.concat()时是否可以展开

let arr1=['c','d'];
['a','b'].concat(arr1,'e');		//['a','b','c','d','e']
arr1[Symvol.isConcatSpreadable]	//undefined

let arr2=['c','d'];
arr2[Symbol.isConcatSpreadable]=false;
['a','b'].concat(arr2,'e');		//['a','b',['c','d'],'e']

数组的默认行为是可以展开的,Symbol.isConcatSpreadable属性等于undefined或者true,都可以

类似于数组的对象也可以展开,但它的Symbol.isConcatSpreadable属性默认为false,必须手动打开、

let obj={length:2,0:'c',1:'d'};
['a','b'].concat(obj,'e');		//['a','b',obj,'e']

 obj[Symbol,isConcatSpreadable]=true;
['a','b'].concat(obj,'e');		//['a','b','c','d','e']

对于一个类而言,Symbol.isConcatSpreadable属性必须写成实例的属性

Symbol.species

对象的Symbol.species属性指向当前对象的构造函数,使用这个函数返回的函数来创造新的实例对象

定义Symbol.species属性要用get读取数据

class Array extends Array{
    //覆盖父类Array的构造函数
    static get [Symbol.species](){return Array;}
}
Symbol.match

对象的Symbol.match属性指向一个函数,当执行str.match(obj)时,如果该属性存在,则会调用它的返回值

Symbol.replace

对象的Symbol.replace属性指向一个方法,当对象被String.prototype.replace方法调用时会返回改方法的返回值

Symbol.split

对象的Symbol.split属性指向一个方法,当对象被String.prototype.split方法调用时会返回改方法的返回值

Symbol.iterator对象的Symbol.iterator属性指向该对象默认的遍历方法
Symbol.toPrimitive

对象的Symbol.toPrimitive属性指向一个方法,对象在转化为原始数据类型时会调用这个方法,返回该对象的原始数据类型

​ 参数:字符串,表示当前运算模式

  • Number:需要转化为数值
  • String:需要转化为字符串
  • Default:可转化为数组,也可转化为字符串
Symbol.toStringTag

对象的Symbol.toStringTag属性指向一个方法,在对象上调用Object.prototype.toString()时,如果这个属性存在,其返回值会出现在toString方法返回值的字符串中,表示对象的类型

Symbol.unscopables

对象的Symbol.unscopables属性指向一个对象,指定了使用with关键字时,那些属性会被with环境排除

二、Set和Map

(一)Set

类似于数组,其成员唯一,不重复

Set本身是一个构造函数,用于生产Set数据结构

let s=new Set();

Set函数可以接受一个数组,作为参数,用于初始化

向Set加入值时不会发生数据转换,即1和’1’为不同的值

在Set内部,两个NaN相等

(1)Set实例的属性

  • Set.prototype.Constructor():构造函数,就是Set()
  • Set.prototype.size():返回Set实例成员总数
  • add(value):添加值,返回Set本身
  • delete(value):删除值,返回一个布尔值,表删除是否成功
  • has(value):返回布尔值,表参数是否为Set成员
  • clear():清除所有成员,无返回值

(2)遍历

  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach(function(){}):使用回调函数遍历每个成员,无返回值(可加参2,表示绑定的this对象)

Set的遍历顺序就是插入顺序

若想同步的改变原来的Set结构,可利用原Set映射出一个新的结构再复制给原Set结构,或者使用Array.from()

(二)WeaKSet

与Set类似,表不重复的集合

与Set的区别

WeakSet的成员只能是对象,不能是其他值

WeakSet中的对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用

WeakSet的成员不能引用,因为其随时可能消失

WeakSet本生是一个构造函数,使用生成WeakSet数据结构

let w = new WeakSet();

可接受一个数组或者类似于数组的对象作为参数来初始化

WeakSet的方法

  • WeakSet.prototype.add(value ):添加新成员
  • WeakSet.prototype.delete(value):删除指定成员
  • WeakSet.prototype.has(value):返回布尔值,表指定值是否在WeakSet实例中

WeakSet无size属性,无法遍历其成员

(三)Map

类似于对象,也是键值组合

其键的范围不限于字符串,可为各种数据类型的值(包括对象)均可当做键

使用Map()构造函数生成

let m = new Map();

Map可接受一个数组作为参数,其数组成员为一个个表示键值对的数组

若一个键多次赋值,则后面的覆盖前面的值

若读取一个未知的键,则返回undefined

Map的键实际上绑定的是地址值,只要地址不同,即视为两个键(解决了同名属性碰撞的问题)

(1)Map实例的属性方法

size

返回Map结构的成员总数

set(key,value)

设置key值所对应的键,然后返回Map结构

若key已经有值,则赋值更新,否则新生成该键值

get(key)

获取key对应的值,若找不到key则返回undefined

has(key)

返回一个布尔值,表示ley是否在Map结构中

delete(key)

删除某个键,删除成功则返回true,反之返回false

clear()

清除所有成员,无返回值

(2)遍历

  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach(function(){}):遍历Map所有成员

Map的遍历顺序就是插入顺序

(四)Map与其他数据类型的转化

(1)Map转数组

Map转化为数组最快的方法时结合使用扩展运算符( . . . )

(2)数组转Map

将数组传入构造函数即可

(3)Map转对象

若Map所有键都是字符串,则可以转为对象

function strMapToObj(strMap){
    let obj = Object.create(null);
    for (let [k,v] of strMap){
        obj[k]=v;
    }
    return obj;
}
(4)对象转Map
function objToStrMap(obj){
    let strMap=new Map();
    for(let k of Object.keys(obj)){
        strMap.set(k.obj[k]);
    }
    return strMap;
}
(5)Map转JSON

情况一:Map键名都是字符串,可以转为对象JSON

function StrMapToJson(StrMap){
    reutrn JSON.stringify(strMapToObj(strMap));
}

情况二:Map键名中含有非字符串,转为数组JSON

function mapToArrayJson(map){
    return JSON.stringify(...map);
}
(6)JSON转Map

正常情况所有键名都是字符串

function jsonToStrMap(jsonStr){
    return objToStrMap(JSON.parse(jsonStr));
}

特殊情况:在整个JSON就是一个数组,且数组成员本身又是由一两个成员的数组,此时应该一一对应的转为Map(数组转为JSON的逆操作)

function jsonToMap(jsonStr){
    return new Map(JSON.parse(jsonStr));
}

(五)WeakMap

与Map结构类似,也用于生成键值对的集合

通过WeakMap函数生成

let wMap = new weakMap();

可使用set方法添加成员

可接受一个数组,作为构造函数的参数

WeakMap与Map的区别
  • WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名(即数组和Symbol值作为WeakMap的键名时会报错)

  • WeakMap的键名所指向的对象不计入垃圾回收机制(会自动被移除,有助于防止内存泄漏)

  • WeakMap没有遍历操作,也,没有size属性

  • 无法清空,即没有clear()方法

WeakMap的语法
  • get()
  • set()
  • has()
  • delete()

三、proxy

用于某些操作的默认行为,等同于在语言层面做出修改

可理解为在目标对象前设置的一个“拦截”层,外界访问目标对象时,先通过拦截层,可对外界的访问进行过滤和改写

使用Proxy构造函数,生成proxy实例

let p = new Proxy(target,handler);
  • target:目标对象
  • handler:用来定制拦截行为的对象(若不设置任何拦截,等同于直接通向原对象)

可将proxy对象设置到object.proxy属性,可在object对象上直接调用

Proxy实例也可作为其他对象的原型对象

Proxy的所有拦截操作

get(target,propKey,receiver)

拦截对象某个属性的读取,最后一个参数为可选对象

若访问目标对象不存在的属性,会抛出一个错误

若没有这个拦截函数,访问不存在的属性只会返回undefined

get方法可以继承

可以利用proxy将get转变为执行某个函数,实现属性的链式操作

set(target,propKey,value,receiver)

拦截对象的设置,返回一个布尔值

利用set方法可以实现数据绑定(即每当对象发生变化,自动跟新DOM)

若目标对象的某个属性不可配置也不可写,只能返回同样的值,否则报错

has(target,propKey)

拦截propKey in proxy的操作,返回一个布尔值(拦截in运算符)

若对象不可配置或禁止扩展,则报错

不判断一个属性是对象自身的还是继承的属性

拦截对for…,in 永不生效

deleteProperty(target,propKey)

拦截delete proxy[proKey]操作,返回一个布尔值

若这个方法抛出错误或者返回false,则当前属性无法被delete删除

目标对昂自身不可配置的属性不能被deleteProperty方法删除,否则报错

ownKeys(target)

拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy),返回一个由目标对象所有自身属性的属性名组成的数组

返回的数组成员只能是字符串或者Symbol值,

若有其他类型的值,或返回的根本不是数组,则报错

若目标对象自身含有不可配置的属性,则改属性必须被ownKeys返回,否则报错

若目标对象不可扩展,则返回的数组中必须包原对象的所有属性,且不能含有其他属性,否则报错

注:使用Object.keys()方法时有三类属性会被ownKeys方法自动过滤

  • 目标对象上不存在的属性
  • 属性名为Symbol值
  • 不可遍历的属性
getOwnPropertyDescriptor(target,propKey)

拦截Object.getOwnPropertyDescriptor(proxy,propKey),返回属性的描述对象或undefined

defineProperty(target,propKey,PropDesc)

拦截Object.defineProperty(proxy,propKey,propDesc)、Object.defineProperties(proxy、propDescs),返回一个布尔值

若目标对象不可扩展,则defineProperty不能增加目标对象中不存在的属性,否则报错

若目标对象中某个属性不可写或不可配置,则defineProperty不得改变这两个设置

preventExtensions(proxy)

拦截Object.preventpreventExtensions(proxy),返回一个布尔值,否则会被自动转为布尔值

限制:只有目标对象不可扩展时,proxy.prevrntExtensions才能返回true,否则报错

解决方案:可在proxy.prevrntExtensions()方法中调用一次Object.preventpreventExtensions()

let p = new proxy({},{
    preventExtensions:function(target){
        Object.preventpreventExtensions(target);
        return true;
    }
})
getPrototypeOf(target)

拦截Object.getPrototype(proxy),返回一个对象或者null,否则报错

若目标对象时一个函数,name还有两种额外操作可以拦截

若目标对象不可扩展,则返回目标对象的原型对象

主要用于拦截对象原型

  • Object.prototype._ _ proto _ _
  • Object.prototype.isPrototypeOf()
  • Object.getPrototypeOf()
  • Reflect.getPrototypeOf()
  • instanceof
setPrototypeOf(target)

拦截Object.setPrototypeOf(),返回一个布尔值,否会被自动转为布尔值

若目标对象不可扩展,setPrototypeOf()不得改变目标对象的原型

isExtensible(target)

拦截Object.isExtensible(proxy),返回一个布尔值

强限制:返回值必须与目标对象的isExtensible属性保持一致,否则报错

apply(target,object,args)

拦截proxy实例,并将其作为函数调用的操作

拦截函数的调用、call、apply操作

直接调用Reflect.apply()也会被拦截

可接受三个参数:

  • 目标对象
  • 目标对象的上下文对象(this)
  • 目标对象的参数数组
construct(target,args)

拦截Proxy实例作为构造函数调用的操作,比如new proxy(…args)

拦截new命令

let handler = {
    construct (target,args,newTatget){
        return new target(...args);
    }
};

可接受两个参数

  • target:目标对象
  • args:构造函数的参数对象

返回一个对象,否则报错

Proxy.revocable(target,handler)

返回一个可取消的proxy实例

四、Reflect

(一)设计目的

  1. 将Object对象上一些明显属于语言的方法放在Reflect上。(从Reflect对象上可以获取语言内部的方法)
  2. 修改一些Object方法的返回结果,让其变得合理
  3. 让Object操作都编程函数行为
  4. proxy对象的方法在Reflect上可以找到与之对应的方法

(二)静态方法

Reflect.get(target,name,receiver)

查找并返target对象的那么属性,若没有则返回undefined

若那么属性部署了读取函数,则读取函数的this绑定receiver

若第一个参数不是对象,则报错

Reflect.set(target,name,value,receiver)

设置target的name属性等于value

若name属性设置了赋值函数,则赋值函数的this绑定receiver

若第一个参数不是对象,则报错

Reflect.set会触发Proxy.defineProperty拦截

Reflect.has(obj,name)

对应name in obj中的in运算符

若一个参数不是对象,则Reflect和in都会报错

Reflect.deletePrototypety(obj,name)

删除对象的属性,等同于delete obj[name]

返回一个布尔值,若删除成功,或删除的属性不存在,则返回true,否则返回false

Reflect.construct(target,args)

等同于new target(…args)

Reflect.getPrototyprOf(obj)

读取对象的 _ _ proto _ _属性,等同于Object.getPrototype(obj)

两者的区别:若参数不是对象,后者会将其转化为对象再进行,而前者则报错

Reflect.setPrototypeOf(obj,newProto)

设置对象的 _ _ proto _ _属性,返回第一个参数

等同于Object.setPrototype(obj,newProto)

若第一个参数不是对象,后者返回第一个对象本身,前者报错

若第一个参数是null或者undefined,两者均报错

Reflect.apply(func,thisArgs,args)

绑定this对象后执行给定函数

等同于Function.prototype.apply.call(func,thisArgs,args)

Reflect.definePropertyOf(target,propertyKey,attribute)

为对象定义属性

等同于Object.definePropertyOf()

Reflect.getOwnPropertyDescriptor(target,propertyKey)

获得指定属性的描述对象

等同于Object.getOwnPropertyDescriptor()

两者区别:若第一个参数不是对象,则后者不会报错,并返回undefined,而前者抛出错误,表示参数非法

Reflect.isExtensible(target)

返回布尔值,表示当前函数是否可扩展

等同于Object.isExtensible()

若第一个参数不是对象,后者返回false(因为非对象不可扩展),前者报错

Reflect.preventExtensions(target)

使一个对象变为不可扩展的,返回布尔值,表示操作是否成功

等同于Object.preventExtensions()

Reflect.OwnKeys(target)

返回对象的所有属性

五、promise

异步编程解决方案

特点:

  • 对象状态不受外界影响
  • 一旦状态改变之后就不会在变,随时可以获取到这个结果

promise对象代表一个异步操作,三种状态:

  1. Pending:进行中
  2. Fulfilled:已成功
  3. Rejected:已失败

只有异步操作的结果可以决定当前的状态,其他操作均不行

使用Promise构造函数生成promise实例

let p = new Promise(function(target,reject){});

promise新建后立即执行

promise接受一个函数作参数,函数的两个参数有JS引擎提供,不用自己部署

target:异步操作成功时调用,将结果作为参数传出去

reject:异步操作失败时调用,将报出的错作为参数传出去

(一)then

为promise实例添加状态改变时的回调函数,返回一个新的promise对象实例

then是定义在原型对象Promise。prototype上的

可用then分别指定Resolved状态和Rejectd状态的回调函数

then的参数为两个回调函数,都接受promise对象传出的值为参数

  • 参1:promise对象状态变为Resolved时调用
  • 参2:promise对象状态变为Rejectd时调用(可选)

(二)catch

指定发生错误时的回调函数

返回一个新的promise对象(后面可接着调then)

可获取then指定的回调函数在运行中抛出的错误

promise的错误会一直向后传递,直到被捕获为止

若前面的then没有报错,则会跳过catch

(三)Promise.all()

将多个promise实例包装成一个新的promise实例

(四)promise.race()

将多个promise实例包装成一个新的promise实例

(五)promise.resolve()

将现有的对象转为Promise

若参数是promise实例:则直接返回这个实例

若参数是thenable对象:则先转成promise对象,在执行thenable对象的then方法

thenable对象:具有then方法的对象

若参数不是thenable对象或者不是对象:promise.resolve返回一个新的Promise对象,状态为Resolved

若不带音任何参数:则返回一个状态为Resolved状态的对象

(六)promise.reject()

返回一个状态为Rejected的新的promise对象

(七)附加方法

done()

处于回调链尾端,保证抛出任何可能出现的错误

可像catch那样使用

有参无参均可,done可捕获到任何可能出现的错误,并向全局抛出

finally()

指定不管promise对象最后状态如何都会执行的操作

与done()的区别:参数为普通的回调函数,不管怎样都必须执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值