ECMAScript6 Proxy和Reflect 对象操作拦截以及自定义

目录

  • 简介
  • Proxy
    • 语法
    • 参数
      • handler 对象方法合集
      • handler.apply()
      • handler.construct()
      • handler.defineProperty()
      • handler.deleteProperty()
      • handler.get()
      • handler.getOwnPropertyDescriptor()
      • handler.getPrototypeOf()
      • handler.has()
      • handler.isExtensible()
      • handler.ownKeys()
      • handler.preventExtensions()
      • handler.set()
      • handler.setPrototypeOf()
    • 方法
  • Reflect
    • 描述
    • 静态方法
      • Reflect.apply()
      • Reflect.construct()
      • Reflect.defineProperty()
      • Reflect.deleteProperty()
      • Reflect.get()
      • Reflect.getOwnPropertyDescriptor()
      • Reflect.getPrototypeOf()
      • Reflect.has()
      • Reflect.isExtensible()
      • Reflect.ownKeys()
      • Reflect.preventExtensions()
      • Reflect.set()
      • Reflect.setPrototypeOf()

简介

Proxy:用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等),用代理实例不影响原对象操作,实现代理拦截需要在代理对象上操作;
Reflect:一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handlers 的方法相同。Reflect不是一个函数对象,因此它是不可构造的。

注意:通过对目标对象创建代理,并在代理中进行对象操作进行拦截和自定义,可理解为达到了一种“元编程”(meta programming)的效果。

术语定义:
handler:包含捕捉器(trap)的占位符对象,可译为处理器对象。
traps:提供属性访问的方法。这类似于操作系统中捕获器的概念。
target:被 Proxy 代理虚拟化的对象。它常被作为代理的存储后端。根据目标验证关于对象不可扩展性或不可配置属性的不变量(保持不变的语义)。

简单举例:当对象中不存在属性名时,通过代理访问该属性,默认返回值为 nothing。设置属性被拦截后在里面写入属性设置也可以设置属性。

const handler = {
    get: function(target, property) {
        return property in target ? target[property] : 'nothing';
    },
    set: function(target, property, value, receiver) {
    	// target[property] = value;
    	Reflect.set(target, property, value);
    	console.log('Successfully set '+ property + ' to value ' + value + ".")
		return true;
  	}
};

const p = new Proxy({}, handler);
p.a = 1; 	//Successfully set a to value 1.

console.log(p.a);      // 1
console.log('b' in p, p.b); // false, 'nothing'

Proxy

语法

const p = new Proxy(target, handler)
语义:创建一个指向 target 对象的代理p,并传入执行各种操作时代理 p 的行为集合 handler。

参数

名称 定义
target 要使用 Proxy 的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)
handler 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为

handler 对象的方法
handler 对象是一个容纳一批特定属性的占位符对象。它包含有 Proxy 的各个捕获器(trap)。所有的捕捉器是可选的。如果没有定义某个捕捉器,那么就会保留源对象的默认行为。

handler 对象方法合集

名称 定义
handler.apply() 函数调用操作的捕捉器
handler.construct() new 操作符的捕捉器
handler.defineProperty() Object.defineProperty 方法的捕捉器
handler.deleteProperty() delete 操作符的捕捉器
handler.get() 属性读取操作的捕捉器
handler.getOwnPropertyDescriptor() Object.getOwnPropertyDescriptor 方法的捕捉器
handler.getPrototypeOf() Object.getPrototypeOf 方法的捕捉器
handler.has() in 操作符的捕捉器
handler.isExtensible() Object.isExtensible 方法的捕捉器
handler.ownKeys() Object.getOwnPropertyNames 方法和Object.getOwnPropertySymbols 方法的捕捉器
handler.preventExtensions() Object.preventExtensions 方法的捕捉器
handler.set() 属性设置操作的捕捉器
handler.setPrototypeOf() Object.setPrototypeOf 方法的捕捉器

一些不标准的捕捉器已经被废弃并且移除了,链接。

handler.apply()

定义:handler.apply() 方法用于拦截函数的调用,该方法会拦截目标对象的以下操作:proxy(...args)Function.prototype.apply()Function.prototype.call()Reflect.apply()
语法

var p = new Proxy(target, {
  apply: function(target, thisArg, argumentsList) {
  }
});

参数:参数传递给 apply 方法,this 上下文绑定在 handler 对象上。
target目标对象(函数)、thisArg被调用时的上下文对象、argumentsList被调用时的参数数组。
返回值:任意值;
异常target 必须是可被调用的一个函数对象,否则代理抛出错误 TypeError。
示例:演示捕获函数的调用

