关于前端:详解ReflectReflect和Object的异同Reflect的一些内置方法以及方法注意点

4次阅读

共计 7354 个字符,预计需要花费 19 分钟才能阅读完成。

Reflect

Reflect领有 Object 对象的一些外部办法,某些办法会同时在 Object 对象和 Reflect 对象上部署,也就是说 Object 对象上存在的办法,通过 Reflect 也能够拜访到。
单论 Reflect 的话,能够这么了解,Reflect 就是继承了 Object 的某些内置办法,并且提供了优化

Object对象上的某些办法会有些缺点,例如:在 Object.defineProperty 上对一个不可写或不可枚举的属性进行 gettersetter时会抛出谬误,对于这个谬误,咱们须要 try catch 去捕捉,而 Reflect.defineProperty 则会抛出 false 来示意本次操作失败(Reflect对对象的操作都会抛出 truefalse来示意是否操作胜利)。
Object

const obj = {name : '东方不败'}
Object.defineProperty(obj,'age',{
    value : 100,
    writable : true,  // 只读
    configurable : false  // 不可删除和批改
})

Object.defineProperty(obj,'age',{get(){return 200}
})
console.log(obj.age); //  TypeError : Cannot redefine property: age
// 报错,不能从新定义属性

Reflect

const obj2 = {name : '东方求败'}
Object.defineProperty(obj2,'age',{
    value : 100,
    writable : true,  // 只读
    configurable : false  // 不可删除和批改
})

let status = Reflect.defineProperty(obj2,'age',{get(){return}
})

console.log(status); //  false
console.log(obj2.age); // 100
// Reflect 会抛出 false 示意此次操作失败

Object的局部操作是命令式的

let obj3 = {
    name : '东方不败',
    age : 100
}

console.log('name' in obj3);  // true
console.log(delete obj3.age);  // true
console.log(obj3);  // {name: '东方不败'}

Reflect 的操作是函数式的

let obj4 = {
    name : '东方求败',
    age : 100
}

console.log(Reflect.has(obj4,'name'));  // true
console.log(Reflect.deleteProperty(obj4,'age')); // true
console.log(obj4);  // {name: '东方求败'}

通过下面的案例能够晓得,Object外部的局部办法能够在 Reflect 上拜访,Reflect对象一共有 13 个静态方法,如下:

1、Reflect.apply(target, thisArg, args)

2、Reflect.construct(target, args)

3、Reflect.get(target, name, receiver)

4、Reflect.set(target, name, value, receiver)

5、Reflect.defineProperty(target, name, desc)

6、Reflect.deleteProperty(target, name)

7、Reflect.has(target, name)

8、Reflect.ownKeys(target)

9、Reflect.isExtensible(target)

10、Reflect.preventExtensions(target)

11、Reflect.getOwnPropertyDescriptor(target, name)

12、Reflect.getPrototypeOf(target)

13、Reflect.setPrototypeOf(target, prototype)

上面是对于下面一些办法的应用解释

Reflect.get(target,name,receiver)

Reglect.get()有三个参数,别离是

 1、`target`:指标对象
 2、`name`:对象属性
 3、`receiver`:代理对象(可疏忽)

作用:查找并返回 target 对象的 name 属性,如果该属性不存在则返回undefined

let o = {
    name : '西方',
    text : '不败'
}
console.log(Reflect.get(o,'name'));  // 西方


Reflect.set(target, name, value, receiver)

用于设置 target 对象的 name 属性等于value,如果批改胜利返回true,失败返回false

  let o2 = {name : '艺术概论',}
// 如果这里设置为不可批改那么 back 会输入 false,price 的值则为 undefined
//   Object.defineProperty(o2,'price',{
//     configurable : false
//   })
  let back = Reflect.set(o2,'price',100)
  console.log(back); // true
  console.log(o2);  // {name: '艺术概论', price: 100}


Reflect.has(obj, name)

相当于 Object 里的 in 运算符,判断以后属性在指标对象内是否存在,true存在,false不存在

let o3 = {name : '中国工艺美术史'}

console.log('name' in o3);  // true
console.log(Reflect.has(o3,'name')); // true

如果 Reflect.has 的第一个参数不是对象会报错


Reflect.deleteProperty(obj, name)

相当于 Object 的删除操作:delete obj.name,用于删除对象的属性

