4種用JavaScript創(chuàng)建對(duì)象的方法

英文 | https://medium.com/programming-essentials/4-ways-to-create-objects-in-javascript-ccb88772a61b
翻譯 | 小愛
本文將介紹4種使用JavaScript構(gòu)建對(duì)象的方法。具體方法如下:
Object literals
Object.create()
Classes
Factory Functions
1、Object literals
創(chuàng)建對(duì)象的最簡(jiǎn)單方法之一是創(chuàng)建對(duì)象文字語法。
示例如下:
const product = {name: 'apple',category: 'fruits',price: 1.99}console.log(product);
JavaScript中的對(duì)象是鍵值對(duì)的動(dòng)態(tài)集合。密鑰始終是字符串,并且在集合中必須是唯一。該值可以是基元、對(duì)象甚至函數(shù)。
這是一個(gè)值是另一個(gè)對(duì)象的示例:
const product = {name: 'apple',category: 'fruits',price: 1.99,nutrients : {carbs: 0.95,fats: 0.3,protein: 0.2}}
該carbs屬性的值是一個(gè)新對(duì)象。接下來檢查我們?nèi)绾卧L問該carbs屬性。
console.log(product.nutrients.carbs);//0.95
簡(jiǎn)寫屬性名稱
考慮將屬性值存儲(chǔ)在變量中的情況。
const name = 'apple';const category = 'fruits';const price = 1.99;const product = {name: name,category: category,price: price}
JavaScript支持速記屬性名稱。它允許我們僅使用變量名來創(chuàng)建對(duì)象。它將創(chuàng)建一個(gè)具有相同名稱的屬性。下一個(gè)對(duì)象文字與上一個(gè)相同。
const name = 'apple';const category = 'fruits';const price = 1.99;const product = {name,category,price}
2、對(duì)象創(chuàng)建
JavaScript具有所謂的原型系統(tǒng),該系統(tǒng)允許在對(duì)象之間共享行為。主要思想是創(chuàng)建一個(gè)具有常見行為的原型對(duì)象,然后在創(chuàng)建新對(duì)象時(shí)使用它。
原型系統(tǒng)允許創(chuàng)建從其他對(duì)象繼承行為的對(duì)象。
原型通常用于存儲(chǔ)方法,而不是數(shù)據(jù)。讓我們創(chuàng)建一個(gè)原型對(duì)象,使我們可以添加產(chǎn)品并從購物車中獲得總價(jià)。
const cartPrototype = {addProduct: function(product){if(!this.products){this.products = [product]} else {this.products.push(product);}},getTotalPrice: function(){return this.products.reduce((total, p) => total + p.price, 0);}}
請(qǐng)注意,這次屬性的值 ddProduct是一個(gè)函數(shù)。我們還可以使用一種稱為“簡(jiǎn)寫方法”語法的較短形式來編寫先前的對(duì)象。
const cartPrototype = {addProduct(product){ },getTotalPrice(){ }}
該cartPrototype是原型對(duì)象,保持在兩種方法addProduct和getTotalPrice的共同行為。它可用于構(gòu)建繼承此行為的其他對(duì)象。
const cart = Object.create(cartPrototype);cart.addProduct({name: 'orange', price: 1.25});cart.addProduct({name: 'lemon', price: 1.75});console.log(cart.getTotalPrice());//3
cartPrototype對(duì)象是原型cart的對(duì)象。cart有一個(gè)稱為 __proto__該原型對(duì)象的隱藏屬性。
cart.__proto__ === cartPrototype;//true
當(dāng)我們?cè)趯?duì)象上使用該方法時(shí),首先在對(duì)象本身而不是原型上搜索該方法。
this
請(qǐng)注意,我們使用特殊的關(guān)鍵字來訪問和修改名為this對(duì)象上的數(shù)據(jù)。
請(qǐng)記住,函數(shù)是JavaScript中行為的獨(dú)立單元。它們不一定是對(duì)象的一部分。
當(dāng)函數(shù)是對(duì)象的一部分時(shí),它們將成為方法,并且它們需要一種方法來訪問同一對(duì)象上的其他成員。this是函數(shù)上下文,并提供對(duì)同一對(duì)象的其他屬性的訪問。
Data
你可能想知道為什么我們沒有在products原型對(duì)象本身上定義和初始化屬性。
因?yàn)槲覀儾粦?yīng)該那樣做。原型應(yīng)該用于共享行為,而不是數(shù)據(jù)。共享數(shù)據(jù)將導(dǎo)致在多個(gè)購物車對(duì)象上擁有相同的產(chǎn)品。請(qǐng)看下面的代碼。
const cartPrototype = {products:[],addProduct: function(product){this.products.push(product);},getTotalPrice: function(){}}const cart1 = Object.create(cartPrototype);cart1.addProduct({name: 'orange', price: 1.25});cart1.addProduct({name: 'lemon', price: 1.75});console.log(cart1.getTotalPrice());//3const cart2 = Object.create(cartPrototype);console.log(cart2.getTotalPrice());//3
從cart1和cart2繼承相同行為的cartPrototype對(duì)象,它們都共享相同的數(shù)據(jù)。如果我們不想要那個(gè)的話,這樣就會(huì)導(dǎo)致出錯(cuò)。所以原型應(yīng)該用于共享行為,而不是共享數(shù)據(jù)。
Classes
原型系統(tǒng)不是構(gòu)建對(duì)象的常用方法。開發(fā)人員更熟悉在類之外構(gòu)建對(duì)象。
類語法允許使用更熟悉的方式來創(chuàng)建共享共同行為的對(duì)象。它仍然在幕后創(chuàng)建相同的原型,但是語法更加清晰,我們還避免了先前與數(shù)據(jù)相關(guān)的問題。
該類提供了一個(gè)特殊的函數(shù)來定義每個(gè)對(duì)象(稱為構(gòu)造函數(shù))所不同的數(shù)據(jù)。
這是使用sugar類語法創(chuàng)建的同一對(duì)象。
class Cart{constructor(){this.products = [];}addProduct(product){this.products.push(product);}getTotalPrice(){return this.products.reduce((total, p) => total + p.price, 0);}}const cart = new Cart();cart.addProduct({name: 'orange', price: 1.25});cart.addProduct({name: 'lemon', price: 1.75});console.log(cart.getTotalPrice());//3const cart2 = new Cart();console.log(cart2.getTotalPrice());//0
請(qǐng)注意,該類具有一個(gè)構(gòu)造函數(shù)方法,該方法為每個(gè)新對(duì)象初始化了不同的數(shù)據(jù)。實(shí)例之間不共享構(gòu)造函數(shù)中的數(shù)據(jù)。為了創(chuàng)建一個(gè)新實(shí)例,我們使用new關(guān)鍵字。
我認(rèn)為大多數(shù)開發(fā)人員都應(yīng)該清楚和熟悉該類語法。但是,它做類似的事情,它使用所有方法創(chuàng)建一個(gè)原型,并使用它來定義新對(duì)象。可以使用訪問原型Cart.prototype。
cart.__proto__ === Cart.prototype;//true
事實(shí)證明,原型系統(tǒng)足夠靈活,可以使用類語法。因此,可以使用原型系統(tǒng)對(duì)類系統(tǒng)進(jìn)行仿真。
Private Properties
唯一的事情是products新對(duì)象的屬性默認(rèn)情況下是公共的。
console.log(cart.products);//[{name: "orange", price: 1.25}// {name: "lemon", price: 1.75}]
我們可以使用哈希#前綴將其設(shè)為私有。
私有屬性使用#name語法聲明。#是屬性名稱本身的一部分,應(yīng)用于聲明和訪問屬性。這是一個(gè)聲明products為私有財(cái)產(chǎn)的示例。
class Cart{constructor(){this.}addProduct(product){this.}getTotalPrice(){return this.}}console.log(cart.//Uncaught SyntaxError: Private field '#products' must be declared in an enclosing class
Factory Functions
另一種選擇是將對(duì)象創(chuàng)建為閉包的集合。
閉包是函數(shù)即使在外部函數(shù)執(zhí)行后也可以從外部函數(shù)訪問變量和參數(shù)的能力。看一下cart使用工廠功能構(gòu)建的下一個(gè)對(duì)象。
function Cart() {const products = [];function addProduct(product){products.push(product);}function getTotalPrice(){return products.reduce((total, p) => total + p.price, 0);}return {addProduct,getTotalPrice}}const cart = Cart();cart.addProduct({name: 'orange', price: 1.25});cart.addProduct({name: 'lemon', price: 1.75});console.log(cart.getTotalPrice());//3
addProduct和getTotalPrice是兩個(gè)內(nèi)部函數(shù)products從其父級(jí)訪問變量。products父級(jí)Cart執(zhí)行后,他們可以訪問變量事件。addProduct和getTotalPrice兩個(gè)關(guān)閉共享同一個(gè)私有變量。
Cart 是Factory 函數(shù)。
cart使用Factory函數(shù)創(chuàng)建的新對(duì)象具有products變量private。不能從外部訪問它。
console.log(cart.products);//undefined
Factory 函數(shù)不需要new關(guān)鍵字,但是你可以根據(jù)需要使用它。無論是否使用new運(yùn)算符,它都將返回相同的對(duì)象。
最后的總結(jié)
使用對(duì)象文字語法可以輕松地構(gòu)建對(duì)象。
JavaScript提供了兩種創(chuàng)新的方式來創(chuàng)建面向?qū)ο蟮膶?duì)象。一種是使用原型對(duì)象共享常見行為。對(duì)象從其他對(duì)象繼承。類提供了一種很好的語法來創(chuàng)建此類對(duì)象。
另一種選擇是,定義的對(duì)象是使用Factory函數(shù)的閉包的集合。
謝謝你的閱讀,祝編程愉快!
學(xué)習(xí)更多技能
請(qǐng)點(diǎn)擊下方公眾號(hào)
![]()

