《JavaScript启示录》——第1章 JavaScript对象 1.1创建对象
发布日期:2021-08-29 16:14:36 浏览次数:0 分类:技术文章

本节书摘来自异步社区《JavaScript启示录》一书中的第1章,第1.1节,作者:【美】Cody Lindley著,更多章节内容可以访问云栖社区“异步社区”公众号查看

第1章 JavaScript对象

1.1 创建对象

在JavaScript中,对象为“王”:JavaScript里的几乎所有东西都是对象或者用起来像对象。理解了对象,就能够理解JavaScript。因此,让我们来查看一下JavaScript中的对象创建。

对象只是一组有命名值(也称为属性)集合的容器。在阅读JavaScript代码之前,让我们先来推理一下。以我自己为例,我们可以用简单的语言在表格中表达“cody”:
screenshot

上述表格中的“cody”一词只是一组属性名和所对应值的标签,这些属性和值构成了cody。正如表格中所看到的:我还活着,33岁,男性。

然而,JavaScript不会用表格来表达,它是用对象来表达的,就像“cody”表格中包含的那样。将上述表格转化成实际的JavaScript对象应是这样的:

<!DOCTYPE html><html lang="en"><body><script>// 创建cody对象var cody = new Object();// 为cody对象的各种属性赋值(使用点表示法)cody.living = true;cody.age = 33;cody.gender = 'male';console.log(cody); // 输出Object {living = true, age = 33, gender = 'male'}</script></body></html>

最重要的是要记住:对象只是属性的容器,每个属性都有一个名称和一个值。JavaScript采用具有命名值属性的容器(即对象)这一概念作为在JavaScript中表达值的构建块。cody对象是一个值,通过创建对象将这个值表示为JavaScript对象,给对象命名,然后将属性赋值给对象。

到目前为止,我们所讨论的cody对象只有静态信息。鉴于正在研究JavaScript编程语言,我们希望为cody对象编写代码,做一些真正有意义的事情。不然,也就只有一个类似JSON的数据库。为了使cody对象有生命力,需要添加一个属性:方法(method)。方法用于执行函数(function)。确切地讲,在JavaScript中,方法是包含Function()对象的属性,其目的是对函数内部的对象进行操作。

更新cody表格,加入getGender方法,用浅显的英语表示如下:
screenshot

用JavaScript代码表示,更新后的上述“cody”表格中的getGender方法应是这样的:

<!DOCTYPE html><html lang="en"><body><script>var cody = new Object();cody.living = true;cody.age = 33;cody.gender = 'male';cody.getGender = function(){ return cody.gender;};console.log(cody.getGender()); // 输出 'male'</script></body></html>

getGender方法是cody对象的属性,用于返回cody的其他属性值:存储在gender属性中的"male"值。必须知道的是,如果没有方法,除了用于存储静态属性以外,对象就没有其他太多用途。

截至目前,我们讨论的cody对象是一种Object()对象。通过使用调用Object()构造函数而得到的空对象创建了cody对象。将构造函数视为模板或饼干模具来生成预定义对象。对于cody对象示例,使用Object()构造函数来生成空对象,然后将它命名为cody。鉴于cody是由Object()构造函数构造出的一个对象,所以将cody称为Object()对象。大家真正需要了解的是,除了创建像cody这样简单的Object()对象外,JavaScript中的大多数值都是对象("foo"、5和true等原始值例外,但它们拥有等效包装器对象)。

由Object()构造函数创建的cody对象与通过string()构造函数创建的字符串对象没有太大的区别。为了证明其真实性,可检验和对比下面的代码:

<!DOCTYPE html><html lang="en"><body><script>var myObject = new Object(); // 生成一个Object()对象myObject['0'] = 'f';myObject['1'] = 'o';myObject['2'] = 'o';console.log(myObject); // 输出Object { 0="f", 1="o", 2="o"}var myString = new String('foo'); // 生成一个String()对象console.log(myString); // 输出foo { 0="f", 1="o", 2="o"}</script></body></html>

