文章目录

  • 一、概述
  • 二、静态方法
    • 1、Reflect.get(target, name, receiver)
    • 2、Reflect.set(target, name, value, receiver)
    • 3、Reflect.has(obj, name)
    • 4、Reflect.deleteProperty(obj, name)
    • 5、Reflect.construct(target, args)
    • 6、Reflect.getPrototypeOf(obj)
    • 7、Reflect.setPrototypeOf(obj, newProto)
    • 8、Reflect.apply(func, thisArg, args)
    • 9、Reflect.defineProperty(target, propertyKey, attributes)
    • 10、Reflect.getOwnPropertyDescriptor(target, propertyKey)
    • 11、Reflect.isExtensible (target)
    • 12、Reflect.preventExtensions(target)
    • 13、Reflect.ownKeys (target)
  • 三、参考资料

一、概述

Reflect 对象的设计目的有这样几个。

(1) 将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty ),放到 Reflect 对象上。现阶段,某些方法同时在 ObjectReflect 对象上部署,未来的新方法将只部署在 Reflect 对象上。也就是说,从 Reflect 对象上可以拿到语言内部的方法。

(2)修改某些 Object 方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc) 在无法定义属性时,会抛出一个错误,定义成功时返回修改后的对象。而 Reflect.defineProperty(obj, name, desc) 在定义属性成功时返回 true ,失败时返回 false

// 老写法
try {Object.defineProperty(target, property, attributes);// success
} catch (e) {// failure
}// 新写法
if (Reflect.defineProperty(target, property, attributes)) {// success
} else {// failure
}

(3)让 Object 操作都变成函数行为。某些 Object 操作是命令式,比如 name in objdelete obj[name],而 Reflect.has(obj, name)Reflect.deleteProperty(obj, name) 让它们变成了函数行为。

// 老写法
'assign' in Object // true// 新写法
Reflect.has(Object, 'assign') // true

(4)Reflect 对象的方法与 Proxy 对象的方法一 一对应,只要是 Proxy 对象的方法,就能在 Reflect对象上找到对应的方法。这就让 Proxy 对象可以方便地调用对应的 Reflect 方法,完成默认行为,作为修改行为的基础。也就是说,不管 Proxy 怎么修改默认行为,总可以在 Reflect 上获取默认行为。

var loggedObj = new Proxy(obj, {get(target, name) {console.log('get', target, name);return Reflect.get(target, name);},deleteProperty(target, name) {console.log('delete' + name);return Reflect.deleteProperty(target, name);},has(target, name) {console.log('has' + name);return Reflect.has(target, name);}
});

二、静态方法

Reflect 对象一共有 13 个静态方法。

  • Reflect.apply(target, thisArg, args)
  • Reflect.construct(target, args)
  • Reflect.get(target, name, receiver)
  • Reflect.set(target, name, value, receiver)
  • Reflect.defineProperty(target, name, desc)
  • Reflect.deleteProperty(target, name)
  • Reflect.has(target, name)
  • Reflect.ownKeys(target)
  • Reflect.isExtensible(target)
  • Reflect.preventExtensions(target)
  • Reflect.getOwnPropertyDescriptor(target, name)
  • Reflect.getPrototypeOf(target)
  • Reflect.setPrototypeOf(target, prototype)

上面这些方法的作用,大部分与 Object 对象的同名方法的作用都是相同的,而且它与 Proxy 对象的方法是一 一对应的。

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

Reflect.get 方法查找并返回 target 对象的 name 属性,如果没有该属性,则返回 undefined

let obj = {name: 'webchang',age: 18,get info() {return this.name + ' ' + this.age;}
}
console.log(Reflect.get(obj, 'name')); // webchang
console.log(Reflect.get(obj, 'age'));  // 18
console.log(Reflect.get(obj, 'info')); // webchang 18

如果 Reflect.get(target, name, receiver) 的第二个参数属性部署了读取函数(getter):

  • 没有第三个参数,this 绑定当前对象
  • 有第三个参数,读取函数的 this 绑定到第三个参数 receiver 上。
