当前位置:首页 > 安卓源码 > 技术博客 >

JavaScript Reflect API提供给开发人员的不同方法的演练

时间:2020-08-09 22:02 来源:互联网 作者:源码搜藏 浏览: 收藏 挑错 推荐 打印

在本文中,我们将探索JavaScript的Reflect API,并了解其不同方法的用法。此外,大多数示例都是为程序员提供的,他们在JavaScript语言方面有点中级,可以轻松地掌握概念。 介绍 当涉及计算机编程环境中的反射时,其定义为在运行时检查,自省和修改其自身的结
在本文中,我们将探索JavaScript的Reflect API,并了解其不同方法的用法。此外,大多数示例都是为程序员提供的,他们在JavaScript语言方面有点中级,可以轻松地掌握概念。

介绍

当涉及计算机编程环境中的反射时,其定义为在运行时检查,自省和修改其自身的结构和行为的能力(定义来自Wikipedia页面)。此外,它对于元编程是众所周知的。因此,您可以在运行时操作对象的变量,属性和方法。使用JavaScript语言,可以进行反思。但是,在过去,它的限制和反射方法并不直接适用于许多开发人员。但是,如今,情况已不再如此,该Reflect对象提供了更好的有意义的方法来帮助开发人员轻松进行反射编程。因此,我们将要解决并观察Reflect物体可以为我们提供什么,特别是它的static方法。好,那就开始吧。

什么是Reflect API?

以下是有关ReflectAPI的注意事项。

  • 它使用的Reflect是全局和静态对象,因此,您无法创建该对象的实例。同样,其所有方法均为static。

  • 它提供了运行时级别的检查和操作对象属性的功能,也称为元编程。此外,在ES6之前,JavaScript语言确实提供了对象反射API,但是它们并不是真正组织起来的,并且在失败时会引发异常。因此,今天,ReflectAPI在Reflect对象的帮助下改善了我们进行元/反射编程的方式。

反映对象提供的各种方法是什么?

Reflect.apply(目标,接收器,参数)

此方法使用指定的参数调用要调用的目标函数。换句话说,如果您要调用某个函数而不真正直接调用它,而是要使用此方法来调用目标函数。

此方法采用三个参数:

  • target -代表目标函数的第一个参数
  • receiver-第二个参数,表示this目标函数内部的值
  • args -第三个参数,表示数组对象中目标函数的参数

请参阅以下示例:

隐藏   复制代码
/** start of Reflect.apply() */

//let's define a function
function getSum(num1, num2) {

    return `${this.value}${num1 + num2}`;
}

//let's try to invoke the function using Reflect.apply()
const returnedValueOfFunc = Reflect.apply(getSum, { value:'Sum of 1 and 2 is '}, [ 1, 2]);

console.log(returnedValueOfFunc); //output: Sum of 1 and 2 is 3

/** end of Reflect.apply() */

Reflect.construct(target,args,prototype)

此方法用于调用构造函数。换句话说,此方法返回由目标构造函数创建的新实例。

此方法采用三个参数:

  • target -代表目标构造函数的第一个参数
  • args-第二个参数,表示目标构造函数的参数。此参数是可选的。
  • prototype-第三个参数,表示另一个构造函数,其原型将用作目标构造函数的原型。此参数是可选的。

请参阅以下示例:

隐藏   复制代码
/** start of Reflect.constructor */

//let's define a constructor function
function Customer(title,firstName, lastName) {
    
    this.title = title;
    this.firstName = firstName;
    this.lastName = lastName;

    this.showFullName = function () {
        
        return `${this.title}. ${lastName}, ${firstName} is from the ${this.country}`;
    }
}
//let's define another constructor set the prototype to add a new property.
function Employee() { }
Employee.prototype.country = 'Philippines';

const myCustomer = Reflect.construct(Customer, ['Dr','Jin Vincent', 'Necesario'],Employee);

console.log(myCustomer.showFullName()); //output: Dr. Necesario, 
                                        //Jin Vincent is from the Philippines

/** end of Reflect.constructor */

Reflect.defineProperty(目标,名称,描述)

可能您会猜测此方法用于定义对象的新属性或更新现有属性。如果这就是您的想法,那么您猜对了。

此方法采用三个参数:

  • target -第一个参数是用于定义或修改属性的对象
  • name -第二个参数是要定义或修改的属性的名称
  • desc -第三个参数是定义或修改的属性的描述符

