Objects are the main unit of encapsulation in Object-Oriented Programming. In this article, I will describe several ways to build objects in JavaScript. They are:

对象是面向对象编程中封装的主要单元。 在本文中,我将介绍几种使用JavaScript构建对象的方法。 他们是:

  • Object literal对象文字
  • Object.create()Object.create()
  • Classes班级
  • Factory functions工厂功能

对象文字 (Object Literal)

First, we need to make a distinction between data structures and object-oriented objects. Data structures have public data and no behavior. That means they have no methods.

首先,我们需要区分数据结构和面向对象的对象。 数据结构具有公共数据,没有任何行为。 那意味着他们没有方法。

We can easily create such objects using the object literal syntax. It looks like this:

我们可以使用对象文字语法轻松创建此类对象。 看起来像这样:

const product = {name: 'apple',category: 'fruits',price: 1.99
}console.log(product);

Objects in JavaScript are dynamic collections of key-value pairs. The key is always a string and has to be unique in the collection. The value can a primitive, an object, or even a function.

JavaScript中的对象是键值对的动态集合。 密钥始终是字符串,并且在集合中必须唯一。 该值可以是基元,对象甚至函数。

We can access a property using the dot or the square notation.

我们可以使用点或正方形符号访问属性。

console.log(product.name);
//"apple"console.log(product["name"]);
//"apple"

Here is an example where the value is another object.

这是一个值是另一个对象的示例。

const product = {name: 'apple',category: 'fruits',price: 1.99,nutrients : {carbs: 0.95,fats: 0.3,protein: 0.2}
}

The value of the carbs property is a new object. Here is how we can access the carbs property.

carbs属性的值是一个新对象。 这是我们如何访问carbs属性的方法。

console.log(product.nutrients.carbs);
//0.95

简写属性名称 (Shorthand Property Names)

Consider the case where we have the values of our properties stored in variables.

考虑将属性值存储在变量中的情况。

const name = 'apple';
const category = 'fruits';
const price = 1.99;
const product = {name: name,category: category,price: price
}

JavaScript supports what is called the shorthand property names. It allows us to create an object using just the name of the variable. It will create a property with the same name. The next object literal is equivalent to the previous one.

JavaScript支持所谓的速记属性名称。 它允许我们仅使用变量名来创建对象。 它将创建一个具有相同名称的属性。 下一个对象文字与上一个相同。

const name = 'apple';
const category = 'fruits';
const price = 1.99;
const product = {name,category,price
}

对象创建 (Object.create)

Next, let's look at how to implement objects with behavior, object-oriented objects.

接下来,让我们看看如何使用行为,面向对象的对象来实现对象。

JavaScript has what is called the prototype system that allows sharing behavior between objects. The main idea is to create an object called the prototype with a common behavior and then use it when creating new objects.

JavaScript具有所谓的原型系统,该系统允许对象之间共享行为。 主要思想是创建一个具有常见行为的对象称为原型,然后在创建新对象时使用它。

The prototype system allows us to create objects that inherit behavior from other objects.

原型系统允许我们创建从其他对象继承行为的对象。

Let’s create a prototype object that allows us to add products and get the total price from a shopping cart.

让我们创建一个原型对象,使我们能够添加产品并从购物车中获得总价。

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);}
}

Notice that this time the value of the property addProduct is a function. We can also write the previous object using a shorter form called the shorthand method syntax.

请注意,这次属性addProduct的值是一个函数。 我们还可以使用称为“简写方法”语法的较短形式来编写先前的对象。

const cartPrototype = {addProduct(product){/*code*/},getTotalPrice(){/*code*/}
}

The cartPrototype is the prototype object that keeps the common behavior represented by two methods, addProduct and getTotalPrice. It can be used to build other objects inheriting this behavior.

cartPrototype是原型对象,该对象保留由两种方法addProductgetTotalPrice表示的常见行为。 它可用于构建继承此行为的其他对象。

