ES6(下)

本文深入探讨ES6的Proxy、Reflect、Promise、Iterator、Generator、Class、Module等新特性,解析其实现原理与应用场景,帮助读者掌握现代JavaScript编程的关键概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

零.Proxy
1.什么是proxy
2.proxy实例方法
3.this问题

一.Reflect
1.设计Reflect对象目的
2.Reflect实例方法

二.Promise对象
1.什么是promise
2.优点/缺点
3.Promise.prototype.then()
4.Promise.prototype.catch()

三.Iterator和for…of循环
1.什么是Iterator
2.Iterator.next()
3.Iterator属性
4.调用Iterator接口
5.遍历器对象的return()
6.什么是for…of
7.for…in和for…of

四.Generator函数
1.什么是Generator函数
2.next()
3.yield
4.Generator.prototype.throw()
5.Generator.prototype.return()
6.什么是Thunk函数

五.Class
1.类内部定义的所有方法,都是不可枚举的。
2…实例的属性
3.Object.getPrototypeOf()
4.set和get关键字
5.name属性
6.静态方法
7.静态属性
8.new.target

六.Class继承
1.extend
2.Object.getPrototypeOf(子类名)
3.super关键字
4.类的prototype属性和__proto__属性
5.Mixin模式

七.Module的语法
1.CommonJS和AMD模块
2.ES6的模块
3.严格模式
4.export default命令
5.模块的继承
6.跨模块常量
7.import()

八.Module的加载实现
1.defer
2.<script type = "module"></script>
3.module默认是严格模式
4.ES6模块与CommonJS模块差异

Proxy
1.什么是proxy
当外界对该对象访问时,可以对外界的访问进行过滤和改写。
通过new Proxy(target,handler)得到proxy实例。target和handler都是对象,
如果没有handler,proxy实例就是target对象
2.proxy实例方法:写在new Proxy()里面
(1)get(target,propertykey,[proxy实例]),拦截访问target对象的propertykey属性
(2)set(target,protypeName,protypeValue,[proxy实例])
set不能设置writable:false,严格模式下没有返回true则报错。
(3)aply(target,targettThis,targetArgs)
如果调用proxy函数,就会被apply方法拦截
(4)has(target,key)判断对象是否有某个属性,要和in一起用
如果元对象不可配置或者禁止扩展就会报错,has对for…in不生效
(5)construct(target,args,newTarget)拦截new命令,必须返回对象
(6)deleteProperty()拦截delete操作,throw error无法delete
(7)defineProperty()拦截Object.defineProperty操作
(8)getOwnPropertyDescriptor()拦截Object.getOwnPropertyDescriptor(),
返回一个属性描述对象或者undefined
(9)getOwnPropertyDescriptor()拦截Object.getOwnPropertyDescriptor(),返回一个属性描述对象或者undefined
(10)getPropertypeOf()拦截获取对象原型
(11)isExtensible()拦截Object.isExtensible操作,只能返回布尔值
(12)OwnKeys()来拦截对象自身属性的读取操作,
(13)preventExtensions()拦截Object.preventExtensions()返回一个布尔值,单Object.isExtensible(proxy)为false,Object.preventExtension()才返回true.
(14)setPrototypeOf()拦截Object.setPrototypeOf(),返回布尔值

3.this问题
在Proxy代理情况下,目标对象内部的this关键字指向proxy代理

一.Reflect
1.设计Reflect对象目的:
(1)Reflect可以拿到对象内部的方法。
(2)修改某些Object方法的返回结果使得更加合理,减少报错
(3)让Object操作变成函数行为
(4)Reflect对象的方法与Proxy对象方法一一对应

2.实例方法
(1)Reflect.get(target,name,receiver)查找并返回target对象的name属性,没有就返回undefined。
如果name属性部署了getter函数,则读取函数的this绑定receiver.

var myObject = {
  foo: 1,
  bar: 2,
  get baz() {
    return this.foo + this.bar;
  },
}

Reflect.get(myObject, 'foo') // 1