var p = new Proxy(function() {}, {
  apply: function(target, thisArg, argumentsList) {
    console.log('called: ' + argumentsList.join(', '));
    return argumentsList[0] + argumentsList[1] + argumentsList[2];
  }
});
console.log(p(1, 2, 3)); // "called: 1, 2, 3"
                         // 6

handler.construct()

定义:handler.construct() 方法用于拦截 new 操作符。为了使 new 操作符在生成的 Proxy 对象上生效,用于初始化代理的目标对象自身必须具有 [[Construct]] 内部方法(即 new target 必须是有效的)。该拦截器可以拦截以下操作:new proxy(...args)Reflect.construct()
语法

var p = new Proxy(target, {
  construct: function(target, argumentsList, newTarget) {
  }
});

参数:参数将会传递给 construct 方法,this 绑定在 handler 上。
target目标对象(函数)、argumentsListconstructor 的参数列表、newTarget最初被调用的构造函数,如语法示例中的p。
返回值:construct 方法必须返回一个对象;
异常:未返回一个对象则抛出错误 TypeError。
示例:演示拦截 new 操作

var p = new Proxy(function() {}, {
  construct: function(target, argumentsList, newTarget) {
    console.log('called: ' + argumentsList.join(', '));
    // 如果此处return非对象则后面new操作异常,如return 1;
    return { value: argumentsList[0] * 10 }; 
  }
});
console.log(new p(1).value); 
// "called: 1"
// 10

handler.defineProperty()

定义:handler.defineProperty() 用于拦截对对象的 Object.defineProperty() 操作。该方法会拦截目标对象的以下操作:Object.defineProperty()Reflect.defineProperty()
语法

var p = new Proxy(target, {
  defineProperty: function(target, property, descriptor) {
  }
});

参数:参数将会被传递给 defineProperty 方法。this 绑定在 handler 对象上。
target目标对象(函数)、property待检索其描述的属性名、descriptor待定义或修改的属性的描述符。
返回值:defineProperty 方法必须以一个 Boolean 返回,表示定义该属性的操作成功与否。
异常:不符合以下约束将抛出异常

  • 如果目标对象不可扩展, 将不能添加属性。
  • 不能添加或者修改一个属性为不可配置的,如果它不作为一个目标对象的不可配置的属性存在的话。
  • 如果目标对象存在一个对应的可配置属性,这个属性可能不会是不可配置的。
  • 如果一个属性在目标对象中存在对应的属性,那么Object.defineProperty(target, prop, descriptor) 将不会抛出异常。
  • 在严格模式下,false作为 handler.defineProperty 方法的返回值的话将会抛出 TypeError 异常

示例:演示如何拦截对目标对象的 Object.defineProperty() 操作。

var p = new Proxy({}, {
  defineProperty: function(target, prop, descriptor) {
    console.log('called: ' + prop);
    return true;
  }
});
var desc = { configurable: true, enumerable: true, value: 10 };
Object.defineProperty(p, 'a', desc); // "called: a"

注意:当调用 Object.defineProperty() 或者 Reflect.defineProperty(),传递给 defineProperty 的 descriptor 有一个限制 - 只有以下属性才有用,非标准的属性将会被无视:enumerableconfigurablewritablevaluegetset

var p = new Proxy({}, {
  defineProperty(target, prop, descriptor) {
    console.log(descriptor);
    return Reflect.defineProperty(target, prop, descriptor);
  }
});
Object.defineProperty(p, 'name', {
  value: 'proxy',
  type: 'custom'
});  // { value: 'proxy' }

handler.deleteProperty()

定义:handler.deleteProperty() 方法可以拦截 delete 操作。该方法会拦截以下操作:删除属性:delete proxy[foo]delete proxy.fooReflect.deleteProperty()
语法

var p = new Proxy(target, {
  deleteProperty: function(target, property) {
  }
});

参数:deleteProperty 方法将会接受以下参数。this 被绑定在 handler 上。
target目标对象(函数)、property待删除的属性名。
返回值:deleteProperty 必须返回一个 Boolean 类型的值,表示了该属性是否被成功删除。
异常:如果目标对象的属性是不可配置的,那么该属性不能被删除。尝试删除则抛出错误 TypeError。
示例:演示对 delete 操作的拦截

var p = new Proxy({}, {
  deleteProperty: function(target, prop) {
    console.log('called: ' + prop);
    return true;
  }
});
delete p.a; // "called: a"

