当前位置: 首页 > 编程日记 > 正文

JavaScript创建对象–如何在JS中定义对象

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/

相关文章:

MyBatis中#{}和${}的区别

------------------------siwuxie095 MyBatis 中 #{} 和 ${} 的区别 1、在 MyBatis 的映射配置文件中,动态传递参数有两种方式: (1)#{} 占位符 (2)${} 拼接符 2、#{} 和 ${} 的区别 (1&#xff…

十进制字符串转十六进制字符串

NSString *colorStr[self.model.sclass_color substringFromIndex:1]; unsigned long cor strtoul([colorStr UTF8String],0,16);

gi克隆github文件_如何构建GitHub文件搜索功能的克隆

gi克隆github文件In this article, we will build a project that mimics the lesser known but awesome file search functionality provided by GitHub.在本文中,我们将构建一个项目,该项目模仿GitHub提供的鲜为人知但功能强大的文件搜索功能。 To se…

ipython --pandas

d定义: pandas是一个强大的Python数据分析的工具包。 pandas是基于NumPy构建的。 安装方法: pip install pandas import pandas as pd pandas的主要功能 具备对其功能的数据结构DataFrame、Series 集成时间序列功能 提供丰富的数学运算和操作 灵活处理缺失数据 Series 定义:Ser…

玩转Android之二维码生成与识别

二维码,我们也称作QRCode,QR表示quick response即快速响应,在很多App中我们都能见到二维码的身影,最常见的莫过于微信了。那么今天我们就来看看怎么样在我们自己的App中集成二维码的扫描与生成功能。OK,废话不多说&…

属性字符串(富文本)的使用