let obj = {name: 'webchang',age: 18,get info() {return this.name + ' ' + this.age;}
}let obj2 = {name: '张三',age: 40
}console.log(Reflect.get(obj, 'info', obj2));// 张三 40

target 对象也可以是数组:

Reflect.get([1,2,3], 1) // 输出索引 1 对应的值:2

如果第一个参数不是对象,Reflect.get 方法会报错。

Reflect.get(1, 'foo') // 报错 TypeError: Reflect.get called on non-object
Reflect.get(false, 'foo') // 报错

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

Reflect.set 方法设置 target 对象的 name 属性等于 value

let obj = {name: 'webchang',set age(value) {this._age = value;}
}
console.log(obj.name); // webchang
Reflect.set(obj, 'name', '李四');
console.log(obj.name); // 李四Reflect.set(obj, 'age', 18);
console.log(obj._age); // 18

3、Reflect.has(obj, name)

Reflect.has 方法对应 name in obj 里面的 in 运算符。如果 Reflect.has() 方法的第一个参数不是对象,会报错。

var myObject = {foo: 1,
};// 旧写法
'foo' in myObject // true// 新写法
Reflect.has(myObject, 'foo') // true

4、Reflect.deleteProperty(obj, name)

Reflect.deleteProperty 方法等同于 delete obj[name],用于删除对象的属性。该方法返回一个布尔值。如果删除成功,或者被删除的属性不存在,返回true;删除失败,被删除的属性依然存在,返回false。

如果 Reflect.deleteProperty() 方法的第一个参数不是对象,会报错。

const myObj = { foo: 'bar' };// 旧写法
delete myObj.foo;// 新写法
Reflect.deleteProperty(myObj, 'foo');

5、Reflect.construct(target, args)

Reflect.construct 方法等同于 new target(...args) ,这提供了一种不使用 new,来调用构造函数的方法。第一个参数是函数,第二个参数是数组。

function Person(name, age) {this.name = name;this.age = age;
}// new 的写法
let p1 = new Person('webchang', 18);// Reflect.construct 的写法,两种写法最终效果一样
let p2 = Reflect.construct(Person, ['webchang', 18]);

6、Reflect.getPrototypeOf(obj)

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

function Person() {}
let p = new Person();console.log(Object.getPrototypeOf(p) === Person.prototype); // true
console.log(Reflect.getPrototypeOf(p) === Person.prototype);// true

如果参数不是对象,Object.getPrototypeOf 会将这个参数转为对象,然后再运行,而Reflect.getPrototypeOf 会报错。

Object.getPrototypeOf(1); // Number {[[PrimitiveValue]]: 0}
Reflect.getPrototypeOf(1); // TypeError: Reflect.getPrototypeOf called on non-object

7、Reflect.setPrototypeOf(obj, newProto)

Reflect.setPrototypeOf 方法用于设置目标对象的原型(prototype),对应 Object.setPrototypeOf(obj, newProto) 方法。它返回一个布尔值,表示是否设置成功。

let obj = {name: 'webchang'
}// 旧写法,设置成功会返回修改后的对象
Object.setPrototypeOf(obj, Array.prototype);// 新写法,设置成功会返回 true
Reflect.setPrototypeOf(obj, Array.prototype);

如果第一个参数不是对象,Object.setPrototypeOf 会返回第一个参数本身,而 Reflect.setPrototypeOf 会报错。

Object.setPrototypeOf(1, {})
// 1Reflect.setPrototypeOf(1, {})
// TypeError: Reflect.setPrototypeOf called on non-object

如果第一个参数是 undefinednullObject.setPrototypeOfReflect.setPrototypeOf 都会报错。

Object.setPrototypeOf(null, {})
// TypeError: Object.setPrototypeOf called on null or undefinedReflect.setPrototypeOf(null, {})
// TypeError: Reflect.setPrototypeOf called on non-object

8、Reflect.apply(func, thisArg, args)

第一个参数是函数,第二个参数用来指定 this 的指向,第三个参数是数组。