handler.get()

定义:handler.get() 方法用于拦截对象的读取属性操作。该拦截器可以拦截以下操作:访问属性:proxy[foo]proxy.bar;访问原型链上的属性:Object.create(proxy)[foo]Reflect.get()
语法

var p = new Proxy(target, {
  get: function(target, property, receiver) {
  }
});

参数:参数将传递给 get 方法,this 上下文绑定在handler 对象上。
target目标对象(函数)、property被获取的属性名、receiverProxy 或者继承 Proxy 的对象。
返回值:任何值。
异常:不符合以下约束将抛出异常

  • 如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同。
  • 如果要访问的目标属性没有配置访问方法,即 get 方法是 undefined 的,则返回值必须为 undefined。

示例:演示拦截属性值的读取操作

var p = new Proxy({}, {
  get: function(target, prop, receiver) {
    console.log("called: " + prop);
    return 10;
  }
});
console.log(p.a); 
// "called: a"
// 10

异常

var obj = {};
Object.defineProperty(obj, "a", {
  configurable: false,
  enumerable: false,
  value: 10,
  writable: false
});
var p = new Proxy(obj, {
  get: function(target, prop) {
    return 20;
  }
});
p.a; //会抛出 TypeError

handler.getOwnPropertyDescriptor()

定义:handler.getOwnPropertyDescriptor() 方法是 Object.getOwnPropertyDescriptor() 的钩子。该拦截器可以拦截以下操作:Object.getOwnPropertyDescriptor()Reflect.getOwnPropertyDescriptor()
语法

var p = new Proxy(target, {
  getOwnPropertyDescriptor: function(target, prop) {
  }
});

参数:参数会被传入 getOwnPropertyDescriptor 方法中。这是绑定到 handler 上。
target目标对象(函数)、prop返回属性名称的描述。
返回值:getOwnPropertyDescriptor 方法必须返回一个 object 或 undefined。
异常:不符合以下约束将抛出异常

  • getOwnPropertyDescriptor 必须返回一个 object 或 undefined。
  • 如果属性作为目标对象的不可配置的属性存在,则该属性无法报告为不存在。
  • 如果属性作为目标对象的属性存在,并且目标对象不可扩展,则该属性无法报告为不存在。
  • 如果属性不存在作为目标对象的属性,并且目标对象不可扩展,则不能将其报告为存在。
  • 属性不能被报告为不可配置,如果它不作为目标对象的自身属性存在,或者作为目标对象的可配置的属性存在。
  • Object.getOwnPropertyDescriptor(target)的结果可以使用Object.defineProperty应用于目标对象,也不会抛出异常。

示例

var p = new Proxy({ a: 20}, {
  getOwnPropertyDescriptor: function(target, prop) {
    console.log('called: ' + prop);
    return { configurable: true, enumerable: true, value: 10 };
  }
});
console.log(Object.getOwnPropertyDescriptor(p, 'a').value); 
// "called: a"
// 10

异常

var obj = { a: 10 };
Object.preventExtensions(obj);
var p = new Proxy(obj, {
  getOwnPropertyDescriptor: function(target, prop) {
    return undefined;
  }
});
Object.getOwnPropertyDescriptor(p, 'a'); // TypeError is thrown

handler.getPrototypeOf()

定义:handler.getPrototypeOf() 是一个代理(Proxy)方法,当读取代理对象的原型时,该方法就会被调用。该拦截器可以拦截以下操作:Object.getPrototypeOf()Reflect.getPrototypeOf()__proto__Object.prototype.isPrototypeOf()instanceof
语法

const p = new Proxy(obj, {
  getPrototypeOf(target) {
  ...
  }
});

参数:当 getPrototypeOf 方法被调用时,this 指向的是它所属的处理器对象。
target被代理的目标对象。
返回值:getPrototypeOf 方法的返回值必须是一个对象或者 null。
异常:不符合以下约束将抛出异常

  • getPrototypeOf() 方法返回的不是对象也不是 null。
  • 目标对象是不可扩展的,且 getPrototypeOf()方法返回的原型不是目标对象本身的原型。

示例

var obj = {};
var proto = {};
var handler = {
    getPrototypeOf(target) {
        console.log(target === obj);   // true
        console.log(this === handler); // true
        return proto;
    }
};
var p = new Proxy(obj, handler);
console.log(Object.getPrototypeOf(p) === proto);    // true

5 种触发 getPrototypeOf 代理方法的方式

