1. 程式人生 > >ES6和ES5語法區別(Reflect物件和Object物件 )

ES6和ES5語法區別(Reflect物件和Object物件 )

概述

Reflect物件與Proxy物件一樣,也是 ES6 為了操作物件而提供的新 API。

現階段,某些方法同時在Object和Reflect物件上部署,未來的新方法將只部署在Reflect物件上。也就是說,從Reflect物件上可以拿到語言內部的方法。

//ES5寫法
try{
 Object.defineProperty(target,property,attributes);
   //success
} catch(e){
  //failure
}

//ES6寫法
if(Reflect.defineProperty(target,property,attributes)){
  //success
}else{ //failure } //ES5寫法 Function.prototype.apply.call(Math.floor,undefined,[1.75]) //1 //ES6寫法 Reflect.apply(Math.floor,undefined,[1.75]) //1

Reflect.get(target, name, receiver)

Reflect.get方法查詢並返回target物件的name屬性,如果沒有該屬性,則返回undefined。

var myObject = {
   foo:1,
   bar:2,
   get baz(){
      return
this.foo + this.bar } } Reflect.get(myObject,'foo') //1 Reflect.get(myObject,'bar') //2 Reflect.get(myObject,'baz') //3

如果name屬性部署了讀取函式(getter),則讀取函式的this繫結receiver。

var myObject = {
  foo: 1,
  bar: 2,
  get baz() {
    return this.foo + this.bar;
  },
};

var myReceiverObject = {
  foo: 4,
  bar: 4
, }; Reflect.get(myObject, 'baz', myReceiverObject) // 8

第一個引數不是物件,Reflect.get方法會報錯。

Reflect.get(1, 'foo') // 報錯
Reflect.get(false, 'foo') // 報錯

Reflect.set(target, name, value, receiver)

Reflect.set方法設定target物件的name屬性等於value值。

var myObject = {
   foo:1,
   set bar(value){
      return this.foo = value;
   }
}

myObject.foo //1

Reflect.set(myObject,'foo',2);
myObject.foo //2

Reflect.set(myObject,'bar',3);
myObject.foo //3

如果name屬性設定了賦值函式,則賦值函式的this繫結receiver。

var myObject = {
  foo: 4,
  set bar(value) {
    return this.foo = value;
  },
};

var myReceiverObject = {
  foo: 0,
};

Reflect.set(myObject, 'bar', 1, myReceiverObject);
myObject.foo // 4
myReceiverObject.foo // 1

如果第一個引數不是物件,Reflect.set會報錯。

Reflect.set(1, 'foo', {}) // 報錯
Reflect.set(false, 'foo', {}) // 報錯

Reflect.has(obj, name)

Reflect.has方法對應name in obj裡面的in運算子。

var myObject = {
   foo:1,
}

//ES5寫法
'foo' in myObject //true

//ES6寫法
Reflect.has(myObject,'foo')

Reflect.construct(target,args)

Reflect.construct方法等同於new target(…args),這提供了一種不使用new,來呼叫建構函式的方法。

function Greeting(name){
   this.name = name;
}

//new的寫法
const instance = new Greeting('阿蔡');

//Reflect.construct寫法
const instance = Reflect.construct(Greeting,['阿蔡']);

Reflect.getPrototypeOf(obj)

Reflect.getPrototypeOf方法用於讀取物件的_proto_屬性,對應Object.getPrototypeOf(obj)。

const myObj = new FancyThing();

//ES5寫法
Object.getPrototypeOf(myObj) === FancyThing.prototype;

//ES6寫法
Reflect.getPrototypeOf(myObj) === FancyThing.prototype;

Reflect.getPrototypeOf和Object.getPrototypeOf的一個區別是,如果引數不是物件,Object.getPrototypeOf會將這個引數轉為物件,然後再執行,而Reflect.getPrototypeOf會報錯。

Object.getPrototypeOf(1) // Number {[[PrimitiveValue]]: 0}
Reflect.getPrototypeOf(1) // 報錯

Reflect.setPrototypeOf(obj, newProto)

Reflect.setPrototypeOf方法用於設定物件的_proto_屬性,返回第一個引數物件,對應Object.setPrototypeOf(obj, newProto)。

const myObj = new FancyThing();

//ES5寫法
Object.setPrototypeOf(myObj,OtherThing.prototyype);

//ES6寫法
Reflect.setPrototypeOf(myObj,OtherThing.prototyype);

如果第一個引數不是物件,Object.setPrototypeOf會返回第一個引數本身,而Reflect.setPrototypeOf會報錯。

Object.setPrototypeOf(1, {})
// 1

Reflect.setPrototypeOf(1, {})
// TypeError: Reflect.setPrototypeOf called on non-object

如果第一個引數是undefined或null,Object.setPrototypeOf和Reflect.setPrototypeOf都會報錯。

Object.setPrototypeOf(null, {})
// TypeError: Object.setPrototypeOf called on null or undefined

Reflect.setPrototypeOf(null, {})
// TypeError: Reflect.setPrototypeOf called on non-object

Reflect.apply(func, thisArg, args)

Reflect.apply方法等同於Function.prototype.apply.call(func, thisArg, args),用於繫結this物件後執行給定函式。

一般來說,如果要繫結一個函式的this物件,可以這樣寫fn.apply(obj, args),但是如果函式定義了自己的apply方法,就只能寫成Function.prototype.apply.call(fn, obj, args),採用Reflect物件可以簡化這種操作。

const ages = [11, 33, 12, 54, 18, 96];

// ES5寫法
const youngest = Math.min.apply(Math, ages);
const oldest = Math.max.apply(Math, ages);
const type = Object.prototype.toString.call(youngest);

// ES6寫法
const youngest = Reflect.apply(Math.min, Math, ages);
const oldest = Reflect.apply(Math.max, Math, ages);
const type = Reflect.apply(Object.prototype.toString, youngest, []);

Reflect.defineProperty(target, propertyKey, attributes)

Reflect.defineProperty方法基本等同於Object.defineProperty,用來為物件定義屬性。

function MyDate() {
  /*…*/
}

// ES5寫法
Object.defineProperty(MyDate, 'now', {
  value: () => new Date.now()
});

// ES6寫法
Reflect.defineProperty(MyDate, 'now', {
  value: () => new Date.now()
});

如果Reflect.defineProperty的第一個引數不是物件,就會丟擲錯誤,比如Reflect.defineProperty(1, ‘foo’)。

Reflect.getOwnPropertyDescriptor(target, propertyKey)

Reflect.getOwnPropertyDescriptor基本等同於Object.getOwnPropertyDescriptor,用於得到指定屬性的描述物件。

var myObject = {};
Object.defineProperty(myObject, 'hidden', {
  value: true,
  enumerable: false,
});

// ES5寫法
var theDescriptor = Object.getOwnPropertyDescriptor(myObject, 'hidden');

// ES6寫法
var theDescriptor = Reflect.getOwnPropertyDescriptor(myObject, 'hidden');

Reflect.getOwnPropertyDescriptor和Object.getOwnPropertyDescriptor的一個區別是,如果第一個引數不是物件,Object.getOwnPropertyDescriptor(1, ‘foo’)不報錯,返回undefined,而Reflect.getOwnPropertyDescriptor(1, ‘foo’)會丟擲錯誤,表示引數非法。

Reflect.isExtensible (target)

Reflect.isExtensible方法對應Object.isExtensible,返回一個布林值,表示當前物件是否可擴充套件。

const myObject = {};

// ES5寫法
Object.isExtensible(myObject) // true

// ES6寫法
Reflect.isExtensible(myObject) // true

如果引數不是物件,Object.isExtensible會返回false,因為非物件本來就是不可擴充套件的,而Reflect.isExtensible會報錯。

Object.isExtensible(1) // false
Reflect.isExtensible(1) // 報錯

Reflect.preventExtensions(target)

Reflect.preventExtensions對應Object.preventExtensions方法,用於讓一個物件變為不可擴充套件。它返回一個布林值,表示是否操作成功。

var myObjet = {};

//ES5寫法
Object.isExtensible(myObject) //true

//ES6寫法
Reflect.preventExtensions(1) //true

如果引數不是物件,Object.isExtensible在 ES5 環境報錯,在 ES6 環境返回這個引數,而Reflect.preventExtensions會報錯。

// ES5
Object.preventExtensions(1) // 報錯

// ES6
Object.preventExtensions(1) // 1

// 新寫法
Reflect.preventExtensions(1) // 報錯

Reflect.ownKeys (target)

Reflect.ownKeys方法用於返回物件的所有屬性,基本等同於Object.getOwnPropertyNames與Object.getOwnPropertySymbols之和。

var myObject = {
  foo:1,
  bar:2,
  [Symbol.for('baz')]:3,
  [Symbol.for('bing')]:4
};

//ES5寫法
Object.getOwnPropertyNames(myObject)  //['foo', 'bar']

Object.getOwnPropertySymbols(myObject)
//[Symbol.for('baz'), Symbol.for('bing')]

// ES6寫法
Reflect.ownKeys(myObject)
// ['foo', 'bar', Symbol.for('baz'), Symbol.for('bing')]