而且,它具有的等效方法是Object.defineProperty()。现在我们已经意识到了这一点,您可能会想:“有什么区别?” ,我将在下一部分中回答。之后,我们将进入代码示例。

Reflect.defineProperty()和Object.defineProperty()有什么区别?

基本上,这些方法执行相同的操作,但主要区别在于这些方法返回的值。现在的区别是该Reflect.defineProperty()方法返回一个Boolean,而该Object.defineProperty()返回了修改后的对象。此外,如果方法Object.defineProperty()失败,则当Reflect.defineProperty()方法返回false结果时它将引发异常。

数据属性和访问器属性是什么?

在进入代码示例之前,让我们尝试了解该方法的第三个参数Reflect.defineProperty()。在任何面向对象的语言中,每个对象属性都是数据属性或访问器属性。

基本上,数据属性的值可以是可读或不可读或可写的,而访问器属性具有一对用于设置和检索该属性值的getter-setter函数。

使用Reflect.define()并定义数据属性描述符

在深入研究代码之前,我们首先来看一下描述符对象的属性:

  • value-这是与属性关联的值。这是undefined默认。
  • writable-如果将其设置为true,则可以使用赋值运算符来更改属性值。这是false默认。
  • configurable-如果将其设置为true,则可以更改属性属性。这是false默认。
  • enumerable-如果将其设置为true,则该属性将显示在for ...in循环和Object.keys()方法中。这是false默认。

让我们来看一个代码示例,用于将属性定义为可写,可配置和可枚举。

隐藏   收缩 JavaScript Reflect API提供给开发人员的不同方法的演练   复制代码
/** start of Reflect.defineProperty */

const book = {};

//let's define a property that is writable, configurable and enumerable 

Reflect.defineProperty(book, "title", {
    value: "JavaScript For Kids",
    writable: true, 
    configurable: true, 
    enumerable:true
});

//let's check the book object
console.log(book); //output: {title: "JavaScript For Kids"}

//let's check the title of the book 
console.log(book.title); //output: JavaScript For Kids

//let's change the value of the Book property, 
//this is possible because writable is set to true
book.title = "Beginning Node.js";

//let's check the title of the book 
console.log(book.title); //output: Beginning Node.js

//let's check if we can enumerate the title property

for (const key in book) {
    console.log(key); //output: title
}

/** end of Reflect.defineProperty */

将属性定义为不可写,不可配置和不可枚举的另一个示例。

隐藏   收缩 JavaScript Reflect API提供给开发人员的不同方法的演练   复制代码
/** start of Reflect.defineProperty */

const laptop = {};

//let's define a property that isn't writable, configurable and enumerable 

Reflect.defineProperty(laptop, "brand", {
    value: "IBM",
    writable: false,
    configurable: false,
    enumerable: false
});

//let's check the laptop object
console.log(laptop); //output: {brand: "IBM"}

//let's check the brand of the laptop
console.log(laptop.brand); //output: IBM

//let's change the value of the brand property, 
//this is not possible because writable is set to false
laptop.brand = "DELL";

//let's check the brand of the laptop
console.log(laptop.brand); //output: IBM

//let's check if we can enumerate the brand property
for (const key in laptop) {
    console.log(key); //output: n/a
}

/** end of Reflect.defineProperty */

使用Reflect.define()并定义访问器属性描述符

同样,在深入研究代码示例之前,让我们看一下访问器属性描述符属性:

  • get -返回属性值的函数
  • set -设置属性值的函数
  • configurable-如果将其设置为true,则可以更改属性描述符。这是false默认
  • enumerable-如果将其设置为true,则该属性将在for..in循环和Object.keys()方法中显示。这是false默认。

让我们看下面的代码示例:

隐藏   复制代码
/** start of accessor property */
/** start of Reflect.defineProperty */

const laundryShop = {
    __defaultName__: "Queens Care Laundry Shop"
}

Reflect.defineProperty(laundryShop, "businessName", {
    get: function () {
        return this.__defaultName__;
    },
    set: function (value){
        this.__defaultName__ = value;
    },
    configurable: true,
    enumerable: true
});

console.log(laundryShop); //output: {__defaultName__: "Queens Care Laundry Shop"}
console.log(laundryShop.businessName); //output: Queens Care Laundry Shop
laundryShop.businessName = "Laundry Shop";
console.log(laundryShop.businessName); //output: Laundry Shop