var obj = {};
var p = new Proxy(obj, {
    getPrototypeOf(target) {
        return Array.prototype;
    }
});
console.log(
    Object.getPrototypeOf(p) === Array.prototype,  // true
    Reflect.getPrototypeOf(p) === Array.prototype, // true
    p.__proto__ === Array.prototype,               // true
    Array.prototype.isPrototypeOf(p),              // true
    p instanceof Array                             // true
);

异常

var obj = {};
var p = new Proxy(obj, {
    getPrototypeOf(target) {
        return "foo";
    }
});
Object.getPrototypeOf(p); // TypeError: "foo" is not an object or null
var obj = Object.preventExtensions({});
var p = new Proxy(obj, {
    getPrototypeOf(target) {
        return {};
    }
});
Object.getPrototypeOf(p); // TypeError: expected same prototype value

handler.has()

定义:handler.has() 方法是针对 in 操作符的代理方法。该拦截器可以拦截以下操作:属性查询:foo in proxy;继承属性查询:foo in Object.create(proxy);with 检查: with(proxy) { (foo); }Reflect.has()
语法

var p = new Proxy(target, {
  construct: function(target, argumentsList, newTarget) {
  }
});

参数:参数将会传递给 construct 方法,this 绑定在 handler 上。
target目标对象、prop需要检查是否存在的属性。
返回值:has 方法返回一个 boolean 属性的值。
异常:不符合以下约束将抛出异常

  • 如果目标对象的某一属性本身不可被配置,则该属性不能够被代理隐藏。
  • 如果目标对象为不可扩展对象,则该对象的属性不能够被代理隐藏。

示例:演示拦截 in 操作符。

var p = new Proxy({}, {
  has: function(target, prop) {
    console.log('called: ' + prop);
    return true;
  }
});
console.log('a' in p); 
// "called: a"
// true

异常

var obj = { a: 10 };
Object.preventExtensions(obj);
var p = new Proxy(obj, {
  has: function(target, prop) {
    return false;
  }
});
'a' in p; // TypeError is thrown

handler.isExtensible()

定义:handler.isExtensible() 方法用于拦截对对象的 Object.isExtensible()。
该拦截器可以拦截以下操作:Object.isExtensible()Reflect.isExtensible()
语法

var p = new Proxy(target, {
  isExtensible: function(target) {
  }
});

参数:参数将会被传递给 isExtensible方法。 this 绑定在 handler 对象上。
target目标对象。
返回值:isExtensible方法必须返回一个 Boolean 值或可转换成 Boolean 的值。
异常:Object.isExtensible(proxy) 必须同 Object.isExtensible(target) 返回相同值,否则抛出错误 TypeError。
示例:演示Object.isExtensible()

var p = new Proxy({}, {
  isExtensible: function(target) {
    console.log('called');
    return true; // 也可以 return 1; 等表示为 true 的值
  }
});
console.log(Object.isExtensible(p));
// "called"
// true

异常

var p = new Proxy({}, {
  isExtensible: function(target) {
    return false; // return 0; return NaN 等都会报错
  }
});
Object.isExtensible(p); // TypeError is thrown

handler.ownKeys()

定义:handler.ownKeys() 方法用于拦截 Reflect.ownKeys()。该拦截器可以拦截以下操作:Object.getOwnPropertyNames()Object.getOwnPropertySymbols()Object.keys()Reflect.ownKeys()
语法

var p = new Proxy(target, {
  ownKeys: function(target) {
  }
});

参数:参数被传递给 ownKeys。this 被绑定在 handler 上。
target目标对象。
返回值:ownKeys 方法必须返回一个可枚举对象。
异常:不满足以下约束将抛出异常

  • ownKeys 的结果必须是一个数组。
  • 数组的元素类型要么是一个 String ,要么是一个 Symbol。
  • 结果列表必须包含目标对象的所有不可配置(non-configurable )、自有(own)属性的 key。
  • 如果目标对象不可扩展,那么结果列表必须包含目标对象的所有自有(own)属性的 key,不能有其它值。

示例:演示拦截 Object.getOwnPropertyNames()

var p = new Proxy({}, {
  ownKeys: function(target) {
    console.log('called');
    return ['a', 'b', 'c'];
  }
});
console.log(Object.getOwnPropertyNames(p)); 
// "called"
// [ 'a', 'b', 'c' ]

handler.preventExtensions()

定义:handler.preventExtensions() 方法用于设置对Object.preventExtensions()的拦截。该拦截器可以拦截以下操作:Object.preventExtensions()Reflect.preventExtensions()
语法

