1. 程式人生 > >ES6的物件新增的方法

ES6的物件新增的方法

  1. Object.is() 嚴格比較兩個值是否相等
    ES5 比較兩個值是否相等,只有兩個運算子:相等運算子()和嚴格相等運算子(=)。它們都有缺點,前者會自動轉換資料型別,後者的NaN不等於自身,以及+0等於-0。
    Object.is就是部署這個演算法的新方法。它用來比較兩個值是否嚴格相等.不同:一是+0不等於-0,二是NaN等於自身。

  2. Obejct.assign() 物件合併
    Object.assign方法用於物件的合併,將源物件(source)的所有可列舉屬性,複製到目標物件(target)。
    Object.assign方法的第一個引數是目標物件,後面的引數都是源物件。
    Object.assign拷貝的屬性是有限制的,只拷貝源物件的自身屬性(不拷貝繼承屬性),也不拷貝不可列舉的屬性(enumerable: false)。
    屬性名為 Symbol 值的屬性,也會被Object.assign拷貝。

    注意,如果目標物件與源物件有同名屬性,或多個源物件有同名屬性,則後面的屬性會覆蓋前面的屬性。
    

    如果只有一個引數,Object.assign會直接返回該引數。
    如果該引數不是物件,則會先轉成物件,然後返回。

    由於undefined和null無法轉成物件,所以如果它們作為引數,就會報錯。如果非物件引數出現在源物件的位置(即非首引數),那麼處理規則有所不同。首先,這些引數都會轉成物件, 如果無法轉成物件,就會跳過。這意味著,如果undefined和null不在首引數,就不會報錯。
    其他型別的值(即數值、字串和布林值)不在首引數,也不會報錯。但是,除了字串會以陣列形式,拷貝入目標物件,其他值都不會產生效果。

const v1 = 'abc';
const v2 = true;
const v3 = 10;

const obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
//上面程式碼中,v1、v2、v3分別是字串、布林值和數值,結果只有字串合入目標物件(以字元陣列的形式),數值和布林值都會被忽略。這是因為只有字串的包裝物件,會產生可列舉屬性。

注意點 :
(1)淺拷貝
Object.assign方法實行的是淺拷貝,而不是深拷貝。也就是說,如果源物件某個屬性的值是物件,那麼目標物件拷貝得到的是這個物件的引用

(2)同名屬性的替換
對於這種巢狀的物件,一旦遇到同名屬性,Object.assign的處理方法是替換,而不是新增。

(3)陣列的處理
Object.assign可以用來處理陣列,但是會把陣列視為物件。

(4)取值函式的處理
Object.assign只能進行值的複製,如果要複製的值是一個取值函式,那麼將求值後再複製。

常見用途:
(1)為物件新增屬性

class Point {
  constructor(x, y) {
    Object.assign(this, {x, y});
  }
}
上面方法通過Object.assign方法,將x屬性和y屬性新增到Point類的物件例項。

(2)為物件新增方法
(3)克隆物件
(4)合併多個物件
(5)為屬性指定預設值

  1. Object.getOwnPropertyDescriptors()
    ES5 的Object.getOwnPropertyDescriptor()方法會返回某個物件屬性的描述物件(descriptor)。ES2017 引入了Object.getOwnPropertyDescriptors()方法,返回指定物件所有自身屬性(非繼承屬性)的描述物件。
    該方法主要是為了解決Object.assign()無法正確拷貝get屬性和set屬性的問題。
    Object.getOwnPropertyDescriptors()方法配合Object.defineProperties()方法,就可以實現正確拷貝。
const shallowMerge = (target, source) => Object.defineProperties(
  target,
  Object.getOwnPropertyDescriptors(source)
);

Object.getOwnPropertyDescriptors()方法的另一個用處,是配合Object.create()方法,將物件屬性克隆到一個新物件。這屬於淺拷貝。