/** end of accessor property */
/** end of Reflect.defineProperty */    

Reflect.deleteProperty(target,name)

方法本身的名称描述了它的作用。它基本上删除了对象的属性。

此方法有两个参数:

  • target -第一个参数是目标/参考对象
  • name -第二个参数是要删除的属性的名称

让我们看下面的代码示例:

隐藏   复制代码
// /** start of Reflect.deleteProperty */

let car = {
    model: "Toyota Hilux",
    yearModel: 2020
};

//let us see the object before removing the model property.
console.log(car);  //output: {model: "Toyota Hilux", yearModel: 2020}

Reflect.deleteProperty(car, "model");

//let use the object after the removal of the model property.
console.log(car); //output: { yearModel: 2020 }

/** end of Reflect.deleteProperty */

Reflect.set(目标,名称,值)

此方法用于设置对象属性的值。

此方法采用三个参数:

  • target -第一个参数是目标/参考对象
  • name -第二个参数是对象属性的名称
  • value -第三个参数是属性的值

让我们看下面的代码示例:

隐藏   复制代码
/** Start of Reflect.set */

const computer2 = {
     processor: "Intel",
     brand: "Dell",
     operatingSystem: "windows 7"
};

console.log(computer2);
//output: {processor: "Intel", brand: "Dell", operatingSystem: "windows 7"}

Reflect.set(computer2, "processor", "AMD");

console.log(computer2);
//output: {processor: "AMD", brand: "Dell", operatingSystem: "windows 7"}

// /** end of Reflect.set */  

Reflect.get(目标,名称,接收者)

显然,此方法与完全相反Reflect.set()。此方法用于检索对象属性的值。

此方法采用三个参数:

  • target -第一个参数是目标/参考对象
  • name -第二个自变量对象的属性名称
  • receiver -第三个参数是接收者

让我们看下面的代码示例:

隐藏   复制代码
/** Start of Reflect.get */

var computer1 = {
    processor: "Intel",
    brand: "Dell",
    operatingSystem: "windows 7"
};

console.log(computer1);
Reflect.get(computer1, "processor");
console.log(computer1.processor);

/** end of Reflect.get */

注意:如果该属性是访问器属性,那么我们可以提供可选的第三个参数,它将是函数this内部的get值。

让我们看下面的代码示例:

隐藏   收缩 JavaScript Reflect API提供给开发人员的不同方法的演练   复制代码
/** start of Reflect.get with 3rd argument */

const dinoComputer = {
    processor: "Intel",
    brand: "Dell",
    operatingSystem: "windows 7"
};

Reflect.defineProperty(dinoComputer, "computerDetails", {
    get: function() { 
        return new String().concat(`*********Computer Details********\r\n`,
                                   `****Processor: ${this.processor}***********\r\n`,
                                   `****Brand: ${this.brand}*****************\r\n`,
                                   `****Operating System: ${this.operatingSystem}*\r\n`);
    }
});

console.log(dinoComputer);

let oldComputer = Reflect.get(dinoComputer, "computerDetails", 
{ processor: "AMD K62", 
  brand: "Clone", 
  operatingSystem: "Windows XP" });

console.log(oldComputer);

/** end of Reflect.get with 3rd argument */

输出:

JavaScript Reflect API提供给开发人员的不同方法的演练

Reflect.getOwnPropertyDescriptor(目标名称)

此方法用于检索对象属性的描述符。Kinda易于实现。

此方法有两个参数:

  • target -第一个参数是目标/参考对象
  • name -第二个参数是对象的属性名称

让我们看下面的代码示例:

隐藏   复制代码
/** start of Reflect.getOwnPropertyDescriptor */

const myDog = {
    yourPet: true,
    name: "Bruno"
}

const descriptor = Reflect.getOwnPropertyDescriptor(myDog, "name");

console.log(descriptor.value); //output: Bruno
console.log(descriptor.writable); //output: true
console.log(descriptor.enumerable);//output: true
console.log(descriptor.configurable); //output: true

/** end of Reflect.getOwnPropertyDescriptor */

Reflect.getPrototypeOf(目标)

此方法用于检索对象的内部原型,即对象的内部属性的值。此方法只有一个参数,即目标/引用对象。

需要注意的一点是,它与Object.getPrototypeOf()方法相同。

让我们看下面的代码示例:

隐藏   复制代码
/** start of  Reflect.getPrototypeOf*/

