首页 > 其他分享 >详解Reflect:Reflect和Object的异同,Reflect的一些内置方法以及方法注意点

详解Reflect:Reflect和Object的异同,Reflect的一些内置方法以及方法注意点

时间:2023-02-21 23:56:57浏览次数:72  
标签:console name 对象 Object Reflect 详解 log

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哟

标签:console,name,对象,Object,Reflect,详解,log
From: https://www.cnblogs.com/wang-fan-w/p/17142942.html

相关文章

  • 一文详解 jitpack 多渠道maven库发布
    先说一下,为什么会有这篇文章?最初接触JitPack时,发现网络上大量涉及JitPack的教程不可用。通过两天的研究才搞明白:1.不同的gradle版本,gradleapi使用方式与JitPack配......
  • Symbol详解
    SymbolSymbol是es6引入的一个新的原始数据类型,是一个独一无二的值。目前为止,js的数据类型有以下几种:数据类型说明undefinedundefinednullnullboolean......
  • Map数据结构详解
    MapObject本质上是键值对的集合(Hash结构),但Object只能将字符串当做键,这就给Object带来了很大的限制。letdata={}lets={name:'东方不败'}data[s]='西......
  • LVS三种工作模式及原理详解
    什么是LVS?摘自:https://blog.csdn.net/qq_59369367/article/details/124951685LVS是LinuxVirtualServer的简写,也就是Linux虚拟服务器,是一个虚拟的服务器集群系统,......
  • 套接字连接以及TCP三次握手详解
    在套接字和地址文章中,我们画出基于套接字接口网络应用的一张图,本文章就是详细解释这些函数具体怎么实现的。socket创建套接字客户端和服务器使用socket函数来创建一个套......
  • Go 中的反射 reflect 介绍和基本使用
    一、什么是反射在计算机科学中,反射(英语:reflection)是指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力。用比喻来说,反射就是程序在运行的时候......
  • JSON.toJSONString(object, SerializerFeature.WriteMapNullValue);第二个参数作用
      这里箭头指向的位置,因为sent-1中的value为空,所以并未打印出来。第二个使用:JSON.toJSONString(map,SerializerFeature.WriteMapNullValue)指定序列化方式就打印出......
  • Kroger EDI 855 采购订单确认报文详解
    本文着重讲述KrogerEDI项目中,供应商发给Kroger的X12855EDI规范报文(采购订单确认)解读。在此前的文章如何读懂X12报文中,我们对X12已经做了详细的介绍,大家可以以此为基础......
  • bfs详解
    bfs详解1,bfs的基本概念bfs是广度优先搜索,是一种对树形结构的遍历,他的思想是先选定一个点,从这个点出发,每次只走一步,分为四个方向,直到找到正确答案,相较于dfs的直接递归,bfs......
  • Flutter帧率监控 | 由浅入深,详解获取帧率的那些事
    前言做线上帧率监控上报时,少不了需要弄明白如何通过代码获取实时帧率的需求,这篇文章通过图解配合Flutter性能调试工具的方式一步步通俗易懂地让你明白获取帧率的基础知识,以......