let o4 = {
    book : '疾风劲草',
    text : '一臂之力'
}
// Object
delete o4.book
console.log(o4);  // {text: '一臂之力'}
// Reflect
Reflect.deleteProperty(o4,'text')
console.log(o4);  // {}


Reflect.construct(target, args)

相当于 new class(params),这里的Reflect 能够不必 new 来创立调用构造函数的办法

function Person(name){this.name = name}

// new 写法
let onNew = new Person('西方')

// Reflect.construct
let onNew2 = Reflect.construct(Person,['不败'])

Reflect.construct的第一个参数不是函数会报错


Reflect.getPrototypeOf(obj)

对应 Object.getPrototypeOf(obj),用于读取对象的__proto__ 属性

let o5 = new String()

// Object.getPrototypeOf()
console.log(Object.getPrototypeOf(o5) == String.prototype); // true

// Reflect.getPrototypeOf()
console.log(Reflect.getPrototypeOf(o5) == String.prototype); // true


Reflect.setPrototypeOf(obj, newProto)

对应Object.setPrototypeOf(obj, newProto),用于设置指标对象的原型(prototype)

let o6 = {}
Reflect.setPrototypeOf(o6,Array.prototype)
console.log(o6.length);  // 0


Reflect.defineProperty(target, propertyKey, attributes)

相当于 Object.definePropertyReflect.defineProperty() 用来定义对象的属性。

let o7 = {name : '东方不败'}

Reflect.defineProperty(o7,'age',{
    value : 100,
    configurable: true,
    enumerable : true,
    writable : true
})
console.log(o7);  // {name: '东方不败', age: 100}

如果 Reflect.defineProperty() 的第一个参数不是对象,会抛出谬误。


Reflect.getOwnPropertyDescriptor(target, propertyKey)

对应Object.getOwnPropertyDescriptor,用来取得指定属性的形容对象

let o8 = {name : '东方不败'}

Reflect.defineProperty(o8,'age',{
    value : 100,
    configurable: true,
    enumerable : true,
    writable : true
})

let back8 = Reflect.getOwnPropertyDescriptor(o8,'age')
console.log(back8);  // {value: 100, writable: true, enumerable: true, configurable: true}

如果 Reflect.getOwnPropertyDescriptor() 的第一个参数不是对象,会抛出谬误。


Reflect.isExtensible (target)

相当于Object.isExtensible,返回布尔值,示意以后对象是否扩大

let o9 = {}
let back9 = Reflect.isExtensible(o9)
console.log(back9);  // true

如果参数不是对象会报错,非对象原本就是不可扩大的

console.log(Reflect.isExtensible(100));  // 报错


Reflect.preventExtensions(target)

相当于Object.preventExtensions,能够让指标对象变为不可扩大状态,返回布尔值示意是否设置胜利

let b = {}
let info =  Reflect.preventExtensions(b)
console.log(info); // true
console.log(Reflect.isExtensible(b)); // false

如果参数不是对象会报错


Reflect.ownKeys (target)

用于返回指标对象的所有属性,包含Symbol

let address = Symbol.for('武汉')
let b2 = {
    name : '东方不败',
    age : 100,
    [address] : '世界城广场'
}

let info2 = Reflect.ownKeys(b2)
console.log(info2); // ['name', 'age', Symbol(武汉)]

如果 Reflect.ownKeys ()的参数不是对象会报错


Reflect.apply(func, thisArg, args)

用于绑定 this 对象后执行给定函数。如果要给行数绑定一个 this 对象,能够应用 apply 的形式,但入股函数本人定义了本人的 apply 办法,就只能写成 Function.prototype.apply.call(fn, obj, args) 的办法嵌套,而 Reflect 则能够简化。

 let arr = [1,2,3,4,5,6,7]
 
 // 旧写法
 let a = Math.min.apply(Math, arr)
 let a2 = Math.max.apply(Math, arr)
 let a3 = Object.prototype.toString.call(a)
 console.log(a);   // 1
 console.log(a2);  // 7
 console.log(a3);  // [object Number]

 // 新写法
 let a4 = Reflect.apply(Math.min, Math, arr)
 let a5 = Reflect.apply(Math.max, Math, arr)
 let a6 = Reflect.apply(Object.prototype.toString, a4, [])
 console.log(a4);  // 1
 console.log(a5);  // 7
 console.log(a6);  // [object Number]