var p = new Proxy(target, {
  preventExtensions: function(target) {
  }
});

参数:参数传递给 preventExtensions 方法。它会绑定到这个 handler。
target所要拦截的目标对象。
返回值:preventExtensions 方法返回一个布尔值。
异常:如果目标对象是可扩展的,那么只能返回 false,否则异常。
示例:演示拦截Object.preventExtensions()

var p = new Proxy({}, {
  preventExtensions: function(target) {
    console.log('called');
    Object.preventExtensions(target);
    return true;
  }
});
console.log(Object.preventExtensions(p)); 
// "called"
// false

异常

var p = new Proxy({}, {
  preventExtensions: function(target) {
    return true;
  }
});
Object.preventExtensions(p); // 抛出类型错误

handler.set()

定义:handler.set() 方法是设置属性值操作的捕获器。该拦截器可以拦截以下操作:指定属性值:proxy[foo] = barproxy.foo = bar;指定继承者的属性值:Object.create(proxy)[foo] = barReflect.set()
语法

const p = new Proxy(target, {
  set: function(target, property, value, receiver) {
  }
});

参数:参数将会传递给 set() 方法。this 绑定在 handler 对象上。
target目标对象、property将被设置的属性名或 Symbol、value新属性值、receiver最初被调用的对象。通常是 proxy 本身,但 handler 的 set 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。

注:如果有一段代码执行 obj.name = “jen”, obj 不是一个 proxy,且自身不含 name 属性,但是它的原型链上有一个 proxy,那么,那个 proxy 的 set() 处理器会被调用,而此时,obj 会作为 receiver 参数传进来。

返回值:set() 方法应当返回一个布尔值,返回 true 代表属性设置成功;在严格模式下,如果 set() 方法返回 false,那么会抛出一个 TypeError 异常。
异常:不满足以下约束将抛出异常

  • 若目标属性是一个不可写及不可配置的数据属性,则不能改变它的值。
  • 如果目标属性没有配置存储方法,即 [[Set]] 属性的是undefined,则不能设置它的值。
  • 在严格模式下,如果 set() 方法返回 false,那么也会抛出一个 TypeError 异常。

示例:演示捕获属性的设置操作

var p = new Proxy({}, {
  set: function(target, prop, value, receiver) {
    target[prop] = value;
    console.log('property set: ' + prop + ' = ' + value);
    return true;
  }
})
console.log('a' in p);  // false
p.a = 10;               // "property set: a = 10"
console.log('a' in p);  // true
console.log(p.a);       // 10

handler.setPrototypeOf()

定义:handler.setPrototypeOf() 方法主要用来拦截 Object.setPrototypeOf()。该拦截器可以拦截以下操作:Object.setPrototypeOf()Reflect.setPrototypeOf()
语法

var p = new Proxy(target, {
  setPrototypeOf: function(target, prototype) {
  }
});

参数:参数将会传递给 setPrototypeOf 方法。
target被拦截目标对象、prototype对象新原型或为null。
返回值:如果成功修改了[[Prototype]], setPrototypeOf 方法返回 true,否则返回 false。
异常:如果 target 不可扩展,原型参数必须与 Object.getPrototypeOf(target) 的值相同,否则异常。
示例:演示拦截 new 操作

var handlerReturnsFalse = {
    setPrototypeOf(target, newProto) {
        return Reflect.setPrototypeOf(target, newProto);
    }
};
var newProto = {a:2},target = {};
var p1 = new Proxy(target, handlerReturnsFalse);
Object.setPrototypeOf(p1, newProto);
//target.__proto__
//{a: 2}

方法

名称 定义
Proxy.revocable() 创建一个可撤销的Proxy对象,这个可撤销的Proxy对象是由Proxy对象和一个revoke撤销方法组成的,其结构为:{“proxy”: proxy, “revoke”: revoke}

注意:{“proxy”: proxy, “revoke”: revoke}中: proxy 表示新生成的代理对象本身,和用一般方式 new Proxy(target, handler) 创建的代理对象没什么不同,只是它可以被撤销掉; revoke 为撤销方法,调用的时候不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象。
Proxy.revocable()示例

var revocable = Proxy.revocable({}, {
  get(target, name) {
    return "[[" + name + "]]";
  }
});
var proxy = revocable.proxy;
proxy.foo;              // "[[foo]]"

revocable.revoke();

console.log(proxy.foo); // 抛出 TypeError
proxy.foo = 1           // 还是 TypeError
delete proxy.foo;       // 又是 TypeError
typeof proxy            // "object",因为 typeof 不属于可代理操作

