ES6+ Reflect(二)
上一节我们学习了 Reflect 的使用和一些基本的API,本节我们将继续学习 Reflect 的一些扩展的API。
Reflect.define
会直接在对象上定义新,或者对象的现有,基本等同于 Object.define
,唯一不同是 Object.define
返回的是这个对象,Reflect.define
返回的是 Boolean
值。
语法:
Reflect.defineProperty(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
更加方便。
var obj = {}
var r = Reflect.defineProperty(obj, 'a', {value: })
if (r) {
// 成功 todo
} else {
// 失败 todo
}
try {
let obj = {}
Object.defineProperty(obj, 'a', {value: })
} catch(e) {
// 如果失败,捕获的异常
}
**Reflect.apply()
** 通过指定的参数列表发起对目标 (target) 的。
语法:
Reflect.apply(target, thisArgument, argumentsList)
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
Reflect.construct()
和 new
操作符构造相似 ,相当于运行 new target(...args)
,提供了一种新的不使用 new 来构造的。
语法:
Reflect.construct(target, argumentsList[, newTarget])
参数:
下面的两种实例化的方式是一样的。
function Foo() {
console.log(arguments);
}
var obj = new @H__665@Foo(...args);
var obj = Reflect.construct(Foo, args);
Reflect.construct()
返回值是以 target
为构造,如果 newTarget
存在,则为 newTarget
。argumentList
为其初始化参数。
对于有没有传递第三个参数,我们可以这样理解:target 就是唯一的构造,但是如果传递了第三个参数,那就表示:我们的实例由两部分组成,实例上绑定在 this 上的部分由第参数的构造;不是实例上的部分则由第三个参数的构造。下面我们来看下具体的实例:
class @H__665@A {
constructor(name) {
console.log('init A class');
this.name = name || 'Jack';
}
getName() {
console.log(this.name);
return this.name;
}
}
class @H__665@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
。
本节主要讲解了 Reflect 扩展的使用