apply 办法:Function.apply(obj,args)办法能接管两个参数  
obj:这个对象将代替 Function 类里 this 对象
args:这个是数组,它将作为参数传给 Function

事实上 Reflect 上存在的一些动态函数对应与 ES2015 之前的 Object 上可用的办法,只管某些办法在行为上看起来类似,但它们之间经常存在着一些轻微的差别。Reflect对象一共有 13 中静态方法,下表具体介绍了 ObjectReflect API 上可用办法之间的差别。请留神,如果 API 中不存在某种办法,则将其标记为N/A

办法 Object Reflect
defineProperty() Object.defineProperty() 返回传递给函数的对象。如果未在对象上胜利定义属性,则返回 TypeError。 如果在对象上定义了属性,则 Reflect.defineProperty()返回 true,否则返回 false。
defineProperties() Object.defineProperties() 返回传递给函数的对象。如果未在对象上胜利定义属性,则返回 TypeError。 N/A
set() N/A 如果在对象上胜利设置了属性,则 Reflect.set()返回 true,否则返回 false。如果指标不是 Object,则抛出 TypeError
get() N/A Reflect.get()返回属性的值。如果指标不是 Object,则抛出 TypeError。
deleteProperty() N/A 如果属性从对象中删除,则 Reflect.deleteProperty()返回 true,否则返回 false。
getOwnPropertyDescriptor() 如果传入的对象参数上存在 Object.getOwnPropertyDescriptor(),则会返回给定属性的属性描述符,如果不存在,则返回 undefined。 如果给定属性存在于对象上,则 Reflect.getOwnPropertyDescriptor() 返回给定属性的属性描述符。如果不存在则返回 undefined,如果传入除对象(原始值)以外的任何货色作为第一个参数,则返回 TypeError
getOwnPropertyDescriptors() Object.getOwnPropertyDescriptors() 返回一个对象,其中蕴含每个传入对象的属性描述符。如果传入的对象没有领有的属性描述符,则返回一个空对象。 N/A
getPrototypeOf() Object.getPrototypeOf()返回给定对象的原型。如果没有继承的原型,则返回 null。在 ES5 中为非对象抛出 TypeError,但在 ES2015 中强制为非对象。 Reflect.getPrototypeOf()返回给定对象的原型。如果没有继承的原型,则返回 null,并为非对象抛出 TypeError。
setPrototypeOf() 如果对象的原型设置胜利,则 Object.setPrototypeOf()返回对象自身。如果设置的原型不是 Object 或 null,或者被批改的对象的原型不可扩大,则抛出 TypeError。 如果在对象上胜利设置了原型,则 Reflect.setPrototypeOf() 返回 true,否则返回 false(包含原型是否不可扩大)。如果传入的指标不是 Object,或者设置的原型不是 Object 或 null,则抛出 TypeError。
isExtensible() 如果对象是可扩大的,则 Object.isExtensible()返回 true,否则返回 false。如果第一个参数不是对象(原始值),则在 ES5 中抛出 TypeError。在 ES2015 中,它将被强制为不可扩大的一般对象并返回 false。 如果对象是可扩大的,则 Reflect.isExtensible() 返回 true,否则返回 false。如果第一个参数不是对象(原始值),则抛出 TypeError。
preventExtensions() Object.preventExtensions() 返回被设为不可扩大的对象。如果参数不是对象(为原始值),则在 ES5 中抛出 TypeError。在 ES2015 中,则将参数视为不可扩大的一般对象,并返回对象自身。 如果对象已变得不可扩大,则 Reflect.preventExtensions() 返回 true,否则返回 false。如果参数不是对象(为原始值),则抛出 TypeError。
keys() Object.keys()返回一个字符串数组,该字符串映射到指标对象本人的(可枚举)属性键。如果指标不是对象,则在 ES5 中抛出 TypeError,但将非对象指标强制为 ES2015 中的对象 N/A
ownKeys() N/A Reflect.ownKeys()返回一个属性名称数组,该属性名称映射到指标对象本人的属性键。如果指标不是 Object,则抛出 TypeError。

上述表格的数据比照起源链接:比拟 Reflect 和 Object 办法


案例源码:https://gitee.com/wang_fan_w/es6-science-institute

如果感觉这篇文章对你有帮忙,欢送点亮一下 star 哟

正文完
 0