正如这里所显示的,myObject和myString都是对象!它们都可以有属性、继承属性,并且都由构造函数生成。包含"foo"字符串值的myString变量看似很简单,但令人惊讶的是,在其表面之下有一个对象结构。查看生成的这两个对象,你会发现这两个对象虽然在本质上是相同的,但在类型上是不同的。更重要的是,希望你开始了解,JavaScript是使用对象来表示值的。

注意

看到字符串值采用"foo"对象形式,你可能会觉得很奇怪,因为通常字符串在JavaScript中被表示为原始值(如var myString = 'foo';)。我在这里特地用一个字符串对象值来强调所有的东西都可以是对象,包括通常不将其视为对象的值(即字符串、数字、布尔值)。同时,我认为这有助于解释为什么有些人说JavaScript中的所有东西都可以是一个对象。
JavaScript将String()和Object()构造函数作为其自身的语言,以便使String()对象和Object()对象的创建变得简单。但是作为JavaScript程序员,也可以创建同样强大的构造函数。如下代码,定义了一个非原生的自定义Person()构造函数,以便用它创建people对象。

<!DOCTYPE html><html lang="en"><body><script>// 定义Person构造函数,以便稍后创建自定义的Person()对象vaPerson = function (living, age, gender) {    this.living = living;    this.age = age;    this.gender = gender;    this.getGender = function () { return this.gender; };};// 实例化Person对象,并将它保存到cody变量var cody = new Person(true, 33, 'male');console.log(cody);/* 下面的String()构造函数由JavaScript自身所定义,有同样的模式。因为string构造函数是JavaScript内置的,获取字符串所要做的就是将它实例化,但无论是用原生的String()还是用户自定义的构造函数Person(),模式都是一样的*/// 实例化一个String对象,并保存到myString变量var myString = new String('foo');console.log(myString);</script></body></html>

用户自定义的Person()构造函数可以生成person对象,就像原生String()构造函数可以生成字符串对象一样。Person()构造函数的能力和延展性并不比原生String()构造函数或JavaScript中的其他原生构造函数差。

还记得我们开始看到的cody对象是如何从Object()生成的吗?重要的是要注意,在上个代码示例中的Object()构造函数和new Person()构造函数可以产生相同的结果。两者都可以生成具有相同属性和属性方法的相同对象。查看下面两段代码,结果表明,尽管生成方式不同,codyA和codyB却拥有相同的对象值。

<!DOCTYPE html><html lang="en"><body><script>// 使用Object()构造函数创建codyA对象var codyA = new Object();codyA.living = true;codyA.age = 33;codyA.gender = 'male';codyA.getGender = function () { return codyA.gender; };console.log(codyA); // 输出Object {living=true, age=33, gender="male", ...}/*  下面创建了同样的cody对象,但不是使用原生的Object()构造函数创建一次性的cody对象,首先定义自己的Person()构造函数来创建cody对象(或者其他任意Person对象),然后使用”new”关键字进行实例化 */var Person = function (living, age, gender) {    this.living = living;    this.age = age;    this.gender = gender;    this.getGender = function () { return this.gender; };};// 输出Object {living=true, age=33, gender="male", ...}var codyB = new Person(true, 33, 'male');console.log(codyB); </script></body></html>

codyA和codyB对象之间的主要区别不在于对象本身,而是在于生成对象的构造函数。codyA对象是使用Object()构造函数实例来产生的。Person()构造函数创建了codyB,但也可以把Person()构造函数当成一个强大的、集中定义的对象“工厂”,用于创建更多的Person()对象。为自定义对象创建自定义构造函数的同时,也为Person()实例创建了原型继承。

这两个方案都能够创建相同的复杂对象。这两个模式最常用于构造对象。

JavaScript实际上是一种预包装若干原生对象构造函数的语言。这些构造函数用于生成一些表达特定类型值(如数字、字符串、函数、对象、数组等)的复杂对象,同样,也可以通过Function()对象创建自定义的对象构造函数(例如Person())。不管是否是用于创建对象的模式,产生的最终结果通常都是创建一个复杂的对象。

理解对象的创建、本质、用法以及其原始等价代码是本书其余部分的重点。

上一篇:《敏捷软件开发:原则、模式与实践(C#版.修订版)》—第1章1.4节参考文献
下一篇:《树莓派Python编程入门与实战(第2版)》——3.9 小结