ES6+ Reflect教程一
发布时间:2023-03-28 09:05:53 所属栏目:教程 来源:
导读:Reflect 是一个内置的对象,它提供了拦截 JavaScript 操作的方法。这些方法与 Proxy 中的 handlers 方法相同。与大多数全局对象不同 Reflect 并非一个构造函数,所以不能通过 new 运算符对其进行调用,或者将 Reflec
|
Reflect 是一个内置的对象,它提供了拦截 JavaScript 操作的方法。这些方法与 Proxy 中的 handlers 方法相同。与大多数全局对象不同 Reflect 并非一个构造函数,所以不能通过 new 运算符对其进行调用,或者将 Reflect 对象作为一个函数来调用。Reflect 的所有属性和方法都是静态的(类似 JSON 或者 Math 等对象)。 Reflect 可以检查对象上是否存在特定属性,可以使用 Reflect.has() 方法检测。 let key = Symbol.for('a'); const obj = { name: 'imooc', lession: 'ES6 Wiki', [key]: } console.log(Reflect.has(obj, 'name')); // true console.log(Reflect.has(obj, 'age')); // false 可以使用 Reflect.get() 方法获取对象上的属性值。 console.log(Reflect.get(obj, 'name')); // imooc 可以使用 Reflect.set() 方法为对象添加一个新的属性。 const res = Reflect.set(obj, 'age', ); console.log(res); // true console.log(obj); // {name: "imooc", lession: "ES6 Wiki", age: 7} 使用 Reflect.ownKeys() 方法获取对象上的自有属性。 console.log(Object.keys(obj)); // ["name", "lession"] console.log(Reflect.ownKeys(obj)); // ["name", "lession", Symbol(a)] 上面的代码可以看出,使用 Object.keys() 获取不到属性是 Symbol 的值。 Reflect 对象上的方法并不是专门为对象设计的,而是在语言层面的,它可以拿到语言内部的方法,和 Proxy 的结合可以实现元编程。并且每个操作都是有返回值的,上节我们使用 Proxy 简单地实现了 Vue3 的响应式。但是在 Vue3 源码中获取和设置对象上的属性使用的是 Reflect,Reflect 会返回一个状态表示获取和设置的成功与否。 // const res = target[key]; // 上节代码 const res = Reflect.get(target, key); // 获取target上属性key的值 // target[key] = value; // 上节代码 const result = Reflect.set(target, key, value); // 设置目标对象key属性的值 上面的两段代码是 Vue3 中的源码,因为在源码中需要知道获取或赋值的结果,因为可能获取失败。在 ES5 中如果想要监听劫持属性操作的结果需要使用 try...catch 的方式。 try { Object.defineProperty(obj, prop, descriptor); // success } catch (e) { // failure } Reflect 在操作对象时是有返回结果的,而 Object.defineProperty 是没有返回结果的,如果失败则会抛出异常,所以需要使用 try...catch 来捕获异常。 Object 中操作数据时,有一些是命令式的操作,如:delete obj.a 、name in obj ,Reflect 则将一些命令式的操作如 delete,in 等使用函数来替代,这样做的目的是为了让代码更加好维护,更容易向下兼容;也避免出现更多的保留字。 // ES5 'assign' in Object // true // ES6 Reflect.has(Object, 'assign') // true delete obj.name; // ES5 Reflect.deleteProperty(obj, 'name'); // ES6 Reflect 的出现是为了取代 Object 中一些属于语言层面的 API,这些 API 在 Object 上也是可以找到的,并且它们的功能基本是相同的。上面我们也提到了 Reflect 和 Proxy 中 handlers 的方法是一一对应的,在很多场景中它门都是配套使用的。这里我们就来学习一下 Reflect 提供的静态方法: Reflect.get() 方法是从对象中读取属性的值,类似 ES5 中属性访问器语法: obj[key] ,但是它是通过调用函数来获得返回结果的。 语法: Reflect.get(target, propertyKey[, receiver]) target:需要取值的目标对象; propertyKey:需要获取的值的键值; receiver:如果 target 对象中指定了 getter,receiver 则为 getter 调用时的 this 值。 如果目标值 target 类型不是 Object,则抛出一个 TypeError。 // Object var obj = { a: , b: }; Reflect.get(obj, "a"); // 1 // Array Reflect.get(["a", "b", "c"], ); // "one" 第三个参数 receiver 是 this 所在的上下文,不传时指的是当前对象,如果传如一个人对象则 this 指向该对象。下面我们来看个实例: let obj = { name: 'imooc', lesson: 'ES5 Wiki', get info() { console.log(`这是 ${this.lesson}`); return } }; Reflect.get(obj, 'info'); // 这是 ES5 Wiki Reflect.get(obj, 'info', {lesson: 'ES6 Wiki'}); // 这是 ES5 Wiki Reflect.set() 是在一个对象上设置一个属性,类似 ES5 中属性设置语法:obj[key] = value ,它也是通过调用函数的方式来对对象设置属性的。 语法: Reflect.set(target, propertyKey, value[, receiver]) target:表示要操作的目标对象; propertyKey:表示要设置的属性名; value:表示设置的属性值; receiver:表示的是一个 this 值,如果我们在设置值的时候遇到 setter 函数,那么这个 receiver 值表示的就是 setter 函数中的 this 值。 这个函数会返回一个 Boolean 值,表示在目标对象上设置属性是否成功。 // Object var obj = {}; Reflect.set(obj, "name", "imooc"); // true console.log(obj.name); // "imooc" // Array var arr = ["a", "b", "c"]; Reflect.set(arr, , "C"); // true console.log(arr); // ["a", "b", "C"] 使用可以截断数组: var arr = ["a", "b", "c"]; Reflect.set(arr, "length", ); // true console.log(arr); // ["a", "b"] 当有 receiver 参数时,如果 receiver 对象中有 propertyKey 属性,则会使用 receiver 对象中的值。 Reflect.set(obj, 'lession', 'ES5 Wiki', {lession: 'ES6 Wiki', age: }); console.log(obj); // {name: "imooc", lesson: "ES5 Wiki"} Reflect.deleteproperty() 方法允许删除对象的属性。它类似 ES5 中的 delete 操作符,但它也是一个函数,通过调用函数来实现。 语法: Reflect.deleteProperty(target, propertyKey) target:表示要操作的目标对象; propertyKey:表示要删除的属性。 这个函数的返回值是一个 Boolean 值,如果成功的话,返回 true;失败的话返回 false。我们来看下面的实例: var obj = { name: 'imooc', lession: 'ES6 Wiki' }; var r1 = Reflect.deleteProperty(obj, 'name'); console.log(r1); // true console.log(obj); // {lession: "ES6 Wiki"} var r2 = Reflect.deleteProperty(Object.freeze(obj), 'lession'); console.log(r2); // false 上面的例子中使用 Object.freeze() 方法来冻结 obj 对象使之不能被修改。 Reflect.has() 方法可以检查一个对象上是否含有特定的属性,这个方法相当于 ES5 的 in 操作符。 语法: Reflect.has(target, propertyKey) target:表示要操作的目标对象; propertyKey: 属性名,表示需要检查目标对象是否存在此属性。 这个函数的返回结果是一个 Boolean 值,如果存在就返回 true,不存在就返回 false。当然如果目标对象 (target) 不是一个对象,那么就会抛出一个异常。 Reflect.has({x: }, "x"); // true Reflect.has({x: }, "y"); // false // 如果该属性存在于原型链中,也返回true Reflect.has({x: }, "toString"); // true 这方法也可检查构造函数的属性。 function A(name) { this.name = name || 'imooc'; } // 在原型上添加方法 A.prototype.getName = function() { return this.name; }; var a = new A(); console.log('name' in a); // true console.log('getName' in a); // true let r1 = Reflect.has(a, 'name'); let r2 = Reflect.has(a, 'getName'); console.log(r1, r2); // true true Reflect.ownKeys() 返回一个由目标对象自身的属性键组成的数组。 语法: Reflect.ownKeys(target) target:表示目标对象 如果这个目标对象不是一个对象那么这个函数就会抛出一个异常。这个数组的值等于 Object.getownPropertyNames(target).concat(Object.getownPropertySymbols(target)) 我们来看下面的实例: let a = Symbol.for('a'); let b = Symbol.for('b'); let obj = { [a]: , [b]: , key1: , key2: }; let arr1 = Object.getownPropertyNames(obj); console.log(arr1); // [ 'key1', 'key2' ] let arr2 = Object.getownPropertySymbols(obj); console.log(arr2); // [ Symbol(a), Symbol(b) ] let arr3 = Reflect.ownKeys(obj); console.log(arr3); // [ 'key1', 'key2', Symbol(a), Symbol(b) ] 本节主要学习了 ES6 新增的全局对象 Reflect ,它的目的是为了分离 Object 中属于语言部分的内容,每个使用 Reflect 下的方法操作的对象都要返回值。 Reflect 对象和 Proxy 下的方法是一一对应的,二者配合可以实现很多功能。Vue3 中的数据响应就是使用的它们。 (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
