在本文中,我们将介绍基本的 JavaScript 对象语法,并重新审视我们在课程前面已经看到的一些 JavaScript 功能,重申您已经处理过的许多功能都是对象这一事实。
先决条件: | 基本的计算机知识,对HTML和CSS的基本理解,熟悉JavaScript基础知识(请参阅第一步和构建块)。 |
目的: | 了解在 JavaScript 中使用对象的基础知识:创建对象、访问和修改对象属性以及使用构造函数。 |
对象基础知识
对象是相关数据和/或功能的集合。这些通常由几个变量和函数组成(当它们位于对象内部时,称为属性和方法)。让我们通过一个示例来了解它们的外观。
首先,创建我们的oojs.html文件的本地副本。这包含很少 - 一个<脚本>元素,供我们将源代码写入其中。我们将以此为基础来探索基本对象语法。在使用此示例时,您应该打开开发人员工具 JavaScript 控制台,并准备好键入某些命令。
与JavaScript中的许多事情一样,创建对象通常从定义和初始化变量开始。尝试在文件中已有的 JavaScript 代码下方输入以下行,然后保存并刷新:
const person = {};
复制到剪贴板
现在打开浏览器的 JavaScript 控制台,进入它,然后按 /。您应获得类似于以下行之一的结果:person
EnterReturn
[object Object]
Object { }
{ }
复制到剪贴板
恭喜,您刚刚创建了第一个对象。工作完成!但这是一个空的物体,所以我们不能真正用它做很多事情。让我们更新文件中的 JavaScript 对象,如下所示:
const person = {
name: ['Bob', 'Smith'],
age: 32,
bio: function() {
console.log(`${this.name[0]} ${this.name[1]} is ${this.age} years old.`);
},
introduceSelf: function() {
console.log(`Hi! I'm ${this.name[0]}.`);
}
};
复制到剪贴板
保存并刷新后,请尝试在浏览器 devtools 上的 JavaScript 控制台中输入以下一些内容:
person.name
person.name[0]
person.age
person.bio()
person.introduceSelf()
复制到剪贴板
现在,您的对象中已经有了一些数据和功能,现在可以使用一些漂亮的简单语法访问它们!
这到底是怎么回事呢?好吧,一个对象由多个成员组成,每个成员都有一个名称(例如 和更高版本),以及一个值(例如 和 )。每个名称/值对必须用逗号分隔,每种情况下的名称和值都用冒号分隔。语法始终遵循以下模式:name
age
['Bob', 'Smith']
32
const objectName = {
member1Name: member1Value,
member2Name: member2Value,
member3Name: member3Value
};
复制到剪贴板
对象成员的值几乎可以是任何东西 - 在我们的人对象中,我们有一个数字,一个数组和两个函数。前两项是数据项,称为对象的属性。最后两项是允许对象对该数据执行某些操作的函数,称为对象的方法。
当对象的成员是函数时,有一个更简单的语法。而不是我们可以写.喜欢这个:bio: function()
bio()
const person = {
name: ['Bob', 'Smith'],
age: 32,
bio() {
console.log(`${this.name[0]} ${this.name[1]} is ${this.age} years old.`);
},
introduceSelf() {
console.log(`Hi! I'm ${this.name[0]}.`);
}
};
复制到剪贴板
从现在开始,我们将使用这种较短的语法。
像这样的对象被称为对象文字 - 我们已经从字面上写出了对象内容,因为我们来创建它。这与从类实例化的对象相比是不同的,我们稍后将介绍这些对象。
当您想要以某种方式传输一系列结构化的相关数据项时,例如,向服务器发送要放入数据库的请求时,使用对象文本创建对象是很常见的。发送单个对象比单独发送多个项目要高效得多,并且当您想要按名称标识单个项目时,它比数组更容易使用。
点表示法
在上面,您使用点表示法访问了对象的属性和方法。对象名称(人)充当命名空间 - 必须首先输入它才能访问对象内的任何内容。接下来,你写一个点,然后写一个你想访问的项——这可以是一个简单的属性的名称,一个数组属性的一个项目,或者是对对象的某个方法的调用,例如:
person.age
person.bio()
复制到剪贴板
对象作为对象属性
对象属性本身可以是对象。例如,尝试将成员从name
name: ['Bob', 'Smith'],
复制到剪贴板
自
name : {
first: 'Bob',
last: 'Smith'
},
复制到剪贴板
要访问这些项目,您只需将额外的步骤链接到末尾,并用另一个点。在 JS 控制台中尝试以下操作:
person.name.first
person.name.last
复制到剪贴板
如果这样做,则还需要遍历方法代码并更改
name[0]
name[1]
复制到剪贴板
自
name.first
name.last
复制到剪贴板
否则,您的方法将不再有效。
括号表示法
还有另一种访问对象属性的方法 — 使用括号表示法。而不是使用这些:
person.age
person.name.first
复制到剪贴板
您可以使用
person['age']
person['name']['first']
复制到剪贴板
这看起来与您访问数组中项目的方式非常相似,并且基本上是相同的 - 您使用的是与每个成员的值关联的名称,而不是使用索引号来选择项目。难怪对象有时被称为关联数组 - 它们将字符串映射到值的方式与数组将数字映射到值的方式相同。
设置对象成员
到目前为止,我们只研究了检索(或获取)对象成员 - 您还可以通过声明要设置的成员(使用点或括号表示法)来设置(更新)对象成员的值,如下所示:
person.age = 45;
person['name']['last'] = 'Cratchit';
复制到剪贴板
尝试输入上面的行,然后再次让成员查看他们是如何变化的,如下所示:
person.age
person['name']['last']
复制到剪贴板
设置成员不仅仅停留在更新现有属性和方法的值上;您还可以创建全新的成员。在 JS 控制台中尝试以下操作:
person['eyes'] = 'hazel';
person.farewell = function() {
console.log('Bye everybody!');
}
复制到剪贴板
您现在可以测试您的新成员:
person['eyes']
person.farewell()
复制到剪贴板
括号表示法的一个有用方面是,它不仅可以动态地设置成员值,还可以用于设置成员名称。假设我们希望用户能够通过在两个文本输入中键入成员名称和值,在其人员数据中存储自定义值类型。我们可以得到这样的值:
const myDataName = nameInput.value;
const myDataValue = nameValue.value;
复制到剪贴板
然后,我们可以将此新成员名称和值添加到对象中,如下所示:person
person[myDataName] = myDataValue;
复制到剪贴板
若要对此进行测试,请尝试将以下行添加到代码中,位于对象的右大括号下方:person
const myDataName = 'height';
const myDataValue = '1.75m';
person[myDataName] = myDataValue;
复制到剪贴板
现在尝试保存和刷新,并在文本输入中输入以下内容:
person.height
复制到剪贴板
使用点表示法无法使用上述方法向对象添加属性,点表示法只能接受文本成员名称,而不能接受指向名称的变量值。
什么是“这个”?
您可能已经注意到我们的方法中有一些奇怪的东西。例如,看看这个:
introduceSelf() {
console.log(`Hi! I'm ${this.name[0]}.`);
}
复制到剪贴板
您可能想知道“这”是什么。关键字是指正在其中编写代码的当前对象 — 因此在本例中等效于 。那么为什么不直接写呢?this
this
person
person
好吧,当您只需要创建单个对象文本时,它就不那么有用了。但是,如果创建多个对象,则 允许您对创建的每个对象使用相同的方法定义。this
让我们用一对简化的 person 对象来说明我们的意思:
const person1 = {
name: 'Chris',
introduceSelf() {
console.log(`Hi! I'm ${this.name}.`);
}
}
const person2 = {
name: 'Deepti',
introduceSelf() {
console.log(`Hi! I'm ${this.name}.`);
}
}
复制到剪贴板
在这种情况下,输出“嗨!我是克里斯。 另一方面输出“嗨!我是Deepti.“,即使该方法的代码在每种情况下都完全相同。当您手动写出对象文本时,这并不是很有用,但是当我们开始使用构造函数从单个对象定义创建多个对象时,这将是必不可少的,这就是下一节的主题。person1.introduceSelf()
person2.introduceSelf()
构造函数简介
当您只需要创建一个对象时,使用对象文本是可以的,但是如果您必须创建多个对象,如上一节所述,则它们严重不足。我们必须为我们创建的每个对象写出相同的代码,如果我们想更改对象的某些属性 - 例如添加属性 - 那么我们必须记住更新每个对象。height
我们想要一种方法来定义对象的“形状”——方法集和它可以拥有的属性——然后创建任意数量的对象,只需更新不同属性的值。
这个的第一个版本只是一个函数:
function createPerson(name) {
const obj = {};
obj.name = name;
obj.introduceSelf = function() {
console.log(`Hi! I'm ${this.name}.`);
}
return obj;
}
复制到剪贴板
此函数每次调用它时都会创建并返回一个新对象。该对象将有两个成员:
- 属性
name
- 一种方法 。
introduceSelf()
请注意,需要一个参数来设置属性的值,但对于使用此函数创建的所有对象,该方法的值将是相同的。这是创建对象的一种非常常见的模式。createPerson()
name
name
introduceSelf()
现在,我们可以根据需要创建任意数量的对象,重用定义:
const salva = createPerson('Salva');
salva.name;
salva.introduceSelf();
const frankie = createPerson('Frankie');
frankie.name;
frankie.introduceSelf();
复制到剪贴板
这工作正常,但有点冗长:我们必须创建一个空对象,初始化它,然后返回它。更好的方法是使用构造函数。构造函数只是一个使用 new 关键字调用的函数。调用构造函数时,它将:
- 创建新对象
- 绑定到新对象,以便您可以在构造函数代码中引用
this
this
- 在构造函数中运行代码
- 返回新对象。
按照惯例,构造函数以大写字母开头,并以其创建的对象类型命名。因此,我们可以像这样重写我们的例子:
function Person(name) {
this.name = name;
this.introduceSelf = function() {
console.log(`Hi! I'm ${this.name}.`);
}
}
复制到剪贴板
要作为构造函数调用,我们使用:Person()
new
const salva = new Person('Salva');
salva.name;
salva.introduceSelf();
const frankie = new Person('Frankie');
frankie.name;
frankie.introduceSelf();
复制到剪贴板
您一直在使用对象
当您浏览这些示例时,您可能一直认为您一直在使用的点表示法非常熟悉。那是因为你在整个课程中一直在使用它!每次我们研究一个使用内置浏览器API或JavaScript对象的示例时,我们一直在使用对象,因为这些功能是使用与我们在这里看到的完全相同类型的对象结构构建的,尽管这些结构比我们自己的基本自定义示例更复杂。
因此,当您使用字符串方法时,例如:
myString.split(',');
复制到剪贴板
您正在使用 String 对象上可用的方法。每次在代码中创建字符串时,该字符串都会自动创建为 的实例,因此具有几个可用的常用方法和属性。String
当您使用如下行访问文档对象模型时:
const myDiv = document.createElement('div');
const myVideo = document.querySelector('video');
复制到剪贴板
您正在使用文档对象上可用的方法。对于加载的每个网页,都会创建一个名为 的实例,该实例表示整个页面的结构、内容和其他功能(如 URL)。同样,这意味着它具有几种可用的常用方法和属性。Document
document
几乎所有其他内置对象或 API 也是如此 - 数组、数学等。
请注意,内置对象和 API 并不总是自动创建对象实例。例如,通知 API(允许现代浏览器触发系统通知)要求您使用要触发的每个通知的构造函数实例化新的对象实例。尝试在 JavaScript 控制台中输入以下内容:
const myNotification = new Notification('Hello!');
总结
恭喜你,你已经到达了我们第一篇JS对象文章的结尾 - 你现在应该对如何使用JavaScript中的对象有了一个很好的了解 - 包括创建你自己的简单对象。您还应该意识到,对象作为存储相关数据和功能的结构非常有用 - 如果您尝试将对象中的所有属性和方法作为单独的变量和函数进行跟踪,那将是低效和令人沮丧的,并且我们将面临与其他具有相同名称的变量和函数发生冲突的风险。对象让我们将信息安全地锁在自己的包装中,免受伤害。person