Reflect

描述

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法 与proxy handlers 的方法相同 。Reflect不是一个函数对象,它是不可构造的,所以不能通过new 运算符对其进行调用,或者将Reflect对象作为一个函数来调用。

静态方法

名称 定义
Reflect.apply(target, thisArgument, argumentsList) 对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似。
Reflect.construct(target, argumentsList[, newTarget]) 对构造函数进行 new 操作,相当于执行 new target(…args)。
Reflect.defineProperty(target, propertyKey, attributes) 和 Object.defineProperty() 类似。如果设置成功就会返回 true
Reflect.deleteProperty(target, propertyKey) 作为函数的delete操作符,相当于执行 delete target[name]。
Reflect.get(target, propertyKey[, receiver]) 获取对象身上某个属性的值,类似于 target[name]。
Reflect.getOwnPropertyDescriptor(target, propertyKey) 类似于 Object.getOwnPropertyDescriptor()。如果对象中存在该属性,则返回对应的属性描述符,否则返回 undefined。
Reflect.getPrototypeOf(target) 与 Object.getPrototypeOf() 方法几乎是一样的。都是返回指定对象的原型(即内部的 [[Prototype]] 属性的值)。
Reflect.has(target, propertyKey) 判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。
Reflect.isExtensible(target) 与 Object.isExtensible() 方法相似,判断一个对象是否可扩展(即是否能够添加新的属性)。
Reflect.ownKeys(target) 返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受enumerable 影响)。
Reflect.preventExtensions(target) 类似于 Object.preventExtensions()。返回一个Boolean。
Reflect.set(target, propertyKey, value[, receiver]) 将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true。
Reflect.setPrototypeOf(target, prototype) 设置对象原型的函数。返回一个 Boolean, 如果更新成功,则返回true。

示例
检测一个对象是否存在特定属性并为这个对象添加新属性

const person = {
  name: 'Bob',
  age: 20,
  greeting: function() {
    console.log(`Hello! My name is ${this.name}`);
  }
}

Reflect.has(person, 'name');
// true
Reflect.has(person, 'haircut');
// false
Reflect.set(person, 'eyes', 'black');
person.eyes;
// 'black'

Reflect.apply()

定义:静态方法 Reflect.apply() 通过指定的参数列表发起对目标 (target) 函数的调用。
语法

Reflect.apply(target, thisArgument, argumentsList)

参数target目标函数、thisArgumenttarget 函数调用时绑定的 this 对象、argumentsListtarget 函数调用时传入的实参列表,该参数应该是一个类数组的对象。
返回值:返回值是调用完带着指定参数和 this 值的给定的函数后返回的结果。
异常:如果 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;
// 4
Reflect.apply("".charAt, "ponies", [3]);
// "i"

Reflect.construct()

定义:Reflect.construct() 方法的行为有点像 new 操作符 构造函数 , 相当于运行 new target(…args)。Reflect.construct允许你使用可变的参数来调用构造函数 ,这和使用new 操作符搭配对象展开符调用一样。

语法

Reflect.construct(target, argumentsList[, newTarget])

参数target被运行的目标构造函数、argumentsList类数组,目标构造函数调用时的参数、newTarget(可选)t作为新创建对象的原型对象的constructor属性, 参考 new.target 操作符,默认值为target。
返回值:以target(如果newTarget存在,则为newTarget)函数为构造函数,argumentList为其初始化参数的对象实例。
异常:如果 target 或者 newTarget 不是构造函数,抛出TypeError,异常。
示例

var d = Reflect.construct(Date, [1996, 6, 6]);
d instanceof Date; // true
d.getFullYear(); // 1996

Reflect.defineProperty()

定义:静态方法 Reflect.defineProperty() 方法允许精确添加或修改对象上的属性,基本等同于 Object.defineProperty() 方法,唯一不同是返回 Boolean 值。
语法

Reflect.defineProperty(target, propertyKey, attributes)

参数target目标函数、propertyKey要定义或修改的属性的名称、attributes要定义或修改的属性的描述。
返回值:Boolean 值指示了属性是否被成功定义。
异常:如果target不是 Object,抛出一个 TypeError。
示例

let obj = {}
Reflect.defineProperty(obj, 'x', {value: 8})  // true
obj.x                                         // 8

Reflect.deleteProperty()

定义:静态方法 Reflect.deleteProperty() 允许用于删除属性。它很像 delete operator ,但它是一个函数。Reflect.deleteProperty 允许你删除一个对象上的属性。返回一个 Boolean 值表示该属性是否被成功删除。它几乎与非严格的 delete operator 相同。
语法

