JS反射机制及Reflect详解
⼀、什么是反射机制
反射机制是在编译阶段不知道是哪个类被加载,⽽是在运⾏的时候才加载、执⾏。
也就是说,反射机制指的是程序在运⾏时能够获取⾃⾝的信息。
js中的apply就是反射机制。
⼆、Reflect
1、Reflect 定义
Reflect是⼀个内建的对象,⽤来提供⽅法去拦截 JavaScript 的操作。
Reflect不是⼀个函数对象,所以它是不可构造的,也就是说它不是⼀个构造器,不能通过new操作符去新建或者将其作为⼀个函数去调⽤Reflect对象。
Reflect的所有属性和⽅法都是静态的。
Reflect内部封装了⼀系列对对象的底层操作
Reflect成员⽅法就是Proxy处理对象的默认实现
const proxy = new Proxy(obj, {
get(target, property) {
// 如果没有定义 get ⽅法,那么默认返回的就是 Reflect 的 get ⽅法
(target, property)
}
})
2、Reflect API 汇总
Reflect提供了⼀套⽤于操作对象的API,我们之前操作对象可以⽤Object上⾯的⼀些⽅法,也可以⽤in、delete 这种操作符,使⽤Reflect就统⼀了操作⽅式
handler ⽅法默认调⽤功能
()获取对象⾝上某个属性的值
set Reflect.set()在对象上设置属性
has Reflect.has()判断⼀个对象是否存在某个属性
deleteProperty Reflect.deleteProperty()删除对象上的属性
PrototypeOf()获取指定对象原型的函数
setProperty Reflect.setPrototypeOf()设置或改变对象原型的函数
isExtensible Reflect.isExtensible()判断⼀个对象是否可扩展(即是否能够添加新的属性)preventExtensions Reflect.preventExtensions()阻⽌新属性添加到对象OwnPropertyDescriptor()获取给定属性的属性描述符
defineProperty Reflect.defineProperty()定义或修改⼀个对象的属性
ownKeys Reflect.ownKeys()返回由⽬标对象⾃⾝的属性键组成的数组
apply Reflect.apply()对⼀个函数进⾏调⽤操作,同时可以传⼊⼀个数组作为调⽤参数
struct()对构造函数进⾏ new 操作,实现创建类的实例.preventExtensions Reflec
t.preventExtensions()阻⽌新属性添加到对象
3、.apply()
Reflect.apply(target, thisArgument, argumentsList)
target:⽬标函数(必选)
thisArgument:target 函数调⽤时绑定的 this 对象(可选)
argumentsList:target 函数调⽤时传⼊的实参列表,该参数应该是⼀个类数组的对象(可选)
① ES5 ⽤法
先指定⽅法,再去调⽤ apply
Math.floor.apply(null, [1.72])  // 1
② ES6 ⽤法
先传递 apply,再指定是哪个⽅法
Reflect.apply(Math.floor, null, [1.72])  // 1
静态扫描时 Math.floor 是没有被执⾏,等到运⾏时再动态的将 Math.floor 作为参数传进来的
③实际应⽤
// ES5 ⽤法
let price = 101.5
if (price > 100) {
price = Math.floor.apply(null, [price])
} else {
price = il.apply(null, [price])
}
price  // 101
/
/ ES6 ⽤法
let price = 101.5
Reflect.apply(price > 100 ? Math.floor : il, null, [price])  // 101
4、.construct()
使⽤反射的⽅式去实现创建类的实例,类似于new target(…args)
target:被运⾏的⽬标函数(必选)
argumentsList:调⽤构造函数的数组或者伪数组(可选)
newTarget:该参数为构造函数,参考 new.target 操作符,如果没有 newTarget 参数,默认和 target ⼀样(可选)
① ES5 ⽤法
let a = new Date()
② ES6 ⽤法
let b = struct(Date, [])
5、.defineProperty()
静态⽅法Reflect.defineProperty()基本等同于Object.defineProperty()⽅法
Reflect.defineProperty(target, propertyKey, attributes)
target:⽬标对象(必选)
propertyKey:要定义或修改的属性的名称(可选)
attributes:要定义或修改的属性的描述(可选)
① ES5 ⽤法
const student = {}
const r = Object.defineProperty(student, 'name', { value: 'Mike' })
student  // {name: "Mike"}
r  // {name: "Mike"}
② ES6 ⽤法
const student = {}
const r = Reflect.defineProperty(student, 'name', { value: 'Mike' })
student  // {name: "Mike"}
r  // true
这两个⽅法效果上来看是⼀摸⼀样的,都可以改变⼀个对象的值
区别在于返回值不同:Object是返回这个值,Reflect是返回true
PS: 在W3C中,以后所有的Object上⾯的⽅法,都会慢慢迁移到Reflect对象,可能以后会在Object 上⾯移除这些⽅法
6、.deleteProperty()
Reflect.deleteProperty允许你删除⼀个对象上的属性,返回⼀个Boolean值表⽰该属性是否被成功删除,它⼏乎与⾮严格的delete operator相同
Reflect.deleteProperty(target, propertyKey)
target:删除属性的⽬标对象
propertyKey:将被删除的属性的名称
① ES5 ⽤法
const obj = { x: 1, y: 2 }
const a = delete obj.x
obj  // {y: 2}
a  // true
② ES6 ⽤法
const obj = { x: 1, y: 2 }
const a = Reflect.deleteProperty(obj, 'x')
obj  // {y: 2}
a  // true
7、.get()
<()⽅法的⼯作⽅式,就像从object (target[propertyKey])中获取属性,但它是作为⼀个函数执⾏的(target, propertyKey[, receiver])
① ES5 ⽤法
const obj = { x: 1, y: 2 }
obj.x  // 1
obj['x']  // 1
② ES6 ⽤法
js argumentsconst obj = { x: 1, y: 2 }
<(obj, 'x')  // 1
<(['a', 'b', 'c'], 1)  // b
8、.getOwnPropertyDescriptor()
静态⽅法OwnPropertyDescriptor()与OwnPropertyDescriptor()⽅法相似
如果在对象中存在,则返回给定的属性的属性描述符,否则返回undefined
① ES5 ⽤法
const obj = { x: 1, y: 2 }
// {value: 1, writable: true, enumerable: true, configurable: true}
② ES6 ⽤法
const obj = { x: 1, y: 2 }
// {value: 1, writable: true, enumerable: true, configurable: true}
// undefined
// {value: 0, writable: true, enumerable: false, configurable: false}
③对⽐
如果OwnPropertyDescriptor的第⼀个参数不是⼀个对象(⼀个原始值),那么将造成TypeError错误⽽对于OwnPropertyDescriptor,⾮对象的第⼀个参数将被强制转换为⼀个对象处理
// TypeError: "foo" is not non-null object
// { value: "f", writable: false, enumerable: true, configurable: false }
9、.getPrototypeOf()
静态⽅法PrototypeOf()与PrototypeOf()⽅法是⼀样的,都是返回指定对象的原型(即,内部的[[Prototype]]属性的值)
① ES5 ⽤法
const d = New Date()
// {constructor: ƒ, toString: ƒ, toDateString: ƒ, toTimeString: ƒ, toISOString: ƒ, …}
② ES6 ⽤法
const d = New Date()
// {constructor: ƒ, toString: ƒ, toDateString: ƒ, toTimeString: ƒ, toISOString: ƒ, …}
10、.has()
判断⼀个对象是否存在某个属性,和in运算符的功能完全相同
Reflect.has(target, propertyKey)
const obj = { x: 1, y: 2 }
Reflect.has(obj, 'x')  // true
Reflect.has(obj, 'z')  // false
11、.isExtensible()
判断⼀个对象是否可扩展
Reflect.isExtensible与Object.isExtensible⽅法⼀样,都是判断⼀个对象是否可扩展(即是否能够添加新的属性)Reflect.isExtensible(target)
const obj = { x: 1, y: 2 }
Reflect.isExtensible(obj)  // true
Object.freeze(obj)  // 阻⽌新属性添加到对象
obj.z = 3
Reflect.isExtensible(obj)  // false
obj  // {x: 1, y: 2}
12、.ownKeys()
判断对象⾃⾝属性
Reflect.ownKeys⽅法返回⼀个由⽬标对象⾃⾝的属性键组成的数组,它的返回值等同于
`OwnPropertyNames(target).OwnPropertySymbols(target))
Reflect.ownKeys(target)
const obj = { x: 1, y: 2 }
Reflect.ownKeys(obj)  // ["x", "y"]
Reflect.ownKeys([])  // ["length"]
Reflect.ownKeys([1, 2])  // ["0", "1", "length"]
13、.preventExtensions()
阻⽌新属性添加到对象,等同于Object.freeze()
Reflect.preventExtensions⽅法阻⽌新属性添加到对象,例如:防⽌将来对对象的扩展被添加到对象中,与Object.preventExtensions()⽅法⼀致
Reflect.preventExtensions(target)
const obj = { x: 1, y: 2 }
Reflect.isExtensible(obj)  // true
Reflect.preventExtensions(obj)  // 阻⽌新属性添加到对象
obj.z = 3
Reflect.isExtensible(obj)  // false
obj  // {x: 1, y: 2}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。