Reflect 认识

  1. ReflectES6 引入的一个内置对象,它提供了一套与 JavaScript 内置操作直接对应的、用于对象操作的静态方法,这些方法的设计目的是为了使操作对象的行为变得更为清晰、更易于使用,并且在某些情况下提供更好的错误处理机制;

  2. Reflect 对象的方法与 Object 对象上的同名方法 (如 get、set、defineProperty 等) 相对应,但它们通常返回一个布尔值以表示操作是否成功,而不是静默失败;

Reflect 特点

  1. 函数式设计

    1. Reflect 对象的方法全部是函数,而不是在对象上作为属性直接调用;
    2. 这种设计使得 Reflect 方法更易于组合、更易于使用函数式编程风格;
  2. 与内建操作对应

    1. Reflect 提供的方法与 JavaScript 内置的许多操作 (如属性访问、定义、删除等) 相对应,形成了一个统一、明确的 API 集合;
    2. 这使得开发者可以通过 Reflect 对象直接调用这些底层操作,而不是依赖语言的隐式行为或使用 Object 类型上的某些方法;
  3. 返回值一致性

    1. Reflect 方法通常返回一个布尔值来表示操作的成功与否,或者返回与操作相关的具体结果;
    2. 这与一些 Object 类型上的方法可能返回 undefined 或静默失败不同,提高了代码的可预测性和调试性;
  4. 错误处理

    1. Reflect 方法在遇到非法操作时会抛出适当的异常,如 TypeErrorRangeError,而不是默默地失败;
    2. 这种严格的错误处理有助于在开发阶段尽早发现潜在问题;
  5. 元编程支持

    1. Reflect 提供了一系列方法用于进行对象的元编程操作,如获取和设置属性描述符、操作对象的原型链、检查对象的扩展性等;
    2. 这些方法为实现更高级的编程模式和库提供了底层支持;

Reflect 常用方法

Reflect.get()

Reflect.get() 方法是从对象中读取属性的值,类似 ES5 中属性访问器语法:obj[key],但是它是通过调用函数来获得返回结果的;

JavaScript
JavaScript
/**
 * 语法
 *  target:需要取值的目标对象,如果目标值 target 类型不是 Object,则抛出一个 TypeError
 *  propertyKey:需要获取的值的键值
 *  receiver:如果 target 对象中指定了 getter, 则 getter 调用时 this 指向 receiver
 */
Reflect.get(target, propertyKey[, receiver]);
/**
 * receiver 是 this 所在的上下文,不传时指的是当前对象,如果传入一个对象则 this 指向该对象;
 */

let obj = {
  name: 'es',
  lesson: 'ES5 Wiki',
  get info() {
    console.log(`这是 ricepudding ${this.lesson}`);
    return 0;
  }
};

Reflect.get(obj, 'info');	// 这是 ricepudding ES5 Wiki
Reflect.get(obj, 'info', { lesson: 'ES6 Wiki' });	// 这是 ricepudding ES6 Wiki

Reflect.set()

Reflect.set() 是在一个对象上设置一个属性,类似 ES5 中属性设置语法:obj[key] = value,它也是通过调用函数的方式来对对象设置属性的,返回值是一个布尔值;

JavaScript
JavaScript
/**
 * 语法:
 *  target:表示要操作的目标对象
 *  propertyKey:表示要设置的属性名
 *  value:表示设置的属性值
 *  receiver:如果 target 对象中指定了 setter, 则 setter 调用时 this 指向 receiver
 */
Reflect.set(target, propertyKey, value[, receiver]);
/**
 * 如果 target 对象中指定了 setter, 则 setter 调用时 this 指向 receiver
 */

var obj = {
  name: 'zhangsan',
  set lession(arg) { // arg:ES5 Wiki
    console.log(this);  // this 指向 myReceiverObject
    this.lession = arg;
  }
};

var myReceiverObject = { lession: 'ES6 Wiki', age: 18 };
if (Reflect.set(obj, 'lession', 'ES5 Wiki', myReceiverObject)) {
  console.log(myReceiverObject); // { lession: 'ES5 Wiki', age: 18 }
}

Reflect.defineProperty()

Reflect.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性;

  1. Reflect.defineProperty() 返回的是 Boolean 值,Object.defineProperty() 返回的是个对象;
  2. Reflect.defineProperty() 可以根据返回值检查属性是否被成功定义,而 Object.defineProperty() 只能通过 try…catch 去捕获其中的错误,相比之下 Reflect.defineProperty() 方法更加方便;
JavaScript
JavaScript
/**
 * 语法:
 *  target:目标对象,如果 target 不是 Object,抛出一个 TypeError
 *  propertyKey:需要定义或修改的属性的名称
 *  attributes:需要定义或修改的属性的描述
 */
Reflect.defineProperty(target, propertyKey, attributes);
var obj = {};
if (Reflect.defineProperty(obj, 'a', { value: 10 })) {
  console.log(obj.a); // 10
  // 成功 todo
} else {
  // 失败 todo
}


try {
  let obj = {};
  Object.defineProperty(obj, 'a', { value: 10 });
} catch (e) {
  // 如果失败,捕获的异常
}

Reflect.deleteProperty()