const product = {
    __proto__: {
        category: {
            id: "1",
            name: "Electronics",
            description: "Electronic devices"
        }
    }
}

const myCategoryResult = Reflect.getPrototypeOf(product);

console.log(myCategoryResult.category);
//output: { id: "1", name: "Electronics", description: "Electronic devices" }

/** end of Reflect.getPrototypeOf */

Reflect.setPrototypeOf(target,newProto)

此方法用于设置对象的内部prototype(__proto__)属性值。

此方法有两个参数:

  • target -第一个参数是目标/参考对象
  • newProto -第二个参数是对象的__proto__属性值

让我们看下面的代码示例:

隐藏   复制代码
/**start of Reflect.setPrototypeOf */

const anime = {
    popularAnimeShow: "Voltes V"
}

Reflect.setPrototypeOf(anime, {
    fullName: "Super Electromagnetic Machine Voltes V"
});

console.log(anime.__proto__.fullName); 
//output: Super Electromagnetic Machine Voltes V

/** end of Reflect.setPrototypeOf */    

Reflect.has(目标,名称)

此方法用于检查对象中是否存在属性。true如果属性存在,则返回,否则返回false。

此方法有两个参数:

  • target -第一个参数是目标/参考对象
  • name -第二个参数是对象的属性名称

让我们看下面的代码示例:

隐藏   复制代码
/** start of Reflect.has */

const band = {
    name: "EHeads",
    songs: ['Ang Huling El Bimbo', 'With A Smile']
}

console.log(Reflect.has(band, "name")); //output: true
console.log(Reflect.has(band, "songs")); //output: true
console.log(Reflect.has(band, "producer")); //output: false

/** end of Reflect.has */

Reflect.isExtensible(目标)

此方法用于检查对象是否可扩展。换句话说,如果我们可以向对象添加新属性。此方法只有一个参数,即目标/引用对象。

让我们看下面的代码示例:

隐藏   复制代码
/** start of Reflect.isExtensible */

const problem = {
    problemIs: "I'm in love with a college girl"
}

console.log(Reflect.isExtensible(problem)); //output: true

Reflect.preventExtensions(problem);         //let's prevent this object to be extended.
//This is the same as Object.preventExtensions(problem);

console.log(Reflect.isExtensible(problem)); //output: false

/** end of Reflect.isExtensible */

/** start of Reflect.preventExtensions */

要知道,我们还可以通过以下方法将对象标记为不可扩展:

  • Object.preventExtension()
  • Object.freeze()
  • Object.seal()

Reflect.preventExtensions(目标)

此方法用于将对象标记为不可扩展。它返回一个Boolean,指示是否成功。此方法只有一个参数,即目标/引用对象。

让我们看下面的代码示例:

隐藏   复制代码
/** start of Reflect.preventExtensions */

const song = {
    title: "Magasin",
    band: "EHeads"
}

console.log(Reflect.isExtensible(song)); //output: true

Reflect.preventExtensions(song);
//This is the same as Object.preventExtensions(song);

console.log(Reflect.isExtensible(song)); //output: false

/** end of Reflect.preventExtensions */

Reflect.ownKeys(目标)

此方法返回对象的键属性的数组。但是,它忽略了继承的属性(__proto__)。此方法只有一个参数,即目标/引用对象。

让我们看下面的代码示例:

隐藏   收缩 JavaScript Reflect API提供给开发人员的不同方法的演练   复制代码
/** start of Reflect.ownKeys */

const currency = {
    name: "USD",
    symbol: "$",
    globalCurrency: true,
    __proto__: {
        country: "USA"
    }
}

const keys = Reflect.ownKeys(currency);

console.log(keys); //output: ["name", "symbol", "globalCurrency"]
console.log(keys.length);//output: 3

/** Output:
 *  name
    symbol
    globalCurrency
 */

keys.forEach(element => {
    console.log(element);
});

/** end of Reflect.ownKeys */

摘要

在本文中,我们学习了使用该Reflect对象的JavaScript反射API 。不仅如此,我们还解决了Reflect对象必须提供的大多数方法,并且已经了解了如何在特定的场景中以不同的方式实现它。总体而言,这篇文章介绍了JavaScript ReflectAPI。


JavaScript Reflect API提供给开发人员的不同方法的演练 转载https://www.codesocang.com/appboke/48989.html

技术博客阅读排行

最新文章