Reflect APIjava
【java
的反射机制】是在编译阶段不知道是哪一个类被加载,而是在运行的时候才加载、执行。js
中的apply
就是反射机制。数组
Reflect
是一个内置的对象,它提供拦截 JavaScript
操做的方法,这些方法与处理器对象的方法相同。Reflect
不是一个函数对象,所以它是不可构造的。app
与大多数全局对象不一样,Reflect
没有构造函数。你不能将其与一个new
运算符一块儿使用,或者将Reflect
对象做为一个函数来调用。Reflect
的全部属性和方法都是静态的( 就像Math对象 )函数
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
就统一了操做方式。this
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() | 阻止新属性添加到对象 |
Reflect.apply(target, thisArgument, argumentsList)target:目标函数,必传<br/>
thisArgument:target函数调用时绑定的this对象,没必要须<br/>
argumentsList:target函数调用时传入的实参列表,该参数应该是一个类数组的对象,没必要须spa
//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
实际应用prototype
// 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
使用反射的方式去实现建立类的实例,相似于new target(…args)
.code
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())
静态方法 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
上面移除这些方法。
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
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
静态方法 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 }
静态方法 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: ƒ, …}
判断一个对象是否存在某个属性,和 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
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}
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"]
等同于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}
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"]
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: ƒ, …}