ES6+ Reflect(二)
1. 前言
上一节我们学习了 Reflect 的使用和一些基本的API,本节我们将继续学习 Reflect 的一些扩展的API。
2 Reflect 扩展 方法
2.1 Reflect.define property()
Reflect.define property() 方法 会直接在 一个 对象上定义 一个 新 属性 ,或者 修改 一个 对象的现有 属性 ,基本等同于 Object.define property() 方法 ,唯一不同是 Object.define property() 返回的是这个对象, Reflect.define property() 返回的是 Boolean 值。
语法:
Reflect . defineProperty ( target , propertyKey , attributes )
target:目标对象; propertyKey:需要定义或 修改 的 属性 的 名称 ; attributes:需要定义或 修改 的 属性 的描述。
如果 target 不是 Object ,抛出 一个 TypeError 。
let obj = { } Reflect . defineProperty ( obj , 'a' , { value : } ) // true obj . a ; // 10
Reflect.defineProperty 方法 可以根据返回值检查 属性 是否被成功定义,而 Object.defineProperty 只能通过 try...catch 去捕获其中的 错误 ,相比之下 Reflect.define property() 方法 更加方便。
var obj = { } var r = Reflect . defineProperty ( obj , 'a' , { value : } ) if ( r ) { // 成功 t odo } else { // 失败 t odo } try { let obj = { } Object . defineProperty ( obj , 'a' , { value : } ) } catch ( e ) { // 如果失败,捕获的异常 }
2.2 Reflect.apply()
**Reflect.apply() ** 通过指定的参数列表发起对目标 (target) 函数 的 调用 。
语法:
Reflect . apply ( target , thisArgument , argumentsList )
target:目标 函数 。 thisArgument:target 函数 调用 时绑定的 this 对象。 argumentsList:target 函数 调用 时传入的实参列表,该参数应该是 一个 类数组的对象。
apply 函数 我们都知道,它可以让 函数 执行并可以改变 this 指向。
const arr = [ , , , , , ] ; let max ; max = Math . max . apply ( null , arr ) ; console . log ( max ) ; // 10
Reflect.apply() 方法 与
上面的 代码 中 fn.apply(obj, args) 的写法还可以写成 Function.prototype.apply.call(func, thisArg, args) , Function.prototype.apply.call(fn, obj, args) 这和 Reflect.apply() 的 调用 时传参是一样的。都是用于绑定 this 对象然 后执行 给定 函数 , Reflect 对象则简化这种操作。
max = Function . prototype . apply . call ( Math . max , null , arr ) ; console . log ( max ) ; // 10 max = Reflect . apply ( Math . max , null , arr ) ; console . log ( max ) ; // 10
Reflect.apply() 可以接收 截取 字符串的 函数 。
let str = 'imooc ES6 wiki' ; let newStr ; newStr = Reflect . apply ( String . prototype . slice , str , [ , ] ) ; console . log ( newStr ) ; // ES6 newStr = str . slice ( , ) ; console . log ( newStr ) ; // ES6 newStr = String . prototype . slice . apply ( str , [ , ] ) ; console . log ( newStr ) ; // ES6
2.3 Reflect.construct(target, args)
Reflect.construct() 和 new 操作符构造 函数 相似 ,相当于运行 new target(...args) ,提供了一种新的不使用 new 来 调用 构造 函数 的 方法 。
语法:
Reflect . construct ( target , argumentsList [ , newTarget ] )
参数:
target:被运行的目标构造 函数 ; argumentsList:类数组,目标构造 函数 调用 时的参数; newTarget:(可选)作为新创建对象的原型对象的 constructor 属性 , 默 认值为 target 。
下面的两种实例化的方式是一样的。
function Foo ( ) { console . log ( arguments ) ; } var obj = new Foo ( ... args ) ; var obj = Reflect . construct ( Foo , args ) ;
Reflect.construct() 返回值是以 target 函数 为构造 函数 ,如果 newTarget 存在,则为 newTarget 。 argumentList 为其初始化参数。
对于有没有传递第三个参数,我们可以这样理解:target 就是唯一的构造 函数 ,但是如果传递了第三个参数,那就表示:我们的实例由两部分组成,实例上绑定在 this 上的 属性 部分由第 一个 参数的构造 函数 生成 ;不是实例上的 属性 部分则由第三个参数的构造 函数 生成 。下面我们来看下具体的实例:
class A { constructor ( name ) { console . log ( 'init A class' ) ; this . name = name || 'Jack' ; } getName ( ) { console . log ( this . name ) ; return this . name ; } } class B { constructor ( age ) { console . log ( 'init A class' ) ; this . age = age || ; } getAge ( ) { console . log ( this . age ) ; return this . age ; } } // 使用A类作为构造 函数 let a = Reflect . construct ( A , [ 'David' ] ) ; // 使用B类作为构造 函数 let b = Reflect . construct ( A , [ 'David' ] , B ) ; console . log ( a ) ; console . log ( b ) ; a . getName ( ) ; b . getAge ( ) ;
下图是上面 代码 的打印结果,创建实例 a 时没有第三个参数,它的原型上的 constructor 指向的是类 A,并且有 getName 方法 。创建实例 b 时有第三个参数,打印的结果可以看到实例 b 原型上的 constructor 执行的是类 B,并且有 B 上的 getAge 方法 。
3. 小结
本节主要讲解了 Reflect 扩展 方法 的使用