一般来说,如果要绑定一个函数的 this 对象,可以这样写 fn.apply(obj, args),但是如果函数定义了自己的 apply 方法,就只能写成 Function.prototype.apply.call(fn, obj, args) ,采用 Reflect 对象可以简化这种操作。

const ages = [11, 33, 12, 54, 18, 96];// 旧写法
const youngest = Math.min.apply(Math, ages);
const oldest = Math.max.apply(Math, ages);// 新写法
const youngest = Reflect.apply(Math.min, Math, ages);
const oldest = Reflect.apply(Math.max, Math, ages);

9、Reflect.defineProperty(target, propertyKey, attributes)

Reflect.defineProperty 方法基本等同于 Object.defineProperty,用来为对象定义属性。

function MyDate() {/*…*/
}// 旧写法
Object.defineProperty(MyDate, 'now', {value: () => Date.now()
});// 新写法
Reflect.defineProperty(MyDate, 'now', {value: () => Date.now()
});

10、Reflect.getOwnPropertyDescriptor(target, propertyKey)

let obj = {name: 'webchang'
}
console.log(Object.getOwnPropertyDescriptor(obj, 'name'));
console.log(Reflect.getOwnPropertyDescriptor(obj, 'name'));


如果第一个参数不是对象,Object.getOwnPropertyDescriptor(1, 'foo') 不报错,返回 undefined,而Reflect.getOwnPropertyDescriptor(1, 'foo') 会抛出错误,表示参数非法。

11、Reflect.isExtensible (target)

Reflect.isExtensible 方法对应 Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展。

let obj = {}// 旧写法
Object.isExtensible(obj); // true// 新写法
Reflect.isExtensible(obj); // trueObject.freeze(obj);
Reflect.isExtensible(obj); // false

如果参数不是对象,Object.isExtensible 会返回 false,因为非对象本来就是不可扩展的,而 Reflect.isExtensible 会报错。

Object.isExtensible(1) // false
Reflect.isExtensible(1) // TypeError: Reflect.isExtensible called on non-object

12、Reflect.preventExtensions(target)

Reflect.preventExtensions 对应 Object.preventExtensions 方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。

var myObject = {};// 旧写法
Object.preventExtensions(myObject) // Object {}// 新写法
Reflect.preventExtensions(myObject) // true

如果参数不是对象,Object.preventExtensions 在 ES5 环境报错,在 ES6 环境返回传入的参数,而Reflect.preventExtensions会报错。

// ES5 环境
Object.preventExtensions(1) // 报错// ES6 环境
Object.preventExtensions(1) // 1// 新写法
Reflect.preventExtensions(1) // 报错

13、Reflect.ownKeys (target)

Reflect.ownKeys 方法用于返回对象的所有属性,基本等同于 Object.getOwnPropertyNamesObject.getOwnPropertySymbols 之和。如果 Reflect.ownKeys() 方法的第一个参数不是对象,会报错。

var myObject = {foo: 1,bar: 2,[Symbol.for('baz')]: 3,[Symbol.for('bing')]: 4,
};// 旧写法
Object.getOwnPropertyNames(myObject)
// ['foo', 'bar']Object.getOwnPropertySymbols(myObject)
//[Symbol(baz), Symbol(bing)]// 新写法
Reflect.ownKeys(myObject)
// ['foo', 'bar', Symbol(baz), Symbol(bing)]

三、参考资料

Reflect - ECMAScript 6

前端学习交流QQ群,群内学习讨论的氛围很好,大佬云集,期待您的加入:862748629 点击加入

