【ES6基礎】Object的新方法

前端達人發表於2019-05-28

Object物件可謂是JS的重要核心內容,在你使用JS的過程中,你會發現自己的工作大部分都是在操作物件,ES6、ES7、ES8引入了不少新的方法,本篇文章筆者將帶著大家一起熟悉下重點的新方法。

本篇文章,筆者將從以下幾個方面進行介紹:

  • 更簡潔的語法
  • Object.values()
  • Object.entries()
  • __proto__
  • Object.is()
  • Object.setPrototypeOf()
  • Object.assign()
  • Object.getOwnPropertyDescriptors()

本篇文章閱讀時間預計6分鐘

更簡潔的語法

定義屬性

我們都知道定義一個物件,必須明確屬性名和對應的值,及時屬性名和宣告的變數名一樣(var a = {obj:obj}),ES6及後續版本允許我們用短的程式碼宣告物件,用於將物件的屬性分配給與屬性同名的變數,我們一般會這麼宣告變數,程式碼如下:

var x = 1, y = 2;
var object = {
 x: x,
 y: y 
};
console.log(object.x); //output "1”複製程式碼

但是ES6之後,你可以這麼做

let x = 1, y = 2;
let object = { x, y };
console.log(object.x); 複製程式碼

定義方法

ES6提供了一種新的語法定義物件的方法,示例程式碼如下:

let object = {
    myFunction(){
        console.log("Hello World!!!"); //Output "Hello World!!!"
    }
}
object.myFunction();複製程式碼

我們可以看出,省去了宣告屬性名,屬性名即為方法名。

計算屬性名

物件屬性支援計算屬性名。其允許在[]中放入表示式,計算結果可以當做屬性名。

let object = {
["first" + "Name"]: "Eden",
};
//extract
console.log(object["first" + "Name"]); 
//Output "Eden”
console.log(object);
//Output "{ firstName: 'Eden' }”複製程式碼

Object.values()

ES8 引入了Object.values()方法,以陣列的形式輸出所有物件的值,省去我們手動迭代取出每個物件屬性的值,示例程式碼如下:

const obj = {
    book: "Learning ES2017 (ES8)",
    author: "前端達人",
    publisher: "前端達人",
    useful: true
};
console.log(Object.values(obj));複製程式碼

上述程式碼將會輸出:

[ 'Learning ES2017 (ES8)', '前端達人', '前端達人', true ]複製程式碼

Object.entries()

Object.entries()可用於將物件轉換為鍵/值對的陣列形式。 即一個二維陣列,陣列的每個元素是一個包含鍵和值的陣列。 示例程式碼如下:

const obj = {
    book: "Learning ES2017 (ES8)",
    author: "前端達人",
    publisher: "前端達人",
    useful: true
};
console.log(Object.entries(obj));複製程式碼

上述程式碼將會輸出:

[ [ 'book', 'Learning ES2017 (ES8)' ],
  [ 'author', '前端達人' ],
  [ 'publisher', '前端達人' ],
  [ 'useful', true ] ]複製程式碼

__proto__

proto:是一個物件擁有的內建屬性,是JS內部使用尋找原型鏈的屬性。可以理解為它是一個指標,用於指向建立它的函式物件的原型物件prototype(即建構函式的prototype)。prototype(原型物件):是函式(Function)的一個屬性(每個函式都有一個prototype),這個物件包含了此函式的所有例項共享的屬性和方法,即:原型物件。

