ES6中物件新增的方法

南風晚來晚相識 發表於 2022-03-30
JavaScript ES6

屬性的簡潔表示法

ES6 允許在大括號裡面直接寫入變數和函式,作為物件的屬性和方法。這樣的書寫更加簡潔。
const foo = 'bar';
const baz = {
    foo
};
console.log(baz); // { foo: 'bar' }
function f(name, age) {
  return {
      name,
      age
  };
}

// 等同於
// function f(name, age) {
//     return {
//         name: name,
//         age: age
//     };
// }

console.log('資訊', f('李四', 23));
// 輸出的資訊是 {age: 23 name: "李四"}
let birth = '2022-3-27';
const Person = {
    name: '張三',
    //等同於birth: birth
    birth,
    // 等同於hello: function (){}
    hello() {
        console.log('我的名字叫:', this.name);
    }
};
// Person.hello(); // 我的名字叫:張三

//沒有返回值時,預設返回 undefined。下面這一條語句會被執行兩次
console.log('資訊', Person.hello());
// 第1次的值: 我的名字叫:張三
// 第2次的值: undefined
注意,簡寫的物件方法不能用作建構函式,會報錯。
let Person = {
  name: '張三',
  hello: function() {
    console.log('你好呀')
  },
  like() {
    console.log('簡寫的物件方法不能用作建構函式==>error會報錯')
  }
};
new Person.hello() // 不會報錯
new Person.like(); //會報錯

ES6物件屬性遍歷的5種方式

ES6 一共有 5 種方法可以遍歷物件的屬性。
1==>for...in
for...in迴圈遍歷物件自身的和繼承的可列舉屬性(不含 Symbol 屬性)。

const obj = { h: 180,w: 125}
for (let keysName in obj) {
  console.log(keysName);
  // h w 輸出的是key值哈
}


2==>Object.keys(obj)
Object.keys返回一個陣列,
包括物件自身的(不含繼承的)所有可列舉屬性(不含 Symbol 屬性)的鍵名。
const obj = {
    height: 180,
    weight: 125,
}
console.log(Object.keys(obj)) //['height', 'weight']


3==>Object.getOwnPropertyNames(obj) 【瞭解即可】
Object.getOwnPropertyNames返回一個陣列,
包含物件自身【所有的屬性】。[其自身的可列舉和不可列舉屬性的名稱被返回]
【不含 Symbol 屬性】的鍵名。
let obj = {};
let a = Symbol("a");
let b = Symbol.for("b");
obj[a] = "localSymbol";
obj[b] = "globalSymbol";
let objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(objectSymbols.length); // 2
console.log(objectSymbols) // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0]) // Symbol(a)

4==>Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一個陣列,包含物件自身的所有 Symbol 屬性的鍵名。


5==>Reflect.ownKeys(obj)
Reflect.ownKeys返回一個陣列,包含物件自身的(不含繼承的)所有鍵名。
不管鍵名是 Symbol 或字串,也不管是否可列舉。
const obj = {
  height: 180,
  weight: 125,
}
console.log(Reflect.ownKeys(obj))
//['height', 'weight']

以上的 5 種方法遍歷物件的鍵名,都遵守同樣的屬性遍歷的次序規則。

JavaScript中的可列舉屬性與不可列舉屬性

在JavaScript中,物件的屬性分為可列舉和不可列舉之分,
它們是由屬性的 enumerable 值決定的。
可列舉性決定了這個屬效能否被for…in查詢遍歷到。

屬性的列舉性會影響以下三個函式的結果:
for…in
Object.keys()
JSON.stringify

Object.is()

ES5 比較兩個值是否相等,只有兩個運算子。
相等運算子(==)和嚴格相等運算子(===)。
它們都有缺點,前者會自動轉換資料型別。
後者的NaN不等於自身,以及+0等於-0。
JavaScript 缺乏一種運算,只要兩個值是一樣的,它們就應該相等。
於是,ES6提出來了一種同值相等的演算法,來解決這個問題。
console.log('==>', Object.is('bar', 'bar'))
// true
console.log(Object.is({}, {}))
// false

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

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

Object.assign物件合併

Object.assign()方法用於物件的合併。
將源物件(source)的所有可列舉屬性,複製到目標物件(target。

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

Object.assign需要注意的點

需要注意的點:Object.assign()方法的第一個引數是目標物件,後面的引數都是源物件。
由於undefined和null無法轉成物件,所以如果它們作為引數,就會報錯。
Object.assign(undefined) // 報錯
Object.assign(null) // 報錯

如果非物件引數出現在源物件的位置即非首引數,
那麼處理規則有所不同。
首先,這些引數都會轉成物件,如果無法轉成物件,就會跳過。
這意味著,如果undefined和null不在首引數,就不會報錯。
let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true

特別注意:其他型別的值(即數值、布林值)不在首引數,也不會報錯。
但是,除了字串會以陣列形式,拷貝入目標物件。

-- 字串會以陣列形式拷貝入目標物件
const str1 = 'abc';
const obj = Object.assign({}, str1);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
為什麼字串會以陣列形式拷貝進入目標物件呢?
這是因為:只有字串的包裝物件,會產生可列舉屬性。

-- 數字不會拷入目標物件
const str2 = 123;
const obj = Object.assign({}, str2);
console.log(obj); // {}

-- 最後補充一點:
Object.assign()拷貝的屬性是有限制的,
只拷貝源物件的自身屬性(不拷貝繼承屬性),
也不拷貝不可列舉的屬性(enumerable: false)。
Object.assign()方法實行的是淺拷貝,而不是深拷貝。