const cart = Object.create(cartPrototype);
cart.addProduct({name: 'orange', price: 1.25});
cart.addProduct({name: 'lemon', price: 1.75});console.log(cart.getTotalPrice());
//3

The cart object has cartPrototype as its prototype. It inherits the behavior from it. cart has a hidden property that points to the prototype object.

cart对象具有cartPrototype作为其原型。 它从中继承行为。 cart具有指向原型对象的隐藏属性。

When we use a method on an object, that method is first searched on the object itself rather than on its prototype.

当我们在对象上使用方法时,首先在对象本身而不是其原型上搜索该方法。

这个 (this)

Note that we are using a special keyword called this to access and modify the data on the object.

请注意,我们正在使用一个名为this的特殊关键字来访问和修改对象上的数据。

Remember that functions are independent units of behavior in JavaScript. They are not necessarily part of an object. When they are, we need to have a reference that allows the function to access other members on the same object. this is the function context. It gives access to other properties.

请记住,函数是JavaScript中行为的独立单元。 它们不一定是对象的一部分。 当它们存在时,我们需要有一个引用,该引用允许该函数访问同一对象上的其他成员。 this是函数上下文。 它提供对其他属性的访问。

数据 (Data)

You may wonder why we haven’t defined and initialized the products property on the prototype object itself.

您可能想知道为什么我们没有在原型对象本身上定义和初始化products属性。

We shouldn't do that. Prototypes should be used to share behavior, not data. Sharing data will lead to having the same products on several cart objects. Consider the code below:

我们不应该那样做。 原型应用于共享行为,而不是数据。 共享数据将导致在多个购物车对象上拥有相同的产品。 考虑下面的代码:

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

Both the cart1 and cart2 objects inheriting the common behavior from the cartPrototype also share the same data. We don’t want that. Prototypes should be used to share behavior, not data.

无论是cart1cart2对象继承自共同行为cartPrototype也有着相同的数据。 我们不想要那个。 原型应用于共享行为,而不是数据。

类 (Class)

The prototype system is not a common way of building objects. Developers are more familiar with building objects out of classes.

原型系统不是构建对象的常用方法。 开发人员更熟悉在类之外构建对象。

The class syntax allows a more familiar way of creating objects sharing a common behavior. It still creates the same prototype behind the scene but the syntax is clearer and we also avoid the previous data-related issue. The class offers a specific place to define the data distinct for each object.

类语法允许使用更熟悉的方式来创建共享共同行为的对象。 它仍然在后台创建相同的原型,但是语法更清晰,并且我们还避免了以前的数据相关问题。 该类提供了一个特定的位置来定义每个对象不同的数据。

Here is the same object created using the class sugar syntax:

这是使用类sugar语法创建的同一对象:

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

Notice that the class has a constructor method that initialized that data distinct for each new object. The data in the constructor is not shared between instances. In order to create a new instance, we use the new keyword.

注意,该类具有一个构造函数方法,该方法针对每个新对象初始化该数据。 实例之间不共享构造函数中的数据。 为了创建一个新实例,我们使用new关键字。

I think the class syntax is more clear and familiar to most developers. Nevertheless, it does a similar thing, it creates a prototype with all the methods and uses it to define new objects. The prototype can be accessed with Cart.prototype.

我认为对于大多数开发人员而言,类语法更加清晰和熟悉。 但是,它做类似的事情,它使用所有方法创建一个原型,并使用它来定义新对象。 可以使用Cart.prototype访问原型。

It turns out that the prototype system is flexible enough to allow the class syntax. So the class system can be simulated using the prototype system.

事实证明,原型系统足够灵活以允许类语法。 因此,可以使用原型系统模拟类系统。

私人财产 (Private Properties)

The only thing is that the products property on the new object is public by default.

唯一的事情是,默认情况下,新对象上的products属性是公共的。

console.log(cart.products);
//[{name: "orange", price: 1.25}
// {name: "lemon", price: 1.75}]

We can make it private using the hash # prefix.

我们可以使用#前缀将其设为私有。

