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

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

