阮一峰ES6教程讀書筆記(六)對象的新增方法

1. Object.is()

在ES6之前我們總是通過相等運算符==或者嚴(yán)格相等運算符===去判斷兩個值是否相等,但是這兩者都有一定的缺陷。所以JavaScript缺乏一種運算,能夠在所有環(huán)境中判斷兩個值是不是一樣的,如果是一樣的就應(yīng)該相等。
ES6提出了同值相等算法,用來解決這個問題,該算法與===表現(xiàn)較為類似,不同之處在于比較+0-0和比較NaN與其自身:

+0 === -0 // true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

在沒有部署Object.is()方法的環(huán)境可以通過以下代碼來部署該方法:

Object.defineProperty(Object, 'is', {
  value: function(x, y) {
    if (x === y) {
      // 針對+0 不等于 -0的情況
      return x !== 0 || 1 / x === 1 / y;
    }
    // 針對NaN的情況
    return x !== x && y !== y;
  },
  configurable: true,
  enumerable: false,
  writable: true
})

2. Object.assign()

Object.assign()主要用于對象的合并,其行為是將源對象的所有可枚舉屬性和方法添加到目標(biāo)對象中。

const [target, source] = [{}, {name: 'bing', age: 23}]
Object.assign(target, source)

target // {name: 'bing', age: 23}

其行為與擴(kuò)展運算符類似,不過擴(kuò)展運算符是把所有的源對象的屬性和方法都放到了一個新的對象中,但是Object.assign()是把源對象的屬性和方法放到了目標(biāo)對象中。

2.1 如果有同名屬性

如果有同名屬性,那么后面的屬性會覆蓋前面的屬性值

let a = {name: 'bing'}
let b = {name: 'yan', age: 24}
let c = {name: 'can', age: 27}

Object.assign(a,b,c) // {name: "can", age: 27}

2.2 如果參數(shù)不是對象

嚴(yán)謹(jǐn)?shù)膩碚f,如果源對象參數(shù)不是對象,或者是特殊對象(正則表達(dá)式,Date對象等),那么該方法會直接跳過參數(shù)而不會報錯

let a = new Date()
let b = {}

Object.assign(b, a) // {}

如果目標(biāo)對象不是對象或者是特殊對象,那么會返回一個包裝對象,當(dāng)然undefinednull除外

Object.assign(null) // Cannot convert undefined or null to object
Object.assign(undefined) // Cannot convert undefined or null to object

// 下面的都會返回一個包裝對象
Object.assign(NaN)
Object.assign(2)
Object.assign('string')

2.3 參數(shù)是數(shù)組的情況

因為數(shù)組也是一種對象,當(dāng)使用該方法時,數(shù)組會被當(dāng)做對象處理:

Object.assign([1, 2, 3, 6], [3, 4, 5]) // [3, 4, 5, 6]

上述代碼中因為目標(biāo)數(shù)組中索引從0-3的位置都被原數(shù)組給覆蓋了,所以返回的數(shù)組是[3, 4, 5, 6]

2.4 對取值函數(shù)的處理

Object.assign只能進(jìn)行值的復(fù)制,如果要復(fù)制的值是一個取值函數(shù),那么將求值后再復(fù)制。

const source = {
  get foo() { return 1 }
};
const target = {};

Object.assign(target, source)
// { foo: 1 }

上面代碼中,source對象的foo屬性是一個取值函數(shù),Object.assign不會復(fù)制這個取值函數(shù),只會拿到值以后,將這個值復(fù)制過去。

3. Object.getOwnPropertyDescriptors()

ES5 的Object.getOwnPropertyDescriptor()方法會返回某個對象屬性的描述對象(descriptor)。ES2017 引入了Object.getOwnPropertyDescriptors()方法,返回指定對象所有自身屬性(非繼承屬性)的描述對象。

onst obj = {
  foo: 123,
  get bar() { return 'abc' }
};

Object.getOwnPropertyDescriptors(obj)
// { foo:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: get bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }

上述代碼中,使用該方法后反悔了一個對象,對象中包括了源對象的所有自身的屬性的屬性描述對象,該方法的出現(xiàn)主要是為了解決Object.assign無法拷貝getset,使用Object.getOwnPropertyDescriptors()方法配合Object.defineProperties()方法,就可以實現(xiàn)正確拷貝。

onst source = {
  set foo(value) {
    console.log(value);
  }
};

const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
Object.getOwnPropertyDescriptor(target2, 'foo')
// { get: undefined,
//   set: [Function: set foo],
//   enumerable: true,
//   configurable: true }

4. Object.setPrototypeOf()

ES6 推薦使用該方法設(shè)置原型對象,在某些時候我們想新生成一個對象使之繼承現(xiàn)有對象的原型,我們可以采用以下方法:

// 方法一
const a = {name: 'bing'}
const b = a.constructor() // b繼承了a的原型

// 方法二
const a = {name: 'bing'}
const b = {}
Object.setPrototypeOf(b, Object.getPrototypeOf(a))

5. Object.values()

Object.values方法返回一個數(shù)組,成員是參數(shù)對象自身的(不含繼承的)所有可遍歷enumerable屬性的鍵值。

const a = {name: 'bing'}
a.__proto__.age = 23  // 繼承屬性
Object.defineProperty(a, 'gender', {value: 'male', enumerable: false}) 
// 不可枚舉屬性

Object.values(a) // ["bing"] 只返回自身的可枚舉屬性

如果該方法的參數(shù)是一個字符串,那么將會得到令人驚喜的結(jié)果:

Object.values('string') // ["s", "t", "r", "i", "n", "g"]
[...'string'] // ["s", "t", "r", "i", "n", "g"]
Array.from('string') // ["s", "t", "r", "i", "n", "g"]

上述三種方法都能把一個字符串分解為包含字符的數(shù)組

6. Object.entries()

Object.entries()方法返回一個數(shù)組,成員是參數(shù)對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值對數(shù)組。
Object.entries的基本用途是遍歷對象的屬性。

let obj = { one: 1, two: 2 };
for (let [k, v] of Object.entries(obj)) {
  console.log(
    `${JSON.stringify(k)}: ${JSON.stringify(v)}`
  );
}
// "one": 1
// "two": 2

Object.entries方法的另一個用處是,將對象轉(zhuǎn)為真正的Map結(jié)構(gòu)。

const obj = { foo: 'bar', baz: 42 };
const map = new Map(Object.entries(obj));
map // Map { foo: "bar", baz: 42 }

Object.fromEntries()方法是Object.entries()的逆操作,用于將一個鍵值對數(shù)組轉(zhuǎn)為對象。

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

該方法的主要目的,是將鍵值對的數(shù)據(jù)結(jié)構(gòu)還原為對象,因此特別適合將 Map 結(jié)構(gòu)轉(zhuǎn)為對象。

參考鏈接

作者:阮一峰
鏈接:http://es6.ruanyifeng.com/#docs/destructuring

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容