改变字符串中某些字符串字体的颜色 NSMutableAttributedString *attrStr[[NSMutableAttributedString alloc] initWithString:str]; [attrStr addAttribute:NSForegroundColorAttributeName value:kUIColorFromRGB(0xb2151c) range:[str rangeOfString:[NSString stringWith…

如何使用create-react-app在本地设置HTTPS

Running HTTPS in development is helpful when you need to consume an API that is also serving requests via HTTPS. 当您需要使用同时通过HTTPS服务请求的API时,在开发中运行HTTPS会很有帮助。 In this article, we will be setting up HTTPS in development …

Swift强制解析

IDE:Xcode Version7.3.1 Swift中"数据类型?"表示这是可选类型,即 某个常量或者变量可能是一个类型,也可能什么都没有,不确定它是否有值,也许会是nil。 比如: let num1 “123” let num2 Int(number1) pri…

rfc6455 WebSockets

https://tools.ietf.org/html/rfc6455 转载于:https://www.cnblogs.com/cheungxiongwei/p/8385719.html

2020-mb面试指南_2020年最佳代码面试准备平台

2020-mb面试指南Software developer interviews are rapidly evolving. Years ago, mastering data structures and common algorithms was enough to ace an interview and get a job. Today though, employers want candidates with real-world experience and skills. 软件开…

设计模式学习笔记(一)之工厂模式、单例模式

一、工厂模式 (1)简单工厂模式: 1 public interface IProduct { 2 3 public void saleProduct(); 4 5 } 创建一个产品接口,有一个卖产品的方法。 1 public class ProductA implements IProduct{ 2 3 public void saleProduct(){ 4 Sy…

iOS使用支付宝支付步骤

开发平台 (http://open.alipay.com/index.htm(这个里面找不到sdk) 需要进入下面的链接) 使用支付宝进行一个完整的支付功能,大致有以下步骤: 1>先与支付宝签约,获得商户ID(partner)和账号ID&#xff08…

heroku_了解如何使用Heroku部署全栈Web应用程序

herokuBuilding a full stack web app is no mean feat. Learning to deploy one to production so that you can share it with the world can add an additional layer of complexity.构建全栈式Web应用程序绝非易事。 学习将其部署到生产环境中,以便您可以与世界…

SpringMVC学习手册(三)------EL和JSTL(上)

1.含义 EL: Expression Language , 表达式语言JSTL: Java Server Pages Standard Tag Library, JSP标准标签库 2.测试项目构建 2.1 复制JSTL的标准实现 复制Tomcat中webapps\examples\WEB-INF\lib下的两个jar包到新建项目目录的WEB-INF\lib下2.2 在JSP文件中使用tagli…

OpenStack Heat模板详解

Heat模板全称为heat orchestration template,简称为HOT。 1 典型Heat模板结构 heat_template_version: 2015-04-30 description:# a description of the template parameter_groups:# a declaration of input parameter groups and order parameters:# declaration …

如何从头开始构建自己的Linux Dotfiles Manager

As a new linux 🐧 user, you might realize that there are a bunch of configuration files present in your system. These special files are called "dotfiles". 作为新的Linux用户,您可能会意识到系统中存在大量配置文件。 这些特殊文件…

D3.js、HTML5、canvas 开发专题

https://www.smartdraw.com/genogram/ http://www.mamicode.com/info-detail-1163777.html D3折线图 https://www.cnblogs.com/hwaggLee/p/5073885.html js-d3画图插件 http://www.xiaomlove.com/2014/06/29/d3-js简单画图-箭头连接随机圆圈/ 连线 http://www.decemberc…

单向链表JAVA代码

//单向链表类publicclassLinkList{ //结点类 publicclassNode{ publicObject data; publicNode next; publicNode(Object obj,Node next){ this.data obj; this.next next; } } Node head; //记录…

forkjoin rxjs_如何通过吃披萨来理解RxJS运算符:zip,forkJoin和Combine

forkjoin rxjs什么是RxJS? (What is RxJS?) Reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change - Wikipedia响应式编程是一种与数据流和变更传播有关的异步编程范式 -Wikipedia RxJS is a…

SQLserver数据库操作帮助类SqlHelper

1 SqlHelper源码 using System; using System.Data; using System.Xml; using System.Data.SqlClient; using System.Collections; namespace SQL.Access {/// <summary>/// SqlServer数据访问帮助类/// </summary>public sealed class SqlHelper{#region 私有构造…

python框架之Flask基础篇(一)

一.第一个hello world程序 # codingutf-8 from flask import Flaskapp Flask(__name__)app.route(/) def hello_world():return Hello World!if __name__ __main__:app.run(debugTrue) 1.app参数的设置&#xff1a; 以下几种方式全部拿debug模式举例&#xff1a; .方式一&…

flask部署机器学习_如何开发端到端机器学习项目并使用Flask将其部署到Heroku

flask部署机器学习Theres one question I always get asked regarding Data Science:关于数据科学&#xff0c;我经常被问到一个问题&#xff1a; What is the best way to master Data Science? What will get me hired?掌握数据科学的最佳方法是什么&#xff1f; 什么会雇…

UVALive2678:Subsequence

UVALive2678:Subsequence 题目大意 给定一个数组A和一个整数S。求数组A中&#xff0c;连续且之和不小于S的连续子序列长度最小值。 要求复杂度:Ο(n) Solution 用变量L表示所选区间最左端下标&#xff0c;用变量R表示所选区间最右端下标&#xff0c;用变量sum表示所选区间的和。…

【BZOJ-3712】Fiolki LCA + 倍增 (idea题)

3712: [PA2014]Fiolki Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 303 Solved: 67[Submit][Status][Discuss]Description 化学家吉丽想要配置一种神奇的药水来拯救世界。吉丽有n种不同的液体物质&#xff0c;和n个药瓶&#xff08;均从1到n编号&#xff09;。初始时&am…

访问系统相册或调用摄像头

头文件&#xff1a;#import <MobileCoreServices/MobileCoreServices.h> 协议&#xff1a;<UINavigationControllerDelegate, UIImagePickerControllerDelegate> // 调用系统相册获取图片 - (IBAction)getImageFromAlbum:(id)sender {// 判断系统相册是否可用&…

unity镜像_通过镜像学习Unity Multiplayer Basics

unity镜像Unity is one of the most well-known and established engines for game development, and Mirror is a third-party, open source networking solution that allows you to add multiplayer to your games.Unity是最著名的游戏开发引擎之一&#xff0c;而Mirror是第…

java内存模型和线程安全

转载于:https://www.cnblogs.com/Michael2397/p/8397451.html

测试,发布,质量保障,用户体验

1.在实际项目中何时开始设计用户体验&#xff1a;用户的第一印象&#xff1b;从用户的角度考虑问题&#xff1b;软件啊服务始终要记住用户的选择&#xff1b;短期刺激和长期影响 2.测试经验交流&#xff1a;基本名词解释及分类&#xff1b;按测试设计的方法分类&#xff1b;按测…

UIImage存为本地文件与UIImage转换为NSData

UIImage *image"XXX"; //png格式 NSData *imagedataUIImagePNGRepresentation(image); //JEPG格式 //NSData *imagedataUIImageJEPGRepresentation(image); NSArray*pathsNSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES); NSString …

如何在JavaScript中实现链接列表

If you are learning data structures, a linked list is one data structure you should know. If you do not really understand it or how it is implemented in JavaScript, this article is here to help you. 如果您正在学习数据结构&#xff0c;则链表是您应该知道的一种…