如果第一个参数不是对象,Reflect.get()报错。
(2)Reflect.set(target,name,value,receiver)设置target对象的name属性等于value。
如果name属性设置了赋值函数,则赋值函数的this绑定receiver
如果第一个参数不是对象会报错。
(3)Reflect.has(obj,name)对应name in obj里面的in运算符
(4)Reflect.deleteProperty(obj,name)等同于delete obj[name],用于删除对象属性。
如果第一个参数不是对象会报错
(5)Reflect.construct(target,agrs)等同于new target(…agrs)新的构造函数
(6)Reflect.getPrototype(obj)用于读取对象的__proto__属性对应Object.getPrototypeOf(obj)
Reflect如果第一个参数不是对象会报错,Object会将第一个参数转为对象之后运行
(7)Reflect.setPrototypeOf(obj,newProto)设置目标对象的原型,返回布尔值,表示是否设置成功。
如果第一个参数不是对象会报错,Object会返回第一个参数自身。
如果是undefined或null就都会报错
(8)Reflect.apply() 等同于 Function.prototype.apply.call(func,thisArgs,args)
(9)Reflect.defineProperty()等同于Object.defineProperty()定义对象属性
(10)Reflect.getOwnPropertyDescriptor(target,propertyKey)等同于Object.getOwnPropertyDescriptor().
如果第一个参数不是对象,Reflect会报错,Object不会报错。
(11)Reflect.getOwnPropertyDescriptor(target,propertyKey)等同于Object.getOwnPropertyDescriptor
如果第一个参数不是对象,Reflect会报错,Object不会报错。
(12)Reflect.isExtensible(target)等同于Object.isExtensible,返回布尔值,表示当前对象是否可扩展。
如果第一个参数不是对象就报错,Object返回false
(13)Reflect.preventExtensions(target)对应Object.preventExtensions,阻止一个对象变成不可扩展,返回布尔值表示是否操作成功。
如果不是第一个参数不是对象都会报错
(14)Reflect.ownKeys()返回对象所有的属性,等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和

二.Promise对象
1.什么是promise
promise是一个对象,代表一个异步操作,有三种状态(pending,fulfilled,rejected),只有异步操作的结果来决定当前的状态,其他无法改变。一旦异步操作的结果是fulfilled还是rejected确定了就不会改变了。
2.优点/缺点
优点:有了promise对象对异步操作就可以避免层层嵌套的回调。
缺点:(1)一旦建立Promise就无法取消,
(2)promise内部跑错,外部不知道
(3)对应pending状态不清楚是刚刚开始还是即将完成

3.Promise.prototype.then()返回一个新的Promise实例(不是原来的Promise实例)。
4.Promise.prototype.catch()是指定发生错误时的回调函数
错误会一直向后传递,如果要catch就不要传入第二个参数。
5.Promise.prototype.finally()不接收任何参数
6.Promise.all()将多个Promise实例,包装成一个新的Promise实例。
参数必须有Iterator实例,返回的每个成员都是promise实例。
7.Promise.race()将多个Promise实例,包装成新的Promise实例。
8.Promise.resolve()将现有对象转为Promise对象,参数是一个thenable对象(有then方法)
9.Promise.reject(reason)返回新的Promise实例,该实例的状态为rejected

三.Iterator和for…of循环
1.什么是Iterator
具有Iterator接口可以进行遍历操作,使用for…of有序遍历。
2.Iterator.next()
Iterator是一个指针对象,调用next方法,将指针指向数据结构的成员。返回当前成员的value和done(是否遍历完)
3.Iterator属性
Iterator有Symbol.iterator属性(放在方括号里面),只要有这个属性就可遍历的。

var iterator = something.[Symbol.iterator]();

原生具备Iterator接口的数据结构:Array,Map,Set,String,TypedArray,函数的arguments对象,NodeList对象。
有原生Iterator接口的数据结构可以使用for …of循环遍历
4.调用Iterator接口
(1)解构赋值
(2)扩展运算符
(3)yield*
(4)其他:for…of,Array.from(),Map(),Set()
5.遍历器对象的return()
return():如果for…of循环提前退出就会调用return方法,return必须返回一个对象。

