共计 6669 个字符,预计需要花费 17 分钟才能阅读完成。
Reflect
- 反射,什么是反射机制?
- Reflect 简介
- 为什么要用 Reflect?
-
Reflect API
- .apply()
- .construct()
- .defineProperty()
- .deleteProperty()
- .get()
- .getOwnPropertyDescriptor()
- .getPrototypeOf()
- .has()
- .isExtensible() —— 是否可扩大
- .ownKeys() —— 判断对象本身属性
- .preventExtensions() —— 是否可扩大
- .set() —— 写数据
- .setPrototypeOf()
- ES6-ES10 学习幅员
反射,什么是反射机制?
【java
的反射机制】是在编译阶段不晓得是哪个类被加载,而是在运行的时候才加载、执行。js
中的 apply
就是反射机制。
Reflect 简介
Reflect
是一个内置的对象,它提供拦挡 JavaScript
操作的办法,这些办法与处理器对象的办法雷同。Reflect
不是一个函数对象,因而它是不可结构的。
与大多数全局对象不同,Reflect
没有构造函数。你不能将其与一个 new
运算符一起应用,或者将 Reflect
对象作为一个函数来调用。Reflect
的所有属性和办法都是动态的(就像 Math 对象)
为什么要用 Reflect?
Reflect
外部封装了一系列对对象的底层操作,Reflect
成员办法就是 Proxy
解决对象的默认实现
const proxy = new Proxy(obj, {get(target, property) {
// 如果没有定义 get 办法,那么默认返回的就是 Reflect 的 get 办法
return Reflect.get(target, property)
}
})
为什么要用 Reflect
?<br/> 因为Reflect
提供了一套用于操作对象的 API
,咱们之前操作对象能够用Object
下面的一些办法,也能够用 in、delete
这种操作符,应用 Reflect
就对立了操作形式。
Reflect API
handler ⽅法 | 默认调⽤ | 性能 |
---|---|---|
get | Reflect.get() | 获取对象身上某个属性的值 |
set | Reflect.set() | 在对象上设置属性 |
has | Reflect.has() | 判断一个对象是否存在某个属性 |
deleteProperty | Reflect.deleteProperty() | 删除对象上的属性 |
getProperty | Reflect.getPrototypeOf() | 获取指定对象原型的函数 |
setProperty | Reflect.setPrototypeOf() | 设置或扭转对象原型的函数 |
isExtensible | Reflect.isExtensible() | 判断一个对象是否可扩大(即是否可能增加新的属性) |
preventExtensions | Reflect.preventExtensions() | 阻止新属性增加到对象 |
getOwnPropertyDescriptor | Reflect.getOwnPropertyDescriptor() | 获取给定属性的属性描述符 |
defineProperty | Reflect.defineProperty() | 定义或批改一个对象的属性 |
ownKeys | Reflect.ownKeys() | 返回由指标对象本身的属性键组成的数组 |
apply | Reflect.apply() | 对一个函数进行调用操作,同时能够传入一个数组作为调用参数 |
construct | Reflect.construct() | 对构造函数进行 new 操作,实现创立类的实例 |
.preventExtensions | Reflect.preventExtensions() | 阻止新属性增加到对象 |
.apply()
Reflect.apply(target, thisArgument, argumentsList)
target:指标函数,必传 <br/>
thisArgument:target 函数调用时绑定的 this 对象,不必须 <br/>
argumentsList:target 函数调用时传入的实参列表,该参数应该是一个类数组的对象,不必须
//ES5
console.log(Math.floor.apply(null,[1.72]))
// 1
// 必须先指定办法,再去调用 apply。
//Reflect 是一个对象,然而不能应用 new
// 先传递 apply,再指定是哪个办法
// 动态扫描的时候,Math.floor 是没有被执行的,运行的时候,是动静的将 Math.floor 作为参数传进来的。Reflect.apply(Math.floor,null,[4.72])
// 4
理论利用
// ES5
let price = 101.5
if (price > 100) {price = Math.floor.apply(null, [price])
} else {price = Math.ceil.apply(null, [price])
}
console.log(price)
// 101
//ES6
let price = 101.5
console.log(Reflect.apply(price > 100 ? Math.floor : Math.ceil, null, [price]))
// 101
.construct()
应用反射的形式去实现创立类的实例,相似于new target(…args)
.
Reflect.construct(target, argumentsList[, newTarget])
target: 被运行的指标函数,必选 <br/>
argumentsList 调用构造函数的数组或者伪数组,不用选 <br/>
newTarget 该参数为构造函数,参考 new.target 操作符,如果没有 newTarget 参数,默认和 target 一样,不用选
let d = new Date()
console.log(d.getTime())
let d1 = Reflect.construct(Date, [])
console.log(d1.getTime())
.defineProperty()
静态方法 Reflect.defineProperty()
根本等同于 Object.defineProperty()
办法
Reflect.defineProperty(target, propertyKey, attributes)
target: 指标对象,必填 <br/>
propertyKey: 要定义或批改的属性的名称,不用填 <br/>
attributes: 要定义或批改的属性的形容,不用填
const student = {}
const r = Object.defineProperty(student, 'name', { value:'Mike'})
console.log(student, r)
// {name: "Mike"} {name: "Mike"}
const student = {}
const r = Reflect.defineProperty(student, 'name', { value:'Mike'})
console.log(student, r)
// {name: "Mike"} true
这两个办法成果上来看是一摸一样的,都能够扭转一个对象的值,他们的区别在于返回值不同。Object
是返回这个值,Reflect
是返回true
PS: 在
W3C
中,当前所有的Object
下面的办法,都会缓缓迁徙到Reflect
对象,可能当前会在Object
下面移除这些办法。
.deleteProperty()
Reflect.deleteProperty
容许你删除一个对象上的属性。返回一个 Boolean
值示意该属性是否被胜利删除。它简直与非严格的 delete operator
雷同。
Reflect.deleteProperty(target, propertyKey)
target: 删除属性的指标对象 <br/>
propertyKey: 将被删除的属性的名称
const obj = {x: 1, y: 2}
delete obj.x
console.log(obj)
// {y: 2}
const obj = {x: 1, y: 2}
const d = Reflect.deleteProperty(obj, 'x')
console.log(obj, d)
// {y: 2} true
.get()
Reflect.get()
办法的工作形式,就像从 object (target[propertyKey])
中获取属性,但它是作为一个函数执行的。
Reflect.get(target, propertyKey[, receiver])
const obj = {x: 1, y: 2}
console.log(obj.x)
// 1
console.log(obj['x'])
// 1
const obj = {x: 1, y: 2}
console.log(Reflect.get(obj, 'x'))
// 1
console.log(Reflect.get([3, 4], 1))
// 4
.getOwnPropertyDescriptor()
静态方法 Reflect.getOwnPropertyDescriptor()
与 Object.getOwnPropertyDescriptor()
办法类似。如果在对象中存在,则返回给定的属性的属性描述符,否则返回 undefined
。
Reflect.getOwnPropertyDescriptor(target, propertyKey)
const obj = {x: 1, y: 2}
console.log(Object.getOwnPropertyDescriptor(obj, 'x'))
// {value: 1, writable: true, enumerable: true, configurable: true}
console.log(Reflect.getOwnPropertyDescriptor(obj, 'x'))
// {value: 1, writable: true, enumerable: true, configurable: true}
console.log(Reflect.getOwnPropertyDescriptor({ x: 'hello'}, 'y'))
// undefined
console.log(Reflect.getOwnPropertyDescriptor([], 'length'))
// {value: 0, writable: true, enumerable: false, configurable: false}
比照
如果该办法的第一个参数不是一个对象(一个原始值),那么将造成 TypeError
谬误。而对于Object.getOwnPropertyDescriptor
,非对象的第一个参数将被强制转换为一个对象解决。
Reflect.getOwnPropertyDescriptor("foo", 0);
// TypeError: "foo" is not non-null object
Object.getOwnPropertyDescriptor("foo", 0);
// {value: "f", writable: false, enumerable: true, configurable: false}
.getPrototypeOf()
静态方法 Reflect.getPrototypeOf()
与 Object.getPrototypeOf()
办法是一样的。都是返回指定对象的原型(即,外部的 [[Prototype]]
属性的值)。
Reflect.getPrototypeOf(target)
const d = New Date()
console.log(Reflect.getPrototypeOf(d))
// {constructor: ƒ, toString: ƒ, toDateString: ƒ, toTimeString: ƒ, toISOString: ƒ, …}
console.log(Object.getPrototypeOf(d))
// {constructor: ƒ, toString: ƒ, toDateString: ƒ, toTimeString: ƒ, toISOString: ƒ, …}
.has()
判断一个对象是否存在某个属性,和 in
运算符 的性能完全相同。
Reflect.has(target, propertyKey)
const obj = {x: 1, y: 2}
console.log(Reflect.has(obj, 'x'))
// true
console.log(Reflect.has(obj, 'z'))
// false
.isExtensible() —— 是否可扩大
Reflect.isExtensible
判断一个对象是否可扩大(即是否可能增加新的属性),它与 Object.isExtensible()
办法一样。
Reflect.isExtensible(target)
const obj = {x: 1, y: 2}
console.log(Reflect.isExtensible(obj))
// true
Object.freeze(obj)
obj.z = 3
console.log(Reflect.isExtensible(obj))
// false
console.log(obj)
// {x: 1, y: 2}
.ownKeys() —— 判断对象本身属性
Reflect.ownKeys
办法返回一个由指标对象本身的属性键组成的数组。它的返回值等同于 Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
Reflect.ownKeys(target)
const obj = {x: 1, y: 2}
console.log(Reflect.ownKeys(obj))
// ["x", "y"]
console.log(Reflect.ownKeys([]))
// ["length"]
console.log(Reflect.ownKeys([1,2]))
// ["0", "1", "length"]
.preventExtensions() —— 是否可扩大
等同于Object.freeze()
Reflect.preventExtensions
办法阻止新属性增加到对象 例如:避免未来对对象的扩大被增加到对象中)。该办法与 Object.preventExtensions()
办法统一
Reflect.preventExtensions(target)
const obj = {x: 1, y: 2}
console.log(Reflect.isExtensible(obj))
// true
Reflect.preventExtensions(obj)
obj.z = 3
console.log(Reflect.isExtensible(obj))
// false
console.log(obj)
// {x: 1, y: 2}
.set() —— 写数据
Reflect.set
办法容许你在对象上设置属性。它的作用是给属性赋值并且就像 property accessor
语法一样,然而它是以函数的形式。
Reflect.set(target, propertyKey, value[, receiver])
const obj = {x: 1, y: 2}
Reflect.set(obj, 'z', 4)
console.log(obj)
// {x: 1, y: 2, z: 4}
const arr = ['apple', 'pear']
Reflect.set(arr, 1, 'banana')
console.log(arr)
// ["apple", "banana"]
.setPrototypeOf()
Reflect.setPrototypeOf
办法扭转指定对象的原型(即,外部的 [[Prototype]]
属性值)
Reflect.setPrototypeOf(target, prototype)
const arr = ['apple', 'pear']
console.log(Reflect.getPrototypeOf(arr))
// [constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ,…]
Reflect.setPrototypeOf(arr, String.prototype)
console.log(Reflect.getPrototypeOf(arr))
// String {"", constructor: ƒ, anchor: ƒ, big: ƒ, blink: ƒ, …}
ES6-ES10 学习幅员