JS中反射Reflect的基本使用相关推荐

  1. js中的Reflect入门讲解

    这个玩意 和 那个 Proxy 对象一样, 是es6为了操作对象而提供的Api, 个人理解吧,应该是为了防止你直接操作对象(object, 函数),做出的一个代替方案: 比如之前使用的 Obejct. ...

  2. Js中Reflect对象

    Js中Reflect对象 Reflect是ES6起JavaScript内置的对象,提供拦截JavaScript操作的方法,这些方法与Proxy对象的handlers中的方法基本相同. 描述 Refle ...

  3. Reflect.ownKeys()与Object.keys()区别 以及 JS中的可枚举属性与不可枚举属性

    代码test1: var obj = {} Object.defineProperty(obj, 'method1', {value: function () {alert("Non enu ...

  4. ES6中的reflect和proxy和一个on-change

    理解reflect 反射,在运行时获得程序或程序集每一个类型的成员和成员信息. JAVA里程序中一般的对象的类型都是在编译期就确定下来的,而Java反射机制可以动态地创建对象并调用其属性,这样的对象的 ...

  5. Golang的反射reflect深入理解和示例

    [TOC] Golang的反射reflect深入理解和示例 [记录于2018年2月] 编程语言中反射的概念 在计算机科学领域,反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机 ...

  6. JavaScript – 6.JS面向对象基础(*) + 7.Array对象 + 8.JS中的Dictionary + 9.数组、for及其他...

    6.JS面向对象基础(*) 7.Array对象 7.1 练习:求一个数组中的最大值.定义成函数. 7.2 练习:将一个字符串数组输出为|分割的形式,比如"刘在石|金钟国|李光洙|HAHA|宋 ...

  7. Java中反射的三种常用方式

    Java中反射的三种常用方式 package com.xiaohao.test; public class Test{ public static void main(String[] args) t ...

  8. [原] 探索 EventEmitter 在 Node.js 中的实现

    你有没有想过,为什么浏览器的 div 上可以绑定多个 onclick 事件,点击一下 div 可以触发全部的事件,jquery 的 .on(),.off(),one() 又是如何实现的?Node.js ...

  9. 反射 reflect

    反射 reflect 什么是反射,其实就是反省,自省的意思 反射指的是以一个对象应该具备,可以检测,修改,增加自身属性的能力 反射就是通过字符串操作属性 涉及到的四个函数,这四个函数就是普通的内置函数 ...

  10. 浅谈Java反射(Reflect)技术--常用方法

    Java反射(Reflect)技术 概念:动态获取在当前Java虚拟机中的类.接口或者对象等等信息(运行过程中读取内容) 1.作用(面试问题): 1.1 解除两个类之间的耦合性,即在未得到依赖类的情况 ...

最新文章

  1. linux u8 头文件,2019-12-11 转载TCP/IP编程常用C语言头文件
  2. python读取 application_python PyQt5.QtWidgets.QApplication类(sys.argv)(app应用对象类)...
  3. Oracle区分中文和英文,oracle中中英文段落划分实现
  4. uva 120——Stacks of Flapjacks
  5. 查看代码 index.html,Javascript查看大图功能代码实现
  6. c# xls 复制一行_编写干净的C#代码技巧
  7. R语言do.call函数简单说明
  8. freebsd mysql tmp_FREEBSD MYSQL数据库备份
  9. 下岗工人到达退休年龄,养老保险未缴纳满15年,补缴合适吗?
  10. .NET 获取类型中的属性
  11. RedisTemplate 常用方法、序列化方式、基于 Redis 实现分布式锁
  12. Windows Defender保护历史记录清空方法
  13. 计算机桌面有阴影,电脑桌面图标有蓝色阴影 怎么去除桌面图标阴影
  14. 1962年 电影版 越剧红楼梦 剧本
  15. UltraVNC源码编译流程
  16. apache与tomcat动静分离
  17. 帝国cms 7.5 utf8集成百度编辑器完美集成版
  18. [安卓开发] 快递物流信息布局
  19. python中的while语句
  20. 408知识框架总结——数据结构

热门文章

  1. 用java计算三角形周长_三角形求周长和面积完整的解决方案
  2. echarts绘制地图
  3. 如何给Word参考文献加方括号
  4. win10-11全版本下载地址MSDN纯净版ISO-20220217更新
  5. Excel2007打开文件时,不显示内容,需要拖拽进去才能显示
  6. 信息系统项目管理师考试经验和心得
  7. 关于信号强度单位db和dBm
  8. 触摸屏与TSC2005触摸屏控制器
  9. 使用dd命令修改bin文件
  10. [杂题]「FJOI2018」所罗门王的宝藏