【ES6】Reflect 反射
文章目录
- 设计目的
- 静态方法
- 1. 取值:Reflect.get()
- 2. 设值:Reflect.set()
- 3. 判断:Reflect.has()
- 4. 删除:Reflect.deleteProperty()
- 5. 定义:Reflect.defineProperty()
- 6. 原型:Reflect.getPrototypeOf()
- 7. 原型:Reflect.setPrototypeOf()
- 8. 绑定:Reflect.apply()
- 9. new:Reflect.construct()
- 10. 扩展:Reflect.isExtensible ()
- 11. 禁扩:Reflect.preventExtensions()
- 12. 属性:Reflect.ownKeys()
- 13. 描述:Reflect.getOwnPropertyDescriptor()
- Reflect 是为了操作对象而提供的新 API
- Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。
- 这些方法与proxy handlers (en-US)的方法相同。
- Reflect不是一个函数对象,因此它是不可构造的。
- 所以不能通过new运算符对其进行调用,或者将Reflect对象作为一个函数来调用。
- Reflect的所有属性和方法都是静态的
设计目的
其一:
- 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。
- 现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。
- 也就是说,从Reflect对象上可以拿到语言内部的方法。
其二:
- 修改某些Object方法的返回结果,让其变得更合理。
// 老写法
try {// 定义一个数据,在无法定义属性时,会抛出一个错误Object.defineProperty(target, property, attributes);// success
} catch (e) {// failure
}// 新写法
if (Reflect.defineProperty(target, property, attributes)) { // 而Reflect则会返回false// success
} else {// failure
}
其三:
- 让Object操作都变成函数行为。
// 老写法
// 判断assign属性是否在Object 对象中
'assign' in Object // true// 新写法
Reflect.has(Object, 'assign') // true
其四:
- Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。
- 这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。
- 也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
// Proxy方法拦截target对象的属性赋值行为。
Proxy(target, {set: function(target, name, value, receiver) {// 它采用Reflect.set方法将值赋值给对象的属性,确保完成原有的行为,然后再部署额外的功能。var success = Reflect.set(target, name, value, receiver);if (success) {console.log('property ' + name + ' on ' + target + ' set to ' + value);}return success;}
});
// 每一个Proxy对象的拦截操作(get、delete、has)
// 内部都调用对应的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);}
});
静态方法
1. 取值:Reflect.get()
Reflect.get()
方法:获取对象身上某个属性的值(类似于target[name]
)
/* 参数说明 */
1. target: 需要取值的目标对象
2. propertyKey: 需要获取的值的键值
3. receiver: 如果target对象中指定了getter,receiver则为getter调用时的this值。/* 语法 */
Reflect.get(target, propertyKey[, receiver])/* 返回值 */
1. 如果含有该属性,返回对应属性值
2. 如果没有该属性,则返回 undefined/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
var myObject = {foo: 1,bar: 2,get baz() {return this.foo + this.bar;},
}
Reflect.get(myObject, 'foofoo') // undefined
Reflect.get(myObject, 'bar') // 2
Reflect.get(myObject, 'baz') // 3// Object
var obj = { x: 1, y: 2 };
Reflect.get(obj, "x"); // 1// Array
var arr = ["zero", "one"];
Reflect.get(arr, 1); // "one"// 带有get处理程序的代理
var x = {p: 1};
var obj = new Proxy(x, {get(t, k, r) { return k + "bar"; }
});
Reflect.get(obj, "foo"); // "foobar"// 非对象
Reflect.get(1, 'foo') // 报错
Reflect.get(false, 'foo') // 报错
- 如果
propertyKey
属性部署了读取函数(getter
),则读取函数的this
绑定receiver
。
var myObject = {foo: 1,bar: 2,get baz() {return this.foo + this.bar;},
};var myReceiverObject = {foo: 4,bar: 4,
};Reflect.get(myObject, 'baz', myReceiverObject) // 8
2. 设值:Reflect.set()
Reflect.set()
:以函数的方式给属性赋值。
/* 参数说明 */
1. target: 设置属性的目标对象。
2. propertyKey: 设置的属性的名称。
3. value: 设置的值。
4. receiver: 如果遇到 setter,receiver则为setter调用时的this值。/* 语法 */
Reflect.set(target, propertyKey, value[, receiver])/* 返回值 */
1. 如果设置成功,返回 true
2. 如果设置失败,则返回 false/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
var myObject = {foo: 1,set bar(value) {return this.foo = value;},
}myObject.foo // 1Reflect.set(myObject, 'foo', 2);
myObject.foo // 2Reflect.set(myObject, 'bar', 3)
myObject.foo // 3// Object
var obj = {};
Reflect.set(obj, "prop", "value"); // true
obj.prop; // "value"// Array
var arr = ["duck", "duck", "duck"];
Reflect.set(arr, 2, "goose"); // true
arr[2]; // "goose"// 它可以截断数组.
Reflect.set(arr, "length", 1); // true
arr; // ["duck"];// With just one argument, propertyKey and value are "undefined".
var obj = {};
Reflect.set(obj); // true
Reflect.getOwnPropertyDescriptor(obj, "undefined");
// { value: undefined, writable: true, enumerable: true, configurable: true }// 非对象类型
Reflect.set(1, 'foo', {}) // 报错
Reflect.set(false, 'foo', {}) // 报错
- 如果
propertyKey
属性设置了赋值函数,则赋值函数的this
绑定receiver
。
var myObject = {foo: 4,set bar(value) {return this.foo = value;},
};var myReceiverObject = {foo: 0,
};Reflect.set(myObject, 'bar', 1, myReceiverObject);
myObject.foo // 4
myReceiverObject.foo // 1
3. 判断:Reflect.has()
Reflect.has()
: 判断一个对象是否存在某个属性(等同于in
运算符)
/* 参数说明 */
1. target: 目标对象.
2. propertyKey: 属性名,需要检查目标对象是否存在此属性。/* 语法 */
Reflect.has(target, propertyKey)/* 返回值 */
1. 如果该属性存在,返回 true
2. 如果该属性不存在,则返回 false/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
var myObject = {foo: 1,
};// 旧写法
'foo' in myObject // true// 新写法
Reflect.has(myObject, 'foo') // trueReflect.has({x: 0}, "x"); // true
Reflect.has({x: 0}, "y"); // false// 如果该属性存在于原型链中,返回true
Reflect.has({x: 0}, "toString");// Proxy 对象的 .has() 句柄方法
obj = new Proxy({}, {has(t, k) { return k.startsWith("door"); }
});
Reflect.has(obj, "doorbell"); // true
Reflect.has(obj, "dormitory"); // false
4. 删除:Reflect.deleteProperty()
Reflect.deleteProperty()
:用于删除对象的属性(等同于delete obj[name]
)
/* 参数说明 */
1. target: 删除属性的目标对象。
2. propertyKey: 需要删除的属性的名称。/* 语法 */
Reflect.get(target, propertyKey)/* 返回值 */
1. 如果该属性不存在 或者 删除成功,返回 true
2. 如果该属性删除失败,则返回 false/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
const myObj = { foo: 'bar' };// 旧写法
delete myObj.foo;// 新写法
Reflect.deleteProperty(myObj, 'foo');var obj = { x: 1, y: 2 };
Reflect.deleteProperty(obj, "x"); // true
obj; // { y: 2 }var arr = [1, 2, 3, 4, 5];
Reflect.deleteProperty(arr, "3"); // true
arr; // [1, 2, 3, , 5]// 如果属性不存在,返回 true
Reflect.deleteProperty({}, "foo"); // true// 如果属性不可配置,返回 false
Reflect.deleteProperty(Object.freeze({foo: 1}), "foo"); // false
5. 定义:Reflect.defineProperty()
Reflect.defineProperty()
:用来为对象定义属性(等同于Object.defineProperty
)
/* 参数说明 */
1. target: 目标对象。
2. propertyKey: 要定义或修改的属性的名称。
3. attributes: 要定义或修改的属性的描述。/* 语法 */
Reflect.defineProperty(target, propertyKey, attributes)/* 返回值 */
1. 如果该定义成功,返回 true
2. 如果该定义失败,则返回 false/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
function MyDate() {/*…*/
}// 旧写法
Object.defineProperty(MyDate, 'now', {value: () => Date.now()
});// 新写法
Reflect.defineProperty(MyDate, 'now', {value: () => Date.now()
});let obj = {}
Reflect.defineProperty(obj, 'x', {value: 7}) // true
obj.x // 7
6. 原型:Reflect.getPrototypeOf()
Reflect.getPrototypeOf()
:用于读取对象的__proto__
属性(等同于Object.getPrototypeOf(obj)
)
/* 参数说明 */target: 获取原型的目标对象。/* 语法 */
Reflect.getPrototypeOf(target)/* 返回值 */
1. 给定对象的原型。
2. 如果给定对象没有继承的属性,则返回 null。/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
const myObj = new FancyThing();// 旧写法
Object.getPrototypeOf(myObj) === FancyThing.prototype;// 新写法
Reflect.getPrototypeOf(myObj) === FancyThing.prototype;Reflect.getPrototypeOf({}); // Object.prototype
Reflect.getPrototypeOf(Object.prototype); // null
Reflect.getPrototypeOf(Object.create(null)); // null
- 与
Object.getPrototypeOf
的区别是:
// 如果参数为 Object,返回结果相同
Object.getPrototypeOf({}) // Object.prototype
Reflect.getPrototypeOf({}) // Object.prototype// 在 ES5 规范下,对于非 Object,抛异常
Object.getPrototypeOf('foo') // Throws TypeError
Reflect.getPrototypeOf('foo') // Throws TypeError// 在 ES2015 规范下,Reflect 抛异常, Object 强制转换非 Object
Object.getPrototypeOf('foo') // String.prototype
Reflect.getPrototypeOf('foo') // Throws TypeError
7. 原型:Reflect.setPrototypeOf()
Reflect.setPrototypeOf()
:方法用于设置目标对象的原型(等同于Object.setPrototypeOf()
)
/* 参数说明 */
1. target: 设置原型的目标对象。
2. propertyKey: 对象的新原型(一个对象或 null)。/* 语法 */
Reflect.setPrototypeOf(target, prototype)/* 返回值 */
1. 原型设置成功,返回 true。
2. 原型设置失败,则返回 false。/* 异常 */
1. 如果目标值类型不是 Object ,抛出一个 TypeError。
2. prototype 既不是对象也不是 null,抛出一个 TypeError。
- 示例:
const myObj = {};// 旧写法
Object.setPrototypeOf(myObj, Array.prototype);// 新写法
Reflect.setPrototypeOf(myObj, Array.prototype);
myObj.length // 0Reflect.setPrototypeOf({}, Object.prototype); // true// 它可以改变一个对象的 [[Prototype]] 为 null.
Reflect.setPrototypeOf({}, null); // true// 如果目标不是可扩展的,则返回false
Reflect.setPrototypeOf(Object.freeze({}), null); // false// 如果它导致原型链循环,则返回false。
var target = {};
var proto = Object.create(target);
Reflect.setPrototypeOf(target, proto); // false
- 第一个参数情况:
/* 第一个参数非对象 */
Object.setPrototypeOf(1, {})
// 1Reflect.setPrototypeOf(1, {})
// TypeError: Reflect.setPrototypeOf called on non-object/* 第一个参数是undefined或null */
Object.setPrototypeOf(null, {})
// TypeError: Object.setPrototypeOf called on null or undefinedReflect.setPrototypeOf(null, {})
// TypeError: Reflect.setPrototypeOf called on non-object
8. 绑定:Reflect.apply()
Reflect.apply()
:用于绑定this对象后执行给定函数(等同于Function.prototype.apply.call()
)
/* 参数说明 */
1. target: 目标函数。
2. thisArgument: target函数调用时绑定的this对象。
3. argumentsList: target函数调用时传入的实参列表,该参数应该是一个类数组的对象。值。/* 语法 */
Reflect.apply(target, thisArgument, argumentsList)/* 返回值 */
1. 返回值是调用完带着指定参数和 this 值的给定的函数后返回的结果。/* 异常 */
1. 如果 target 对象不可调用,抛出 TypeError。
- 示例:
Reflect.apply(Math.floor, undefined, [1.75]);
// 1;Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]);
// "hello"Reflect.apply(RegExp.prototype.exec, /ab/, ["confabulation"]).index;
// 4Reflect.apply("".charAt, "ponies", [3]);
// "i"
- 一般来说,如果要绑定一个函数的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 type = Object.prototype.toString.call(youngest);// 新写法
const youngest = Reflect.apply(Math.min, Math, ages);
const oldest = Reflect.apply(Math.max, Math, ages);
const type = Reflect.apply(Object.prototype.toString, youngest, []);
9. new:Reflect.construct()
Reflect.construct()
:调用构造函数的方法(等同于new target(...args)
)
/* 参数说明 */
1. target: 被运行的目标构造函数
2. argumentsList: 类数组,目标构造函数调用时的参数。
3. newTarget: 作为新创建对象的原型对象的constructor属性, 参考 new.target 操作符,默认值为target。/* 语法 */
Reflect.construct(target, argumentsList[, newTarget])/* 返回值 */
1. 以target(如果newTarget存在,则为newTarget)函数为构造函数,argumentList为其初始化参数的对象实例。/* 异常 */
1. 如果target或者newTarget不是构造函数,抛出TypeError,异常。
- 示例:
function Greeting(name) {this.name = name;
}// new 的写法
const instance = new Greeting('张三');// Reflect.construct 的写法
const instance = Reflect.construct(Greeting, ['张三']);unction OneClass() {this.name = 'one';
}function OtherClass() {this.name = 'other';
}// 创建一个对象:
var obj1 = Reflect.construct(OneClass, args, OtherClass);// 与上述方法等效:
var obj2 = Object.create(OtherClass.prototype);
OneClass.apply(obj2, args);console.log(obj1.name); // 'one'
console.log(obj2.name); // 'one'console.log(obj1 instanceof OneClass); // false
console.log(obj2 instanceof OneClass); // falseconsole.log(obj1 instanceof OtherClass); // true
console.log(obj2 instanceof OtherClass); // true
10. 扩展:Reflect.isExtensible ()
Reflect.isExtensible()
:判断当前对象是否可扩展(等同于Object.isExtensible
)
/* 参数说明 */
1. target: 检查是否可扩展的目标对象。/* 语法 */
Reflect.isExtensible(target)/* 返回值 */
1. 如果当前对象可扩展,返回 true
2. 如果当前对象不可扩展,则返回 false/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
const myObject = {};// 旧写法
Object.isExtensible(myObject) // true// 新写法
Reflect.isExtensible(myObject) // true// 新对象是可扩展的。
var empty = {};
Reflect.isExtensible(empty); // === true// 但这是可以改变的.
Reflect.preventExtensions(empty);
Reflect.isExtensible(empty); // === false// 根据定义,密封对象是不可扩展的.
var sealed = Object.seal({});
Reflect.isExtensible(sealed); // === false// 根据定义,冻结对象也是不可扩展的.
var frozen = Object.freeze({});
Reflect.isExtensible(frozen); // === false
- 如果参数不是对象,
Object.isExtensible
会返回false,因为非对象本来就是不可扩展的, - 而
Reflect.isExtensible
会报错。
Object.isExtensible(1) // false
Reflect.isExtensible(1) // 报错
11. 禁扩:Reflect.preventExtensions()
Reflect.preventExtensions()
:阻止新属性添加到对象(等同于Object.preventExtensions
)
/* 参数说明 */
1. target: 需要取值的目标对象阻止扩展的目标对象。/* 语法 */
Reflect.preventExtensions(target)/* 返回值 */
1. 如果设置成功,返回 true
2. 如果设置失败,则返回 false/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
var myObject = {};// 旧写法
Object.preventExtensions(myObject) // Object {}// 新写法
Reflect.preventExtensions(myObject) // true// 默认情况下,对象是可扩展的
var empty = {};
Reflect.isExtensible(empty); // === true// 但这是可以改变的
Reflect.preventExtensions(empty);
Reflect.isExtensible(empty); // === false
- 与
Object.preventExtensions
的区别
// ES5 环境
Object.preventExtensions(1) // 报错// ES6 环境
Object.preventExtensions(1) // 1// ES5、ES6 环境
Reflect.preventExtensions(1) // 报错
12. 属性:Reflect.ownKeys()
Reflect.ownKeys()
:返回对象的所有属性(等同于Object.getOwnPropertyNames
+Object.getOwnPropertySymbols
)
/* 参数说明 */
1. target: 获取自身属性键的目标对象。/* 语法 */
Reflect.ownKeys(target)/* 返回值 */
1. 由目标对象的自身属性键组成的 Array。/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
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)]
13. 描述:Reflect.getOwnPropertyDescriptor()
Reflect.getOwnPropertyDescriptor()
:获取指定属性的描述对象(等同于Object.getOwnPropertyDescriptor
)
/* 参数说明 */
1. target: 需要寻找属性的目标对象。
2. propertyKey: 获取自己的属性描述符的属性的名称。/* 语法 */
Reflect.getOwnPropertyDescriptor(target, propertyKey)/* 返回值 */
1. 如果属性存在于给定的目标对象中,则返回属性描述符;
2. 否则,返回 undefined。/* 异常 */
1. 如果目标值类型不是 Object,则抛出一个 TypeError。
- 示例:
Reflect.getOwnPropertyDescriptor({x: "hello"}, "x");
// {value: "hello", writable: true, enumerable: true, configurable: true}Reflect.getOwnPropertyDescriptor({x: "hello"}, "y");
// undefined
- 与
Object.getOwnPropertyDescriptor
的区别
// 第一个参数不是对象,抛出错误,表示参数非法
Reflect.getOwnPropertyDescriptor("foo", 0);
// TypeError: "foo" is not non-null object// 第一个参数不是对象,不报错,返回 undefined,
Object.getOwnPropertyDescriptor("foo", 0);
// { value: "f", writable: false, enumerable: true, configurable: false }
【ES6】Reflect 反射相关推荐
- Proxy(代理,拦截器),Reflect(反射)
Proxy(代理,拦截器),Reflect(反射) Proxy: 代理: var duixaing = {"name":"小胖","age" ...
- Proxy代理 和 Reflect反射(反射的是obj)的概念
1. Proxy代理 // 供应商(原始对象)let obj = {time:'2018-01-03',name:'net',_r: "123"}// 创建代理商,传入obj数据l ...
- es6 --- Reflect的静态方法
Reflect.get(target, name, receiver): 查找并返回 target对象的 name属性,若没有,返回undefined var myObject = {foo: 1,b ...
- GO语言reflect反射篇
1.1 reflect反射是什么,为什么需要反射 GO 反射的意义:Go 语言的 ORM 库离不开它,Go 语言的 json 序列化库离不开它, fmt包字符串格式化离不开它,Go 语言的运行时更是离 ...
- 利用 Proxy 代理与 Reflect 反射实现 mv 模型视图,实现一个 打怪升级 的小游戏“勇士之战”
利用 Proxy 代理与 Reflect 反射实现 mv 模型视图,多层数据动态渲染页面,模仿 vue3 双向绑定中 viewModel 核心功能,实现一个 打怪升级 的小游戏"勇士之战&q ...
- GO语言基础之reflect反射
反射reflection 1. 反射可以大大的提高程序的灵活性,使得 interface{} 有更大的发挥余地 2. 反射使用 TypeOf 和 ValueOf 函数从接口中获取目标对象信息 3. 反 ...
- Go 语言编程 — reflect 反射机制
目录 文章目录 目录 为什么需要反射? reflect 包 通过 reflect.TypeOf() 获取对象的反射类型 reflect.Type 通过 reflect.Elem() 获取指针所指向的对 ...
- golang reflect 反射 简介
和Java语言一样,Go也实现运行时反射,这为我们提供一种可以在运行时操作任意类型对象的能力.比如我们可以查看一个接口变量的具体类型,看看一个结构体有多少字段,如何修改某个字段的值等等. TypeOf ...
- es6 Reflect对象的静态方法
Reflect对象的静态方法 Reflect对象一共有 13 个静态方法. Reflect.apply(target, thisArg, args) Reflect.construct(target, ...
- es6 Reflect对象简介
Reflect对象简介 Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API.Reflect对象的设计目的有这样几个. (1) 将Object对象的一些明显属于语言内部 ...
最新文章
- PYthon3:函数实现“自动售卖机”功能
- 【C语言】20-static和extern关键字2-对变量的作用
- uygurqa输入法android,uygurqa输入法
- 为什么都在吹鸿蒙,真的是吹爆鸿蒙
- Python 参考文档
- 【转载】 quartus中调用modelsim仿真的方法
- ASP.NET Core 运行原理解剖[2]:Hosting补充之配置介绍
- java minor gc_Java Minor发布计划再次进行了调整
- Java Annotation认知(包括框架图、详细介绍、示例说明)
- IT 已成为最疯狂的加班行业,没有之一
- 15.explain
- Leetcode之两棵二叉搜索树中的所有元素
- php mysql sum用法_mysql怎么使用sum()求id字段的和?
- Raki的统计学习方法笔记0x2章:感知机
- Everything搜索_使用方法
- python爬虫qq音乐_Python爬虫实战:采集全部QQ音乐歌曲
- 罗技G500游戏鼠标
- B站粉丝计数器 | ESP32轻松学(Arduino版)
- 买阿里云服务器多少钱,不同预算可购买的配置及价格汇总
- iphone ipad 为孩子创建 apple id