JS中反射Reflect的基本使用
文章目录
- 一、概述
- 二、静态方法
- 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
对象上。现阶段,某些方法同时在 Object
和 Reflect
对象上部署,未来的新方法将只部署在 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 obj
和 delete 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
如果第一个参数是 undefined
或 null
,Object.setPrototypeOf
和 Reflect.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.getOwnPropertyNames
与Object.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的基本使用相关推荐
- js中的Reflect入门讲解
这个玩意 和 那个 Proxy 对象一样, 是es6为了操作对象而提供的Api, 个人理解吧,应该是为了防止你直接操作对象(object, 函数),做出的一个代替方案: 比如之前使用的 Obejct. ...
- Js中Reflect对象
Js中Reflect对象 Reflect是ES6起JavaScript内置的对象,提供拦截JavaScript操作的方法,这些方法与Proxy对象的handlers中的方法基本相同. 描述 Refle ...
- Reflect.ownKeys()与Object.keys()区别 以及 JS中的可枚举属性与不可枚举属性
代码test1: var obj = {} Object.defineProperty(obj, 'method1', {value: function () {alert("Non enu ...
- ES6中的reflect和proxy和一个on-change
理解reflect 反射,在运行时获得程序或程序集每一个类型的成员和成员信息. JAVA里程序中一般的对象的类型都是在编译期就确定下来的,而Java反射机制可以动态地创建对象并调用其属性,这样的对象的 ...
- Golang的反射reflect深入理解和示例
[TOC] Golang的反射reflect深入理解和示例 [记录于2018年2月] 编程语言中反射的概念 在计算机科学领域,反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机 ...
- JavaScript – 6.JS面向对象基础(*) + 7.Array对象 + 8.JS中的Dictionary + 9.数组、for及其他...
6.JS面向对象基础(*) 7.Array对象 7.1 练习:求一个数组中的最大值.定义成函数. 7.2 练习:将一个字符串数组输出为|分割的形式,比如"刘在石|金钟国|李光洙|HAHA|宋 ...
- Java中反射的三种常用方式
Java中反射的三种常用方式 package com.xiaohao.test; public class Test{ public static void main(String[] args) t ...
- [原] 探索 EventEmitter 在 Node.js 中的实现
你有没有想过,为什么浏览器的 div 上可以绑定多个 onclick 事件,点击一下 div 可以触发全部的事件,jquery 的 .on(),.off(),one() 又是如何实现的?Node.js ...
- 反射 reflect
反射 reflect 什么是反射,其实就是反省,自省的意思 反射指的是以一个对象应该具备,可以检测,修改,增加自身属性的能力 反射就是通过字符串操作属性 涉及到的四个函数,这四个函数就是普通的内置函数 ...
- 浅谈Java反射(Reflect)技术--常用方法
Java反射(Reflect)技术 概念:动态获取在当前Java虚拟机中的类.接口或者对象等等信息(运行过程中读取内容) 1.作用(面试问题): 1.1 解除两个类之间的耦合性,即在未得到依赖类的情况 ...
最新文章
- linux u8 头文件,2019-12-11 转载TCP/IP编程常用C语言头文件
- python读取 application_python PyQt5.QtWidgets.QApplication类(sys.argv)(app应用对象类)...
- Oracle区分中文和英文,oracle中中英文段落划分实现
- uva 120——Stacks of Flapjacks
- 查看代码 index.html,Javascript查看大图功能代码实现
- c# xls 复制一行_编写干净的C#代码技巧
- R语言do.call函数简单说明
- freebsd mysql tmp_FREEBSD MYSQL数据库备份
- 下岗工人到达退休年龄,养老保险未缴纳满15年,补缴合适吗?
- .NET 获取类型中的属性
- RedisTemplate 常用方法、序列化方式、基于 Redis 实现分布式锁
- Windows Defender保护历史记录清空方法
- 计算机桌面有阴影,电脑桌面图标有蓝色阴影 怎么去除桌面图标阴影
- 1962年 电影版 越剧红楼梦 剧本
- UltraVNC源码编译流程
- apache与tomcat动静分离
- 帝国cms 7.5 utf8集成百度编辑器完美集成版
- [安卓开发] 快递物流信息布局
- python中的while语句
- 408知识框架总结——数据结构