Object.getOwnPropertyDescriptors()方法可以實現一個物件繼承另一個物件。
ES6 規定__proto__只有瀏覽器要部署,其他環境不用部署。
Object.getOwnPropertyDescriptors()也可以用來實現 Mixin(混入)模式

  1. __proto__屬性,Object.setPrototypeOf(),Object.getPrototypeOf()
    (1)__proto__屬性(前後各兩個下劃線),用來讀取或設定當前物件的prototype物件。目前,所有瀏覽器(包括 IE11)都部署了這個屬性。
// es5 的寫法
const obj = {
  method: function() { ... }
};
obj.__proto__ = someOtherObj;

// es6 的寫法
var obj = Object.create(someOtherObj);
obj.method = function() { ... };

__proto__前後的雙下劃線,說明它本質上是一個內部屬性,而不是一個正式的對外的 API,只是由於瀏覽器廣泛支援,才被加入了 ES6。
無論從語義的角度,還是從相容性的角度,都不要使用這個屬性,而是使用下面的Object.setPrototypeOf()(寫操作)、Object.getPrototypeOf()(讀操作)、Object.create()(生成操作)代替。
如果一個物件本身部署了__proto__屬性,該屬性的值就是物件的原型。Object.getPrototypeOf({ proto: null })// null

(2)Object.setPrototypeOf()
Object.setPrototypeOf方法的作用與__proto__相同,用來設定一個物件的prototype物件,返回引數物件本身。它是 ES6 正式推薦的設定原型物件的方法。

// 格式
Object.setPrototypeOf(object, prototype)
// 用法
const o = Object.setPrototypeOf({}, null);

//該方法等同於下面的函式
function setPrototypeOf(obj, proto) {
  obj.__proto__ = proto;
  return obj;
}
//由於undefined和null無法轉為物件,所以如果第一個引數是undefined或null,就會報錯

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

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

(3)Object.getPrototypeOf()
該方法與Object.setPrototypeOf方法配套,用於讀取一個物件的原型物件。Object.getPrototypeOf(obj);
如果引數不是物件,會被自動轉為物件。
如果引數是undefined或null,它們無法轉為物件,所以會報錯。

  1. Object.keys(),Object.values(),Object.entries()
    (1)Object.keys()
    ES5 引入了Object.keys方法,返回一個數組,成員是引數物件自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵名。
    ES2017 引入了跟Object.keys配套的Object.values和Object.entries,作為遍歷一個物件的補充手段,供for…of迴圈使用。

    (2)Object.values()
    Object.values方法返回一個數組,成員是引數物件自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值。
    Object.values會過濾屬性名為 Symbol 值的屬性。
    如果Object.values方法的引數是一個字串,會返回各個字元組成的一個數組。
    如果引數不是物件,Object.values會先將其轉為物件。由於數值和布林值的包裝物件,都不會為例項新增非繼承的屬性。所以,Object.values會返回空陣列。
    (3)Object.entries()
    Object.entries()方法返回一個數組,成員是引數物件自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值對陣列。
    除了返回值不一樣,該方法的行為與Object.values基本一致。
    如果原物件的屬性名是一個 Symbol 值,該屬性會被忽略。
    Object.entries的基本用途是遍歷物件的屬性。
    Object.entries方法的另一個用處是,將物件轉為真正的Map結構。

  2. Object.fromEntries()
    Object.fromEntries()方法是Object.entries()的逆操作,用於將一個鍵值對陣列轉為物件。
    該方法的主要目的,是將鍵值對的資料結構還原為物件,因此特別適合將 Map 結構轉為物件。
    該方法的一個用處是配合URLSearchParams物件,將查詢字串轉為物件

Object.fromEntries([
  ['foo', 'bar'],
  ['baz', 42]
])
// { foo: "bar", baz: 42 }


// 例一
const entries = new Map([
  ['foo', 'bar'],
  ['baz', 42]
]);

Object.fromEntries(entries)
// { foo: "bar", baz: 42 }

// 例二
const map = new Map().set('foo', true).set('bar', false);
Object.fromEntries(map)
// { foo: true, bar: false }


Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
// { foo: "bar", baz: "qux" }
  1. 詳細參考 http://es6.ruanyifeng.com/#docs/object-methods