es6声明变量的方法:var、function、let、const、import、class。
顶层对象的属性与全局变量挂钩,被认为是JavaScript语言最大的设计败笔之一。这样的设计带来了几个很大的问题,首先是没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);其次程序员很容易不知不觉地就创造了全局变量;最后,顶层对象的属性是到处可以读写的,这非常不利于模块化编程。另一方面,window对象有实体含义,值的是浏览器的窗口对象,顶层对象是一个有实体含义的对象也是不合适的。
var、function命令声明的全局变量依旧是顶层对象的属性,let、const、class命令声明的全局变量不属于顶层对象的属性。也就是说,从es6开始,全局变量将逐步与顶层对象的属性脱钩(进行剥离)。
获取顶层对象
(typeof window !== ‘undefined‘ ? window : (typeof process === ‘object‘ && typeof require === ‘function‘ && typeof global === ‘object‘) ? global : this) function getGlobal(){ if(typeof self !== ‘undefined‘){ return self } if(typeof window !== ‘undefined‘){ return window } if(typeof global !== ‘undefined‘){ return global } throw new Error(‘unable to locate global object‘) }
解构赋值报错:等号右边的值,要么转为对象以后不具备Iterator接口,要么本身就不具备Iterator接口。事实上,只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。
解构赋值允许指定默认值。es6内部使用严格相等运算符(===),判断一个位置是否有值。只有当一个数组(对象中属性)成员的值严格等于undefined,默认值才会生效。
对象的解构赋值是下面形式的简写。
let {foo:foo,bar:bar} = {foo:‘aaa‘,bar:‘bbb‘}
也就是说,对象的解构赋值的内部机制是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
let {foo:baz} = {foo:‘aaa‘,bar:‘bbb‘} baz //‘aaa‘ foo //error:foo is not defined
前者是匹配模式。后者才是变量。
在模板字符串(template string)中使用反引号,需要在其前面用反斜杠转义。
使用模板字符串表示多行字符串,所有空格和缩进都会被保留在输出之中。
ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b
(或0B
)和0o
(或0O
)表示。
函数参数制定了默认值以后,函数的length属性将返回没有指定默认值的参数的个数。
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等初始化结束,这个作用于就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。
var x = 1 function fn(x,y = x){ console.log(y) } fn(2) //2 fn() //undefined
利用参数默认值,可以指定某个参数不得省略,如果省略就会抛出错误。
function throwIfMiss(){ throw new Error(‘Missing Parameter‘) } function fn(mustBeProvidedParam = throwIfMiss()){ return mustBeProvidedParam } fn()
将参数默认值设为undefined
,表明这个参数是可以省略的。
函数的length属性,不包括rest参数(函数的多余参数)。
es6规定,只要函数参数使用了默认值、解构赋值、扩展运算符,那么函数就不能显式设定为严格模式,否则报错。有两种方法可以规避这种限制:
第一种是设定全局性的严格模式
‘use strict‘; function doSomething(a, b = a) { // code }
第二种是把函数包在一个无参数立即执行函数里面。
const doSomething = (function () { ‘use strict‘; return function(a,b = a) { // code }; }());
箭头函数有几个使用注意点:
Array.from()方法可将类数组对象(array-like object)和可遍历(iterable)的对象转为真正的数组。
Array.of()方法用于将一组值转换为数组。
对象中属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object],而对象中只会有最后一个[object Object],前面的均会被覆盖掉。
isPrototypeOf()、getPrototypeOf()、setPrototype()用法示例:
如果Symbol的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后再生成一个symbol值。
Symbol实例属性description,直接返回symbol的描述。
使用Set很容易实现并集(Union)、交集(Intersect)和差集(Difference)。
let s1 = new Set([1,2,3]) let s2 = new Set([3,4,5]) let union = new Set([...s1,...s2]) let intersect = new Set([...s1].filter(i => s2.has(i))) let difference = new Set([...s1].filter(i => !s2.has(i)))
Proxy构造函数:let proxy = new Proxy(target,handler);
target参数表示所要拦截的目标对象,handler参数也是一个对象。
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)
。
Reflect
对象一共有 13 个静态方法。Reflect.apply(target, thisArg, args) 用于绑定this
对象后执行给定函数
Reflect.construct(target, args) 提供了一种不使用new
,来调用构造函数的方法。
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.defineProperty(target, name, desc) 用来为对象定义属性
Reflect.deleteProperty(target, name) 用于删除对象的属性
Reflect.has(target, name) 方法对应name in obj
里面的in
运算符。
Reflect.ownKeys(target) 用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames
与Object.getOwnPropertySymbols
之和。
Reflect.isExtensible(target) 返回一个布尔值,表示当前对象是否可扩展。
Reflect.preventExtensions(target) 用于让一个对象变为不可扩展。
Reflect.getOwnPropertyDescriptor(target, name) 用于得到指定属性的描述对象,
Reflect.getPrototypeOf(target) 用于读取对象的__proto__
属性
Reflect.setPrototypeOf(target, prototype) 用于设置目标对象的原型(prototype)
实例的状态都变成fulfilled
,或者其中有一个变为rejected
,才会调用Promise.all
方法后面的回调函数。
一个实例率先改变状态,Promise.race()的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给Promise.rece()的回调函数
Promise.allSettled()
方法只有等到所有这些参数实例都返回结果,不管是fulfilled
还是rejected
,包装实例才会结束。
Promise.any()只要参数实例有一个变成fulfilled
状态,包装实例就会变成fulfilled
状态;如果所有参数实例都变成rejected
状态,包装实例就会变成rejected
状态。
Promise.try()
类相当于实例的原型,所有在类中定义的方法都会被实例继承。如果在一个方法前,加上static关键字,表示该方法不会被实例继承,而是直接通过类调用,这就成为静态方法。
如果静态方法中包含this关键字,这个this指的是类,而不是实例。
class Foo{ static bar(){ this.baz() } static baz(){ console.log(‘hello‘) } baz(){ console.log(‘world‘) } } Foo.bar() // hello
提案:私有属性、方法,前面加#
new
是从构造函数生成实例对象的命令。ES6 为new
命令引入了一个new.target
属性,该属性一般用在构造函数之中,返回new
命令作用于的那个构造函数。如果构造函数不是通过new
命令或Reflect.construct()
调用的,new.target
会返回undefined
,因此这个属性可以用来确定构造函数是怎么调用的
需要注意的是,子类继承父类时,new.target
会返回子类,利用这个特点,可以写出不能独立使用,必须继承后才能使用的类。
class Father{ constructor(){ if(new.target === Father){ throw new Error(‘本类不能实例化‘) } } } class Son extends Father{ constructor(x,y){ super() this.x = x; this.y = y } }
未完待续...
原文:https://www.cnblogs.com/zhenjianyu/p/13490845.html