Reflect.deleteProperty() 方法允许删除对象的属性,它类似 ES5 中的 delete 操作符,但它也是一个函数,通过调用函数来实现,返回值是一个 Boolean 值;

JavaScript
JavaScript
/**
 * 语法
 *  target:表示要操作的目标对象
 *  propertyKey:表示要删除的属性
 */
Reflect.deleteProperty(target, propertyKey);
var obj = {
  name: 'ricepudding',
  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
console.log(obj); // {lession: "ES6 Wiki"}

Reflect.apply()

Reflect.apply() 通过指定的参数列表发起对目标 (target) 函数的调用;

JavaScript
JavaScript
/**
 * 语法:
 *  target:目标函数
 *  thisArgument:target 函数调用时绑定的 this 对象
 *  argumentsList:target 函数调用时传入的实参列表,该参数应该是一个类数组的对象
 */
Reflect.apply(target, thisArgument, argumentsList);
const arr = [1, 6, 7, 10, 2, 5];

console.log(Math.max(...arr));

console.log(Function.prototype.apply.call(Math.max, null, arr));	// 10

console.log(Reflect.apply(Math.max, null, arr));  // 10

Reflect.construct()

Reflect.construct()new 操作符构造函数相似,相当于运行 new target(…args),提供了一种新的不使用 new 来调用构造函数的方法;

JavaScript
JavaScript
/**
 * 语法:
 *  target:被运行的目标构造函数
 *  argumentsList:类数组,目标构造函数调用时的参数
 *  newTarget:(可选)表示使用 Reflect.construct 后生成的实列对象是谁的实列,如果没有该参数,默认生成的实列对象就和 target 构造函数是一样的
 */
Reflect.construct(target, argumentsList[, newTarget]);
class A {
  constructor(name) {
    this.name = name;
  }
  getName() {
    return this.name;
  }
}

class B {
  constructor(age) {
    this.age = age || 18;
  }
  getAge() {
    return this.age;
  }
}


let a = Reflect.construct(A, ['David']);
let b = Reflect.construct(A, ['David'], B);
console.log(a instanceof A); // true
console.log(b instanceof B); // true

Reflect.has()

Reflect.has() 方法可以检查一个对象及原型链上是否含有特定的属性,这个方法相当于 ES5in 操作符,返回值是一个 Boolean 值;

JavaScript
JavaScript
JavaScript
/**
 * 语法:
 *  target:表示要操作的目标对象,如果不是一个对象,会抛出一个异常
 *  propertyKey: 属性名,表示需要检查目标对象是否存在此属性
 */
Reflect.has(target, propertyKey);
Reflect.has({ x: 0 }, "x"); // true
Reflect.has({ x: 0 }, "toString");	// true

Reflect.has({ x: 0 }, "y"); // false
class A {
  constructor(name) {
    this.name = name;
  }
  getName() {

  }
}

var a = new A();
console.log(Reflect.has(a, 'name')); // true
console.log(Reflect.has(a, 'getName')); // true

Reflect.ownKeys()

Reflect.ownKeys() 返回一个由目标对象自身的属性键组成的数组;

JavaScript
JavaScript
/**
 * 语法:
 *  target:表示目标对象,如果不是对象会抛出一个异常
 */
Reflect.ownKeys(target);
let a = Symbol.for('a');
let b = Symbol.for('b');

let obj = {
  [a]: 10,
  [b]: 20,
  key1: 30,
  key2: 40
};

console.log(Object.getOwnPropertyNames(obj)); // [ 'key1', 'key2' ]
console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(a), Symbol(b) ]
console.log(Reflect.ownKeys(obj)); // [ 'key1', 'key2', Symbol(a), Symbol(b) ]

Reflect.preventExtensions()

阻止目标对象 target 扩展 (不能再添加新属性),返回一个布尔值;

const obj = { a: 1 };
console.log(Reflect.preventExtensions(obj)); // 输出:true
console.log(Reflect.isExtensible(obj)); // 输出:false

obj.b = 2; // 尝试添加新属性
console.log(obj.b); // 输出:undefined,因为对象已不可扩展

Reflect.isExtensible()

判断目标对象 target 是否可扩展 (即是否可以添加新属性),返回一个布尔值;

constobj = { a: 1 };
console.log(Reflect.isExtensible(obj)); // true

Object.preventExtensions(obj); // 阻止对一个对象进一步添加新的属性(不可扩展)
console.log(Reflect.isExtensible(obj)); // false 

Reflect.getPrototypeOf()

返回目标对象 target 的原型 (即[[Prototype]]),相当于 Object.getPrototypeOf()

class MyClass{ }
const instance = new MyClass();

console.log(Reflect.getPrototypeOf(instance) === MyClass.prototype); // 输出:true
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. Reflect 认识
  2. 2. Reflect 特点
  3. 3. Reflect 常用方法
    1. 3.1. Reflect.get()
    2. 3.2. Reflect.set()
    3. 3.3. Reflect.defineProperty()
    4. 3.4. Reflect.deleteProperty()
    5. 3.5. Reflect.apply()
    6. 3.6. Reflect.construct()
    7. 3.7. Reflect.has()
    8. 3.8. Reflect.ownKeys()
    9. 3.9. Reflect.preventExtensions()
    10. 3.10. Reflect.isExtensible()
    11. 3.11. Reflect.getPrototypeOf()