Reflect.deleteProperty(target, propertyKey)

参数target删除属性的目标对象、propertyKey需要删除的属性的名称。
返回值:Boolean 值表明该属性是否被成功删除。
异常:抛出一个 TypeError,如果target不是 Object。
示例

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

Reflect.get()

定义:Reflect.get()方法与从 对象 (target[propertyKey]) 中读取属性类似,但它是通过一个函数执行来操作的。
语法

Reflect.get(target, propertyKey[, receiver])

参数target需要取值的目标对象、propertyKey需要获取的值的键值、receiver如果target对象中指定了getter,receiver则为getter调用时的this值。
返回值:属性的值。
异常:如果目标值类型不是 Object,则抛出一个 TypeError。
示例

// Object
var obj = { x: 1, y: 2 };
Reflect.get(obj, "x"); // 1
// Array
Reflect.get(["zero", "one"], 1); // "one"
// Proxy with a get handler
var x = {p: 1};
var obj = new Proxy(x, {
  get(t, k, r) { return k + "bar"; }
});
Reflect.get(obj, "foo"); // "foobar"

Reflect.getOwnPropertyDescriptor()

定义:静态方法 Reflect.getOwnPropertyDescriptor() 与 Object.getOwnPropertyDescriptor() 方法相似,与Object.getOwnPropertyDescriptor() 的唯一不同在于如何处理非对象目标。如果在对象中存在,则返回给定的属性的属性描述符。否则返回 undefined。
语法

Reflect.getOwnPropertyDescriptor(target, propertyKey)

参数target需要寻找属性的目标对象、propertyKey获取自己的属性描述符的属性的名称。
返回值:如果属性存在于给定的目标对象中,则返回属性描述符;否则,返回 undefined。
异常:抛出一个 TypeError,如果目标不是 Object。
示例

Reflect.getOwnPropertyDescriptor({x: "hello"}, "x");
// {value: "hello", writable: true, enumerable: true, configurable: true}
Reflect.getOwnPropertyDescriptor({x: "hello"}, "y");
// undefined
Reflect.getOwnPropertyDescriptor([], "length");
// {value: 0, writable: true, enumerable: false, configurable: false}

与 Object.getOwnPropertyDescriptor() 的不同点
如果该方法的第一个参数不是一个对象(一个原始值),那么将造成 TypeError 错误。而对于 Object.getOwnPropertyDescriptor,非对象的第一个参数将被强制转换为一个对象处理。

Reflect.getOwnPropertyDescriptor("foo", 0);
// TypeError: "foo" is not non-null object
Object.getOwnPropertyDescriptor("foo", 0);
// { value: "f", writable: false, enumerable: true, configurable: false }

Reflect.getPrototypeOf()

定义:静态方法 Reflect.getPrototypeOf() 与 Object.getPrototypeOf() 方法几乎是一样的。都是返回指定对象的原型(即内部的 [[Prototype]] 属性的值)。
语法

Reflect.getPrototypeOf(target)

参数target获取原型的目标对象。
返回值:给定对象的原型。如果给定对象没有继承的属性,则返回 null。
异常:如果 target 不是 Object,抛出一个 TypeError 异常。
示例

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

// 如果想要模拟 Object 在 ES2015 规范下的表现,需要强制类型转换
Reflect.getPrototypeOf(Object('foo'))  // String.prototype

Reflect.has()

定义:静态方法 Reflect.has() 作用与 in 操作符 相同。
语法

Reflect.has(target, propertyKey)

参数target目标对象、propertyKey属性名,需要检查目标对象是否存在此属性。
返回值:一个 Boolean 类型的对象指示是否存在此属性。
异常:如果目标对象并非Object 类型,抛出TypeError。
示例

Reflect.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

Reflect.isExtensible()

定义:静态方法 Reflect.isExtensible() 判断一个对象是否可扩展(即是否能够添加新的属性)。与它 Object.isExtensible() 方法相似,但有一些不同,详情可见 与 Object.isExtensible() 的不同点。
语法

Reflect.isExtensible(target)

参数target检查是否可扩展的目标对象。
返回值:返回一个 Boolean 值表明该对象是否可扩展。
异常:抛出一个 TypeError,如果对象不是 Object。
示例