Private properties are declared with #name syntax. # is a part of the property name itself and should be used for declaring and accessing the property. Here is an example of declaring products as a private property:

私有属性使用#name语法声明。 #是属性名称本身的一部分,应用于声明和访问属性。 以下是将products声明为私有财产的示例:

class Cart{#productsconstructor(){this.#products = [];}addProduct(product){this.#products.push(product);}getTotalPrice(){return this.#products.reduce((total, p) => total + p.price, 0);}
}console.log(cart.#products);
//Uncaught SyntaxError: Private field '#products' must be declared in an enclosing class

工厂功能 (Factory Functions)

Another option is to create objects as collections of closures.

另一种选择是将对象创建为闭包的集合。

Closure is the ability of a function to access variables and parameters from the other function even after the outer function has executed. Take a look at the cart object built with what is called a factory function.

闭包是一个函数即使在外部函数执行后也可以从另一个函数访问变量和参数的能力。 看一下使用工厂函数构建的cart对象。

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 and getTotalPrice are two inner functions accessing the variable products from their parent. They have access to the products variable event after the parent Cart has executed. addProduct and getTotalPrice are two closures sharing the same private variable.

addProductgetTotalPrice是两个内部函数,用于从其父级访问变量products 。 他们在执行父Cart后可以访问products变量事件。 addProductgetTotalPrice是两个共享同一私有变量的闭包。

Cart is a factory function.

Cart是出厂功能。

The new object cart created with the factory function has the products variable private. It cannot be accessed from the outside.

使用工厂功能创建的新对象cart具有products变量private。 不能从外部访问它。

console.log(cart.products);
//undefined

Factory functions don’t need the new keyword but you can use it if you want. It will return the same object no matter if you use it or not.

工厂函数不需要new关键字,但是您可以根据需要使用它。 无论是否使用它,它都会返回相同的对象。

回顾 (Recap)

Usually, we work with two types of objects, data structures that have public data and no behavior and object-oriented objects that have private data and public behavior.

通常,我们使用两种类型的对象:具有公共数据但没有行为的数据结构和具有私有数据和公共行为的面向对象的对象。

Data structures can be easily built using the object literal syntax.

使用对象文字语法可以轻松构建数据结构。

JavaScript offers two innovative ways of creating object-oriented objects. The first is using a prototype object to share the common behavior. Objects inherit from other objects. Classes offer a nice sugar syntax to create such objects.

JavaScript提供了两种创新的方式来创建面向对象的对象。 第一种是使用原型对象共享常见行为。 对象从其他对象继承。 类提供了很好的糖语法来创建此类对象。

The other option is to define objects are collections of closures.

另一种选择是将对象定义为闭包的集合。

For more on closures and function programming techniques check out my book series Functional Programming with JavaScript and React.

有关闭包和函数编程技术的更多信息,请参阅我的书系列《 使用JavaScript和React进行函数式编程》 。

The Functional Programming in JavaScript book is coming out.

JavaScript中 功能编程》 一书即将出版。

翻译自: https://www.freecodecamp.org/news/javascript-create-object-how-to-define-objects-in-js/

JavaScript创建对象–如何在JS中定义对象相关推荐

  1. Vue中向js中传递参数并在js中定义对象并转换参数

    场景 有下面这种主从表结构 上面的信息是主表的信息,下面是从表的信息. 在Vue中将页面的信息传递到js的方法中,在js方法中将参数进行转换使其与后台接收的参数相匹配. 注: 博客: https:// ...

  2. JavaScript 随机数 – 如何在 JS 中生成随机数

    在使用 JavaScript 程序时,有时您可能需要生成一个随机数. 例如,您可能希望在开发 JavaScript 游戏(例如猜数字游戏)时生成一个随机数. JavaScript 有许多用于处理数字和 ...

  3. 初学JavaScript:js中的对象(对象+原型对象)

    文章目录 js对象详解 1.创建对象 字面量模式创建对象 构造函数模式创建对象 2.访问对象 访问属性 访问方法 3.遍历对象中的属性和属性值 4.往对象中新添属性 5.删除对象中的属性 6.Obje ...

  4. JavaScript中定义对象的几种方式

    JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下5种方式(附加改进方式): 1.基于已有对象扩充其属性和方法 2.工厂方式 3.构造函数方式 4.原型(&q ...

  5. Js中Reflect对象

    Js中Reflect对象 Reflect是ES6起JavaScript内置的对象,提供拦截JavaScript操作的方法,这些方法与Proxy对象的handlers中的方法基本相同. 描述 Refle ...

  6. js中自定义对象、json对象、json字符串、普通js对象 --js学习那本书上的

    4.7 自定义对象 JS除了内置对象之外,还允许我们程序自己定义属于我们自己的对象,在JS中自定义对象的方式有2种:通过构造器创建对象,通过初始化器创建对象. 4.7.1 构造器创建对象(原生JS对象 ...

  7. js中自定义对象、json对象、json字符串、普通js对象

    4.7 自定义对象 JS除了内置对象之外,还允许我们程序自己定义属于我们自己的对象,在JS中自定义对象的方式有2种:通过构造器创建对象,通过初始化器创建对象. 4.7.1 构造器创建对象(原生JS对象 ...

  8. Js中Proxy对象

    Js中Proxy对象 Proxy对象用于定义基本操作的自定义行为,例如属性查找.赋值.枚举.函数调用等. 语法 const proxy = new Proxy(target, handler); ta ...

  9. Js中Symbol对象

    Js中Symbol对象 ES6引入了一种新的基本数据类型Symbol,表示独一无二的值,最大的用法是用来定义对象的唯一属性名,Symbol()函数会返回symbol类型的值,该类型具有静态属性和静态方 ...

最新文章

  1. 独家 | 如何利用大规模无监督数据建立高水平特征?
  2. 系统管理员设置了系统策略 禁止进行此安装的修改办法
  3. 关于jdbc连接mysql的问题bug
  4. 语音识别 | 从入门到精通的高效选择!
  5. Oracle bpm实现oa,谈谈BPM、工作流引擎与OA的关系
  6. VMware安装Windows Server 2003提示Operating System not found
  7. flashFxp连接不上服务器。
  8. 华为云学院 华为物联网平台
  9. 淘宝/天猫、1688、京东按图搜索淘宝商品(拍立淘)API接口
  10. cisco 模拟器安装及交换机的基本配置实验心得_软考网络工程师级配置题总结 | 交换机配置、路由器配置、广域网接入配置、L2TP配置、IPSec配置、PIX防火墙配置...
  11. CSDN发博客上传照片失败问题解决方案
  12. tf-faster-rcnn训练报错: Loaded runtime CuDNN library: 7.0.5 but source was compiled with: 7.1.4.r-rcn
  13. 第5.2节 应用工具包得到幅相加权
  14. 解释计算机概念BIOS,电脑BIOS的小常识
  15. ant-design-vue select 可搜索下拉加载更多
  16. 商品详情页系统架构-笔记4-商品详情页多级缓存
  17. 哪款蓝牙耳机降噪效果比较强?适合当做520礼物的蓝牙耳机推荐
  18. Leetcode题库(数据库合集)
  19. 百度地图Mark 点自动点击 触发mark点击事件
  20. python中字典列表元组_Python中的列表和元组

热门文章

  1. 【web】将一个jar包更改成war包
  2. 《深入理解计算机系统》学习心得二:关于show-bytes的 学习
  3. 扫描服务器端口信息工具,服务器端口扫描工具
  4. iOS 关于手机权限的检查与获取
  5. iOS12-crash错误-reason: 'UITableView failed to obtain a cell from its dataSource'
  6. 绝对定位下margin的作用
  7. APP之红点提醒三个阶段
  8. php代码中使用换行及(\n或\r\n和br)的应用
  9. IO流(文件的读写)---本文的正确性有待您验证。
  10. Android UI SurfaceView的使用-绘制组合图型,并使其移动