阿里云主机折上折
  • 微信号
Current Site:Index > The methods of the Reflect object translate this sentence into English.

The methods of the Reflect object translate this sentence into English.

Author:Chuan Chen 阅读数:9292人阅读 分类: JavaScript

Reflect is a new built-in object introduced in ECMAScript 6 that provides methods to intercept JavaScript operations. These methods correspond one-to-one with the methods of the Proxy object. They standardize object operations, with some methods replacing the older Object-based approaches.

Reflect.apply()

Calls a function with a specified this value and an array of arguments, equivalent to Function.prototype.apply() but more intuitive:

function sum(a, b) {
  return a + b;
}

// Traditional way
sum.apply(null, [1, 2]); // 3

// Reflect way
Reflect.apply(sum, null, [1, 2]); // 3

When dynamically invoking functions, Reflect.apply() provides clearer semantics. It is particularly useful when working with Proxy:

const proxy = new Proxy(sum, {
  apply(target, thisArg, args) {
    console.log(`Calling ${target.name} function`);
    return Reflect.apply(target, thisArg, args);
  }
});

proxy(1, 2); // Logs output and returns 3

Reflect.construct()

Similar to the new operator for creating instances but supports initialization via an array of arguments:

class Person {
  constructor(name) {
    this.name = name;
  }
}

// Traditional way
new Person('Zhang San');

// Reflect way
Reflect.construct(Person, ['Zhang San']);

This method is especially useful for dynamically creating instances, such as in pluggable class factories:

function createInstance(Constructor, ...args) {
  return Reflect.construct(Constructor, args);
}

const person = createInstance(Person, 'Li Si');

Reflect.get()

Retrieves the value of an object property and supports a receiver parameter to change this binding:

const obj = { x: 1, y: 2 };
Reflect.get(obj, 'x'); // 1

// Using receiver to change `this`
const receiver = { x: 10 };
Reflect.get(obj, 'x', receiver); // Still returns 1, but `this` points to `receiver` during the operation

Works seamlessly with Proxy's get trap:

const proxy = new Proxy(obj, {
  get(target, property, receiver) {
    console.log(`Accessing property ${property}`);
    return Reflect.get(target, property, receiver);
  }
});

proxy.x; // Logs output and returns 1

Reflect.set()

Sets the value of an object property and returns a boolean indicating success:

const obj = {};
Reflect.set(obj, 'x', 1); // true
obj.x; // 1

// Fails for read-only properties
const frozen = Object.freeze({ x: 1 });
Reflect.set(frozen, 'x', 2); // false

The receiver parameter can change this in setters:

const obj = {
  _x: 0,
  set x(value) {
    this._x = value;
  }
};

const receiver = {};
Reflect.set(obj, 'x', 1, receiver);
receiver._x; // 1
obj._x; // 0

Reflect.has()

Checks if an object contains a property, replacing the in operator:

const obj = { x: 1 };
'x' in obj; // true
Reflect.has(obj, 'x'); // true

// Checks prototype chain properties
Reflect.has(obj, 'toString'); // true

Can intercept in operations in Proxy:

const proxy = new Proxy(obj, {
  has(target, property) {
    console.log(`Checking property ${property}`);
    return Reflect.has(target, property);
  }
});

'x' in proxy; // Logs output and returns true

Reflect.deleteProperty()

Deletes an object property, replacing the delete operator:

const obj = { x: 1, y: 2 };
delete obj.x; // true
Reflect.deleteProperty(obj, 'y'); // true
obj; // {}

// Fails for non-configurable properties
const frozen = Object.freeze({ x: 1 });
Reflect.deleteProperty(frozen, 'x'); // false

Reflect.getOwnPropertyDescriptor()

Retrieves an object property's descriptor, safer than Object.getOwnPropertyDescriptor():

const obj = { x: 1 };
Reflect.getOwnPropertyDescriptor(obj, 'x');
// { value: 1, writable: true, enumerable: true, configurable: true }

// Returns `undefined` for non-existent properties
Reflect.getOwnPropertyDescriptor(obj, 'y'); // undefined

Reflect.defineProperty()

Defines or modifies an object property, replacing Object.defineProperty():

const obj = {};
Reflect.defineProperty(obj, 'x', {
  value: 1,
  writable: true
}); // true

// Returns `false` on failure instead of throwing an error
Reflect.defineProperty(Object.freeze({}), 'x', { value: 1 }); // false

Reflect.ownKeys()

Retrieves all own property keys (including Symbol and non-enumerable properties):

const obj = {
  [Symbol('id')]: 123,
  x: 1,
  y: 2
};

Object.defineProperty(obj, 'hidden', {
  value: 'secret',
  enumerable: false
});

Reflect.ownKeys(obj); // ['x', 'y', 'hidden', Symbol(id)]

Reflect.getPrototypeOf()

Retrieves an object's prototype, replacing Object.getPrototypeOf():

const obj = {};
Reflect.getPrototypeOf(obj) === Object.prototype; // true

// Works with Proxy
const proxy = new Proxy(obj, {
  getPrototypeOf(target) {
    console.log('Getting prototype');
    return Reflect.getPrototypeOf(target);
  }
});

Object.getPrototypeOf(proxy); // Logs output and returns Object.prototype

Reflect.setPrototypeOf()

Sets an object's prototype, replacing Object.setPrototypeOf():

const obj = {};
const proto = { x: 1 };
Reflect.setPrototypeOf(obj, proto); // true
obj.x; // 1

// Fails for non-extensible objects
Reflect.setPrototypeOf(Object.freeze({}), proto); // false

Reflect.isExtensible()

Checks if an object is extensible, replacing Object.isExtensible():

const obj = {};
Reflect.isExtensible(obj); // true

Object.freeze(obj);
Reflect.isExtensible(obj); // false

Reflect.preventExtensions()

Makes an object non-extensible, replacing Object.preventExtensions():

const obj = {};
Reflect.preventExtensions(obj); // true
Reflect.isExtensible(obj); // false

// Returns `true` for already non-extensible objects
Reflect.preventExtensions(Object.freeze({})); // true

Using Reflect with Proxy

Reflect methods were designed to correspond one-to-one with Proxy handler methods, enabling transparent proxying:

const logger = {
  get(target, property, receiver) {
    console.log(`GET ${property}`);
    return Reflect.get(target, property, receiver);
  },
  set(target, property, value, receiver) {
    console.log(`SET ${property}=${value}`);
    return Reflect.set(target, property, value, receiver);
  },
  // Other trap methods...
};

const data = { x: 1 };
const proxy = new Proxy(data, logger);

proxy.x; // Logs "GET x" and returns 1
proxy.y = 2; // Logs "SET y=2"

Differences from Object Methods

Although Reflect methods are similar to Object methods, there are key differences:

  1. Return value handling differs:
Object.defineProperty(obj, 'x', { value: 1 }); // Returns obj
Reflect.defineProperty(obj, 'x', { value: 1 }); // Returns boolean
  1. Error handling differs:
// Object methods throw errors on failure
Object.defineProperty(Object.freeze({}), 'x', { value: 1 }); // Throws TypeError

// Reflect methods return false
Reflect.defineProperty(Object.freeze({}), 'x', { value: 1 }); // false
  1. More consistent parameter handling:
// Object.getPrototypeOf(1) throws an error
Reflect.getPrototypeOf(1); // Returns Number.prototype

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.