// New objects are extensible.
var empty = {};
Reflect.isExtensible(empty); // === true
// ...but that can be changed.
Reflect.preventExtensions(empty);
Reflect.isExtensible(empty); // === false
// Sealed objects are by definition non-extensible.
var sealed = Object.seal({});
Reflect.isExtensible(sealed); // === false
// Frozen objects are also by definition non-extensible.
var frozen = Object.freeze({});
Reflect.isExtensible(frozen); // === false

与 Object.isExtensible() 的不同点
如果该方法的第一个参数不是一个对象(原始值),那么将造成一个 TypeError 异常。对于 Object.isExtensible(),非对象的第一个参数会被强制转换为一个对象。

Reflect.isExtensible(1);
// TypeError: 1 is not an object
Object.isExtensible(1);
// false

Reflect.ownKeys()

定义:静态方法 Reflect.ownKeys() 返回一个由目标对象自身的属性键组成的数组。它的返回值等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。
语法

Reflect.ownKeys(target)

参数target获取自身属性键的目标对象。
返回值:由目标对象的自身属性键组成的 Array。
异常:如果目标不是 Object,抛出一个 TypeError。
示例

Reflect.ownKeys({z: 3, y: 2, x: 1}); // [ "z", "y", "x" ]
Reflect.ownKeys([]); // ["length"]
var sym = Symbol.for("comet");
var sym2 = Symbol.for("meteor");
var obj = {[sym]: 0, "str": 0, "773": 0, "0": 0,
           [sym2]: 0, "-1": 0, "8": 0, "second str": 0};
Reflect.ownKeys(obj);
// [ "0", "8", "773", "str", "-1", "second str", Symbol(comet), Symbol(meteor) ]
// Indexes in numeric order,
// strings in insertion order,
// symbols in insertion order

Reflect.preventExtensions()

定义:静态方法 Reflect.preventExtensions() 方法阻止新属性添加到对象 (例如:防止将来对对象的扩展被添加到对象中)。该方法与Object.preventExtensions()相似。
语法

Reflect.preventExtensions(target)

参数target阻止扩展的目标对象。
返回值:返回一个 Boolean 值表明目标对象是否成功被设置为不可扩展。
异常:抛出一个 TypeError 错误,如果 target 不是 Object。
示例

// Objects are extensible by default.
var empty = {};
Reflect.isExtensible(empty); // === true
// ...but that can be changed.
Reflect.preventExtensions(empty);
Reflect.isExtensible(empty); // === false

与 Object.preventExtensions() 的不同点
如果该方法的 target 参数不是一个对象(是原始值),那么将造成一个 TypeError 异常。 对于Object.preventExtensions() 方法, 非对象的 target 参数将被强制转换为对象。

Reflect.preventExtensions(1);
// TypeError: 1 is not an object
Object.preventExtensions(1);
// 1

Reflect.set()

定义:静态方法 Reflect.set() 允许你在对象上设置属性。它的作用是给属性赋值并且就像 property accessor 语法一样,但是它是以函数的方式。
语法

Reflect.set(target, propertyKey, value[, receiver])

参数target设置属性的目标对象、propertyKey设置的属性的名称、value设置的值、receiver如果遇到 setter,receiver则为setter调用时的this值。
返回值:返回一个 Boolean 值表明是否成功设置属性。
异常:抛出一个 TypeError,如果目标不是 Object。
示例

// 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"
// It can truncate an array.
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.setPrototypeOf()

定义:除了返回类型以外,静态方法 Reflect.setPrototypeOf() 与 Object.setPrototypeOf() 方法是一样的。它可设置对象的原型(即内部的 [[Prototype]] 属性)为另一个对象或 null,如果操作成功返回 true,否则返回 false。
语法

Reflect.setPrototypeOf(target, prototype)

参数target设置原型的目标对象、prototype对象的新原型(一个对象或 null)。
返回值:返回一个 Boolean 值表明是否原型已经成功设置。
异常:如果 target 不是 Object ,或 prototype 既不是对象也不是 null,抛出一个 TypeError 异常。
示例

Reflect.setPrototypeOf({}, Object.prototype); // true
// It can change an object's [[Prototype]] to null.
Reflect.setPrototypeOf({}, null); // true
// Returns false if target is not extensible.
Reflect.setPrototypeOf(Object.freeze({}), null); // false
// Returns false if it cause a prototype chain cycle.
var target = {};
var proto = Object.create(target);
Reflect.setPrototypeOf(target, proto); // false

参考:
1.《Proxy - JavaScript | MDN》;
2.《Reflect - JavaScript | MDN》;

你可能感兴趣的:(JavaScript,es6,javascript,前端,开发语言)