__proto__屬性在ES5中沒有標準化,但由於它的受歡迎程度,它在以後的版本中被標準化了。 我們可以使用Object.getPrototypeOf()方法返回指定物件的原型(內部[[Prototype]]屬性的值,可以使用Object.create()方法建立一個新物件,使用現有的物件來提供新建立的物件的__proto__。

//In ES5
var x = {prop1: 12};
var y = Object.create(x, {prop2:{value: 13}});
console.log(y.prop1); //Output "12"
console.log(y.prop2); //Output "13"
console.log(x); // Output: {prop1: 12}
console.log(y); // Output: {prop2: 13}
console.log(y.__proto__); // Output: {prop1: 12}

//In ES6 onwards
let a = {prop1: 12, __proto__: {prop2: 13}};
console.log(a.prop1); //Output "12"
console.log(a.prop2); //Output "13"
console.log(a); // Output: {prop1: 12}
console.log(a.__proto__); // Output: {prop2: 13}複製程式碼

在ES5示例中,物件y繼承物件x,x的屬性相對於y來說是隱藏的,我們可以使用__proto__來查詢繼承自x的屬性prop1。ES6及其後,你可以直接將值新增到物件的原型鏈中。

Object.is()

Object.is()方法用於確定兩個值是否相等。它類似於===運算子,但Object.is()方法有一些特殊情況和使用“===”的結果是不一致的,如下段程式碼所示:

console.log(Object.is(0, -0));//false
console.log(0 === -0);//true
console.log(Object.is(NaN, 0/0));//true
console.log(NaN === 0/0);//false
console.log(Object.is(NaN, NaN));//true
console.log(NaN ===NaN);//false複製程式碼

如下圖所示,展示了使用==,===和Object.is的結果差異:

【ES6基礎】Object的新方法

Object.setPrototypeOf()

Object.setPrototypeOf方法可以為現有物件設定原型,返回一個新物件。Object.setPrototypeOf方法接受兩個引數,第一個是現有物件,第二個是原型物件。Object.setPrototypeOf() 是給物件設定原型,是為了obj.proto = .... 這種寫法更優雅,有更好的相容性。如下段程式碼所示:

let x = {x: 12};
let y = {y: 13};
Object.setPrototypeOf(y, x);
console.log(y.x); //Output "12"
console.log(y.y); //Output "13”
console.log(y);//Output "{ y: 13 }"
console.log(y.__proto__);//Output "{ x: 12 }"複製程式碼

Object.assign()

Object.assign()方法用於將所有可列舉屬性的值從一個或多個源物件複製到目標物件。它將返回目標物件。它至少需要兩個物件作為引數,第一個引數是目標物件,後面的引數都是源物件。如下段程式碼所示:

let x = {x: 12};
let y = {y: 13, __proto__: x};
let z = {z: 14, get b() {return 2;}, q: {}};
Object.defineProperty(z, "z", {enumerable: false});
let m = {};
Object.assign(m, y, z);
console.log(m.y);//13
console.log(m.z);//undefined
console.log(m.b);//2
console.log(m.x);//undefined
console.log(m.q == z.q);//true複製程式碼

從上述程式碼輸出,我們可以得出Object.assign()方法的一些特徵:

  • 該方法使用源物件的[[Get]]和目標物件的[[Set]],所以它會呼叫相關getter和setter。
  • 它只是將源的屬性值分配給目標的新屬性或現有屬性。
  • 它不會複製來源的[[prototype]]屬性。
  • JavaScript屬性名稱可以是字串或symbol。Object.assign()這兩種都支援。
  • Object.assign方法只會拷貝源物件自身的並且可列舉的屬性到目標物件。
  • 如果目標物件中的屬性具有相同的鍵,則屬性將被源中的屬性覆蓋。後來的源的屬性將覆蓋早先的屬性。
  • 為了將屬性定義(包括其可列舉性)複製到原型,應使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。
  • Object.assign不會跳過那些值為[null]或[undefined]的源物件。

Object.getOwnPropertyDescriptors()

在ES8中JS引入Object.getOwnPropertyDescriptors()方法將返回給定物件的所有屬性描述,如下段程式碼所示:

const details = { 
    get food1() { return 'tasty'; },
    get food2() { return 'bad'; }
};
console.log(Object.getOwnPropertyDescriptors(details));複製程式碼

上述程式碼將會輸出:

{ food1:
   { get: [Function: get food1],
     set: undefined,
     enumerable: true,
     configurable: true },
  food2:
   { get: [Function: get food2],
     set: undefined,
     enumerable: true,
     configurable: true } }複製程式碼

這個方法還會用在物件的克隆上,示例程式碼如下:

const x = { foo: 1, __proto__: { bar: 2 } };
const y = Object.create( 
  Object.getPrototypeOf(x), 
  Object.getOwnPropertyDescriptors(x) 
);
console.log(y.__proto__); // { bar: 2 }複製程式碼

小節

今天的內容就到這裡,我們可以看出ES6關於物件的使用,增加了不少新方法,使用得當,可以讓我們的業務程式碼更加簡潔易讀,建議大家在實踐中多多運用,加深和理解其應用場景。


【ES6基礎】Object的新方法


相關文章