JavaScript 基础
Document
运算符
深入数据和类型
函数进阶
原型、继承
类
浏览器存储
Web API
事件
错误处理
异步编程
网络请求
模块
练习
实例
工具与规范
软件架构模式
设计模式
对象
对象是 JavaScript
中功能最多,也是最复杂的一种类型。不用怕,这个章节只是简单地入门一下。
对象是一个储存着多个键值对的类型,键是一个对象内唯一的字符串,而值可以是任意类型任意值,键与值一一对应,通过键可以找到对应的值。
比如下面的例子定义了包含人相关信息的对象,包含了姓名和身份证两个键值对。
let person = {
name: "小明", // 姓名
"identity card": 123456789123, // 身份证件
}
在以下的例子中定义了一个有着属性与方法(一般将属性值为函数的属性称之为方法)的对象。
$$edit$$
$$jsdemo$$
let mingren = {
name: "鸣人",
height: 1.8,
eat: function () {
alert("吃拉面。")
},
fight: function () {
alert("螺旋丸。")
},
}
alert(mingren.name)
mingren.fight()
$$tip
在其他语言中也有类似对象的类型,被称为字典(dict)。
$$
定义对象
定义一个对象的语法如下:
let object = {
key: value,
key2: value2,
}
由冒号分割的键值对被放在大括号当中,每一个键值对之间用逗号分隔。
- key:键(属性名),键为字符串类型(如果属性符合变量命名规范或是可默认转换为字符串的数据值,则可省略引号),键名不能重复。
- value:值(属性值),属性值可以为任意类型。
以下是一个小例子:
let person = {
name: "鸣人",
height: 1.8,
}
- 定义了
person
对象。 person
对象中有name
、height
键,分别对应"鸣人"
与1.8
。
以下这个例子中,使用对象来组织数据明显比使用多个变量来得清晰明了。
$$edit$$
// 多个变量组织数据
let mingrenName = "鸣人"
let mingrenHeight = 1.8
let mingrenFight = function () {
alert("螺旋丸")
}
let lufeiName = "路飞"
let lufeiHeight = 1.75
let lufeiFight = function () {
alert("橡胶子弹")
}
// 使用对象组织数据
let mingren = {
name: "鸣人",
height: 1.8,
fight: function () {
alert("螺旋丸")
},
}
let lufei = {
name: "路飞",
height: 1.75,
fight: function () {
alert("橡胶子弹")
},
}
属性简写
在定义一个对象时,如果用已存的变量作为属性值,并且属性名与变量名相同的情况下则可以省略属性值。
$$jsdemo$$
$$edit$$
let name = "鸣人"
let person = {
name, // 等同于 name: name
height: 1.8,
}
alert(person.name)
获取与赋值
点操作符
只要在对象后接点操作符再接属性名即可获取属性值。
$$jsdemo$$
$$edit$$
let person = {
name: "鸣人",
height: 1.8,
}
alert(person.name)
同样的点操作符也可以修改属性值或赋新值。
$$jsdemo$$
$$edit$$
let person = {
name: "鸣人",
height: 1.8,
}
person.name = "路飞"
alert(person.name)
person.address = "木叶村"
alert(person.address)
方括号操作符
方括号操作符与点操作符类似,也可以取值与赋值。
$$jsdemo$$
$$edit$$
let person = {
name: "鸣人",
height: 1.8,
}
person["name"] = "路飞"
alert(person["name"])
点操作符与方括号操作符的区别在于:
- 点操作符的属性名必须符合变量命名规范。
- 方括号操作符可以采用任何字符串属性名(非字符串类型会被默认转成字符串)或者变量。
$$jsdemo$$
$$edit$$
let person = {
name: "鸣人",
height: 1.8,
}
person[123] = 123
person["a b"] = 456
let str = "key"
person[str] = 789
alert(person["123"]) // 123
alert(person["a b"]) // 456
alert(person[str]) // 789
// person.123 = 123 // Unexpected number
获取所有的键
Object.keys()
方法可以数组的形式返回所有给定对象的键。
$$jsdemo$$
$$edit$$
let mingren = {
name: "鸣人",
height: 1.8,
fight: function () {
alert("螺旋丸")
},
}
let keys = Object.keys(mingren)
console.log(keys) // ['name', 'height', 'fight']
获取所有的值
Object.values()
方法可以数组的形式返回所有给定对象的值。
$$jsdemo$$
$$edit$$
let mingren = {
name: "鸣人",
height: 1.8,
fight: function () {
alert("螺旋丸")
},
}
let values = Object.values(mingren)
console.log(values) // ['鸣人', 1.8, ƒ]
获取所有的键值对
Object.entries()
方法可以数组的形式返回所有给定对象的键值对。
$$jsdemo$$
$$edit$$
let mingren = {
name: "鸣人",
height: 1.8,
fight: function () {
alert("螺旋丸")
},
}
let entries = Object.entries(mingren)
console.log(entries) // [['name', '鸣人'], ['height', 1.8], ['fight', ƒ]]
for in 作用于对象
当 for in
作用于对象时,会循环对象的所有键。
$$jsdemo$$
$$edit$$
let mingren = {
name: "鸣人",
height: 1.8,
fight: function () {
alert("螺旋丸")
},
}
for (let key in mingren) {
alert(key)
alert(mingren[key])
}
$$tip
与数组不同, for of
不能作用于对象。
$$
判断属性是否存在
in
操作符可以判断对象中是否存在对应的属性。
$$jsdemo$$
$$edit$$
let mingren = {
name: "鸣人",
height: 1.8,
fight: function () {
alert("螺旋丸")
},
}
alert("name" in mingren) // true
alert("sex" in mingren) // false
删除属性
delete
操作符可以帮助我们删除对象中的属性。
$$jsdemo$$
$$edit$$
let person = {
name: "鸣人",
height: 1.8,
}
delete person.name
alert(person.name)
实例
对象最常用场景之一就是用来保存一些具有相同属性,同一类型的数据,并在之后批量处理。
$$jsdemo$$
$$edit$$
// 学生信息收集程序
let students = []
while (true) {
let name = prompt("输入同学的姓名(空为退出)")
if (!name) break
let skill = prompt("输入同学的技能(空为退出)")
if (!skill) break
students.push({
name,
skill,
})
}
alert(`共收集了${students.length}名同学的信息。`)
for (let item of students) {
alert(`${item.name}同学的技能是${item.skill}。`)
}
console.log(students)
练习
- 写一个 函数
showScore
,显示每个学生的姓名和分数,如果未及格则不显示分数。
let students = [
{
name: "佐助",
score: 98,
},
{
name: "小樱",
score: 88,
},
{
name: "鸣人",
score: 28,
},
]
showScore(students)
$$demo
<button onclick="work()">显示分数</button>
<script>
function work() {
function showScore(students) {
for (let student of students) {
if (student.score >= 60) {
alert(姓名:${student.name}\n分数:${student.score}
)
} else {
alert(姓名:${student.name}\n分数:不及格
)
}
}
}
let students = [
{
name: "佐助",
score: 98,
},
{
name: "小樱",
score: 88,
},
{
name: "鸣人",
score: 28,
},
]
showScore(students)
}
</script> $$
$$answer
$$jsdemo$$
$$edit$$
function showScore(students) {
for (let student of students) {
if (student.score >= 60) {
alert(`姓名:${student.name}\n分数:${student.score}`)
} else {
alert(`姓名:${student.name}\n分数:不及格`)
}
}
}
let students = [
{
name: "佐助",
score: 98,
},
{
name: "小樱",
score: 88,
},
{
name: "鸣人",
score: 28,
},
]
showScore(students)
$$
- 写一个函数
sum
,接收一个属性值全为数字的对象,并求出所有属性值的和。
let damages = {
悟空: 800,
贝吉塔: 660,
农夫: 5,
}
alert(sum(damages)) // 1465
$$answer
$$jsdemo$$
$$edit$$
function sum(obj) {
let values = Object.values(obj)
let total = 0
for (let value of values) {
total += value
}
return total
}
let damages = {
悟空: 800,
贝吉塔: 660,
农夫: 5,
}
alert(sum(damages)) // 1465
$$
- 写一个函数
isEmpty
,接收一个对象作为参数,如果对象为空时返回true
,否则返回false
。
let mingren = {}
alert(isEmpty(mingren)) // true
mingren.name = "鸣人"
alert(isEmpty(mingren)) // false
$$answer
$$jsdemo$$
$$edit$$
function isEmpty(obj) {
return Object.keys(obj).length === 0
}
let mingren = {}
alert(isEmpty(mingren)) // true
mingren.name = "鸣人"
alert(isEmpty(mingren)) // false
$$
- 写一个函数
highestFreq
,接收一个字符数组作为参数,返回出现频率最高的字符,比如:
let array = ["B", "B", "C", "I", "G", "A", "E", "E", "C", "C"]
alert(highestFreq(array)) // C
$$answer
$$jsdemo$$
$$edit$$
function highestFreq(array) {
let mark = {}
// 循环数组
// 用对象标记出现的次数
// 键为字母,值为出现的次数
for (let letter of array) {
if (letter in mark) {
// 已经出现过,次数加 1
mark[letter]++
} else {
// 第一次出现,记为一次
mark[letter] = 1
}
}
// 最高频的字母
let highestLetter
// 最大出现的次数
let maxCount = 0
for (let letter in mark) {
if (mark[letter] > maxCount) {
maxCount = mark[letter]
highestLetter = letter
}
}
return highestLetter
}
let array = ["B", "B", "C", "I", "G", "A", "E", "E", "C", "C"]
alert(highestFreq(array)) // C
$$
- 通过以下题库,完成首都问答的程序。
// 题库
let items = [
{
question: "中国的首都是?",
answers: ["上海", "广州", "北京"],
rightIdx: 2,
},
{
question: "美国的首都是?",
answers: ["纽约", "华盛顿", "伦敦"],
rightIdx: 1,
},
{
question: "新加坡的首都是?",
answers: ["后港", "新加坡市", "裕华"],
rightIdx: 1,
},
{
question: "越南的首都是?",
answers: ["河内", "胡志明市", "海防"],
rightIdx: 0,
},
{
question: "印度的首都是?",
answers: ["新德里", "巴黎", "孟买"],
rightIdx: 0,
},
]
// 补全代码
$$demo <button onclick="work()">首都问答</button> <script> function work() { let items = [ { question: "中国的首都是?", answers: ["上海", "广州", "北京"], rightIdx: 2, }, { question: "美国的首都是?", answers: ["纽约", "华盛顿", "伦敦"], rightIdx: 1, }, { question: "新加坡的首都是?", answers: ["后港", "新加坡市", "裕华"], rightIdx: 1, }, { question: "越南的首都是?", answers: ["河内", "胡志明市", "海防"], rightIdx: 0, }, { question: "印度的首都是?", answers: ["新德里", "巴黎", "孟买"], rightIdx: 0, }, ]
alert("首都问答~")
let rightCount = 0
for (let item of items) {
let idx
while (true) {
let answer = prompt(
`${item.question}\nA: ${item.answers[0]}\nB: ${item.answers[1]}\nC: ${item.answers[2]}`
)
switch (answer) {
case "A":
case "a":
idx = 0
break
case "B":
case "b":
idx = 1
break
case "C":
case "c":
idx = 2
break
default:
// 如果是无效输入则让用户重新输入
// 用 continue 跳过当前循环
alert("无效输入,请重新输入。")
continue
}
// 有效输入的情况下最终会 break 结束循环
break
}
if (idx === item.rightIdx) {
alert("恭喜答对了~")
rightCount++
} else {
alert(`很遗憾答错了,正确答案是:${item.answers[item.rightIdx]} 。`)
}
}
alert(`共回答了 ${items.length} 题,答对了 ${rightCount} 题。`)
}
</script> $$
$$answer
$$jsdemo$$
$$edit$$
let items = [
{
question: "中国的首都是?",
answers: ["上海", "广州", "北京"],
rightIdx: 2,
},
{
question: "美国的首都是?",
answers: ["纽约", "华盛顿", "伦敦"],
rightIdx: 1,
},
{
question: "新加坡的首都是?",
answers: ["后港", "新加坡市", "裕华"],
rightIdx: 1,
},
{
question: "越南的首都是?",
answers: ["河内", "胡志明市", "海防"],
rightIdx: 0,
},
{
question: "印度的首都是?",
answers: ["新德里", "巴黎", "孟买"],
rightIdx: 0,
},
]
alert("首都问答~")
let mark = {
A: 0,
a: 0,
B: 1,
b: 1,
C: 2,
c: 2,
}
let rightAmount = 0
for (let item of items) {
let idx
while (true) {
let answer = prompt(
`${item.question}\nA: ${item.answers[0]}\nB: ${item.answers[1]}\nC: ${item.answers[2]}`
)
idx = mark[answer]
if (idx === undefined) {
// 输入错误
alert("无效输入,请重新输入。")
} else {
break
}
}
if (idx === item.rightIdx) {
alert("恭喜答对了~")
rightAmount++
} else {
alert(`很遗憾答错了,正确答案是:${item.answers[item.rightIdx]} 。`)
}
}
alert(`共回答了 ${items.length} 题,答对了 ${rightAmount} 题。`)