6.什么是for…of
for…of就是循环内部调用数据结构
for…of循环可以使用范围:数组,set,map结构,伪数组,arguments对象,string,generator
for…of可以代替数组的forEach(),for…of可以得到value,for… of不会遍历arr.属性
注意:在遍历对象的时候应该for(var key of Object.keys(someObject))
for…in只能获取对象的键名,不能获取键值
arr.forEach()不可以跳出break和return

优点缺点注意点
for循环原始写法写法麻烦
forEach简化写法无法跳出break,return命令
for…in遍历对象key,遍历数组的index会遍历原型链继承的其他键,且无序适合遍历对象
for…of具有forEach和for…in的优点for… of不会遍历arr.属性

四.Generator函数
1.什么是Generator函数
Generator的函数内部指针指向,调用next(),会返回一个遍历器对象,value是yield表达式的值,done布尔值表示是否遍历结束。
2.next()
遇到yield就会暂停之后再调用next(),直到return语句结束,如果没有return就并返回undefined。
3.yield
只能和Generator函数,如果和表达式一起用要放在括号里面,如果是赋值可以直接用yield
4.Generator.prototype.throw()
如果没有在Generator函数内捕捉错误就会把错误抛出,前提是调用next()
5.Generator.prototype.return()
可以返回定值,并且会终结Generator函数
6.什么是Thunk函数
Thunk函数就是把参数放在一个临时函数,然后将这个临时函数传入函数体

五.Class
1.类内部定义的所有方法,都是不可枚举的。
2.实例的属性
如果不是显式定义其本身(this),否则是定义在原型上(class)
实例属性可以定义在constructor()方法里面,或者定义在类的最顶层。
3.Object.getPrototypeOf()
获取实例对象的原型,为原型添加属性和方法。
4.set和get关键字
对属性设置值函数和取值函数,拦截该属性的存取行为,是设置在属性的Descriptor对象的。
注意:类没有变量提升的
5.name属性
返回紧跟着class关键字后面的类名
6.静态方法:加上static关键字,表示该方法不会被实例继承,而是直接通过类来调用,静态方法的this指向类。父类的静态方法,子类可以调用这个方法。

7.静态属性:加上static关键字,
8.new.target属性返回new命令的构造函数,如果不是通过new命令或者Reflect.construct()调用的,就会返回undefined.

六.Class继承
1.extend
使用关键字extend,子类的constructor要先super再写子类的属性
2.Object.getPrototypeOf(子类名)
用来获取父类,判断子类是否继承了某个类
3.super关键字
调用函数,ES6规定子类的构造函数必须执行一次super函数
只能在constructor()里面使用
要显示的表示super是当作函数还是对象调用
(1)super作为函数
super虽然代表父类A的构造函数,但是返回的是子类B的实例。
super()相当于A.prototype.call(this),super()内部的this是指向B的。
super()只能在子类的构造函数使用
(2)super作为对象,
[1]在子类普通方法指向父类的原型对象 ,方法的this指向子类的实例,父类 实例上的方法或属性无法通过super调用
[2]在静态方法指向父类,方法内部的this是当前的子类,而不是子类的实例
4.类的prototype属性和__proto__属性
(1)子类的__proto__属性表示构造函数的继承,总是指向父类
(2)子类的prototype总是指向方法的继承,总是指向父类的prototype属性
5.Mixin模式
Mixin模式是指多个对象合成一个新的对象,新的对象具有各个组成成员的接口。

七.Module的语法
1.CommonJS和AMD模块:“运行时加载”=>都只能在运行时确定东西
2.ES6的模块不是对象,而是通过export命令显式指定输出代码(export{变量名 as 另一个变量名}),接口名和模块内部的变量要一一对应
再通过import命令输入,ES6在编译时就完成加载,“静态加载”
import命令输入的变量都是只读的,不能改写接口,
import是编译时执行的,在代码运行之前,对应多次重复的import语句只执行1次。
import * from …表示加载全部的模块

