ES6對象的擴展

1 屬性的簡潔表示法

ES6允許直接寫入變量和函數,作爲對象的屬性和方法。這種寫法更加簡潔

const foo = 'bar';
const baz = {foo};
bar       // {foo: 'bar'}

// 等同於
const baz = {foo: foo}
function f(x, y) {
  return {x, y};
}

// 等同於

function f(x, y) {
  return {x: x, y: y};
}

f(1, 2) // Object {x: 1, y: 2}

方法也是可以簡寫:

const o = {
  method() {
    return "Hello!";
  }
};

// 等同於

const o = {
  method: function() {
    return "Hello!";
  }
};

實際中的例子

function getPoint() {
  const x = 1;
  const y = 10;
  return {x, y};
}

getPoint()
// {x:1, y:10}

屬性的賦值器(setter)和取值器(getter),事實上也是採用這種寫法。

const cart = {
    _wheels: 4,

    get wheels () {
    return this._wheels;
    },

    set wheels (value) {
    if (value < this._wheels) {
        throw new Error('數值太小了!');
    }
    this._wheels = value;
    }
}

2 屬性名表達式
Javascript定義對象的屬性,有兩種方法。

// 方法一
obj.foo = true;

// 方法二
obj['a' + 'bc'] = 123;

console.log(obj);  // Object {foo: true, abc: 123}

但是如果使用字面量方式定義對象(使用大括號),在ES5中只能使用方法一來定義屬性。

var obj = {
    foo: true,
    abc: 123
}

ES6允許字面量定義對象時,使用方法二作爲對象的屬性名,即把表達式放在方括號內。

let propKey = 'foo';

let obj = {
  [propKey]: true,
  ['a' + 'bc']: 123
};

console.log(obj); // Object {foo: true, abc: 123}

3 方法的name屬性
函數的name屬性,返回函數名,對象方法也是函數,因此也有name屬性。

const person = {
  sayName() {
    console.log('hello!');
  },
};

person.sayName.name   // "sayName"

4 Object.assign()
Object.assign方法用於對象的合併,將源對象的所有可枚舉屬性,複製到目標對象(target)

const target = { a: 1 };

const source1 = { b: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

注意,如果目標對象與源對象有同名屬性,或對各源對象有同名屬性,後面的屬性會覆蓋前面的屬性。

const target = { a: 1, b: 1 };

const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target          // {a:1, b:2, c:3}

如果只有一個參數,Object.assign 會直接返回該參數

cons obj = {a: 1};
Object.assign(obj) === obj;   // true

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

const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b                // 2

上面代碼中,源對象obj1的a屬性的值是一個對象,Object.assign拷貝得到的是這個對象的引用。這個對象的任何變化,都會反映到目標對象上面。
(2)同名屬性的替換
對於這種嵌套的對象,一旦遇到同名屬性,Object.assign的處理方法是替換,而不是添加。

const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }

上面代碼中,target對象的a屬性被source對象的a屬性整個替換掉了,而不會得到

{ a: { b: 'hello', d: 'e' } }

這樣的結果,所以需要注意!
(3) 取值函數的處理
Object.assign只能進行值得複製,如果要複製的值是一個取值函數,那麼將求值後再複製。

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

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

上面代碼中,source對象的foo屬性是一個取值函數,Object.assign不會複製這個取值函數,只會等拿到值以後,將這個值複製過去。
常見用途
(1)爲對象添加方法

Object.assign(SomeClass.prototype, {
  someMethod(arg1, arg2) {
    ···
  },
  anotherMethod() {
    ···
  }
});

// 等同於下面的寫法
SomeClass.prototype.someMethod = function (arg1, arg2) {
  ···
};
SomeClass.prototype.anotherMethod = function () {
  ···
};

上面代碼使用了對象屬性的簡介表示法,直接將兩個函數放在大括號中,再使用assign方法添加到SomeClass.prototype之中。
(2)克隆對象

function clone(origin) {
  return Object.assign({}, origin);
}

上面代碼將原始對象拷貝到一個空對象,就得到了原始對象的克隆。
不過採用這種方法克隆,只能克隆到原始對象自身的值,不能克隆它繼承的值。

本博客內容摘抄自
阮一峯老師寫的ECMAScript6入門一書

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章