3.严格模式:
(1)不能使用with
(2)不能删除补可以删除的属性
(3)不能删除变量delete prop,会报错,只能删除属性delete global[prop]
(4)eval不会在它的外层作用域引入变量
(5)禁止this指向全局对象
(6)argumemts不会自动反映函数参数的变化
(7)不能使用argument.callee和arguement.caller

4.export default命令
(1)使用export default,在import的时候不需要使用大括号,一个模块只能有一个export default,实质是输出一个default的变量

5.模块的继承

6.跨模块常量
多个模块共享相同的const常量,可以将常量写在一个转码的constants目录文件里面,并合并在index.js里面,使用的时候直接加载index文件即可

7.import()
(1)import和export命令只能在模块的顶层,不能在代码块之中.import命令不能动态加载模块,因此引入了import()
(2)import()和import参数是一样的,区别在于前者是动态加载。import()可以在任何地方使用。
eg:
[1]按需加载
[2]条件加载
[3]动态加载
(3)import()加载模块之后会作为一个对象,当作then方法的参数

八.Module的加载实现
1.defer:页面渲染之后再执行;async:下载完就执行
多个defer会按照它们在页面出现的顺序,而多个async不能保证加载的顺序
**2.是按照顺序来的
3.注意:module默认是严格模式,不管有没有使用use strict
在模块中使用this是没有一样的,会返回undefined
4.ES6模块与CommonJS模块差异
(1)ES6模块输出的是值的引用,而CommonJs模块输出的是值的拷贝
加载模块以后,模块内部的变化不会影响输出的值,除非写get函数,
而ES6模块会跟着被被加载的模块变化而变化
(2)ES6模块的编译时输出接口,而CommonJS模块是运行时加载
在Node中,脚本文件里面使用了import或者export命令就要采用.mjs后缀名,只有import命令才能加载.mjs文件
(3)Node规定ES6模块不能使用CommonJS模块内部变量
eg:this,argument,require,exports,_filename, _dirname

编程风格
1.块级作用域
(1)let取代var
(2)能用const就用const,原因:提醒这个变量是不应该修改的,编译器对const进行优化,提高程序运行效率

2.字符串
(1)静态的字符串用单引号或者反引号,不要使用双引号,动态字符串使用反引号

3.解构赋值
(1)当对数组成员对变量赋值时,优先使用解构赋值
(2)当函数参数是对象的成员时,优先使用解构赋值
(3)当函数返回多个值时,优先使用对象的解构赋值

4.对象
(1)当行定义的对象,最后一个成员不加逗号,
多行定义的对象,最后一个成员加逗号
(2)尽量静态化对象,如果要添加对象属性使用Object.assign().
如果对象的属性是动态的化,使用属性表达式定义

5.数组
(1)使用扩展运算符(…)拷贝数组
(2)使用Array.from()将类似数组的对象转为数组

6.函数
(1)将立即执行的函数写成箭头形式
(2)将匿名函数写成箭头形式
(3)简单的,不会复用的函数就写成箭头函数
(4)函数参数:布尔值不可以直接作为参数,要放在对象里面
(5)不要在函数体内使用argument变量,使用rest运算符,因为rest运算符可以是真数组,而argument是伪数组
(6)使用默认值语法设置函数参数的默认值

7.Map结构
(1)只有模拟现实世界的实体对象才使用Object,
如果只是key:value形式使用Map结构,因Map结构具有遍历机制
map.key(),map.values(),map.entries()

8.Class
总是用Class取代需要prototype的操作,因为Class写法更简洁易懂,可以使用extend,不会破坏instanceof运算

9.模块
(1)使用import代替require
(2)使用export代替module.export
(3)如果输出值只有一个值就用export default,否则用export
(4)不要使用通配符,以确保只有一个export default
(5)如果模块输出是函数,那么函数名称首字母要小写
(6)如果模块输出一个对象,那么对象名称首字母要大写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值