# JS 一个重要数据结构:对象
# 课程目标
- 学习对象基础知识
- 掌握对象创建方式 读取动态属性方法
- 学习对象的基本操作
- 掌握对象的克隆合并方法
# 对象基础
对象是一种数据类型,允许您将多个变量组合成一个包含键和值的变量。这通常用于表示或描述实体。例如,一个人、一个用户、一个产品等。
创建对象的方法如下:
const student = {
id: 1,
name: "Jackson",
age: 20,
requiredCourses:['Linear Alberia ','Intorduction of Computer',' Avanced Mathematics'],
optionalCourses:['Software Engineering',' Signal and System','Principle of Compiling',' Data Structure']
};
对象命名最好用驼峰命名规则,比如必修课程命名为 requiredCourses,而不是 required_courses
读取/更新对象属性值
要读取或者更新对象中属性的值,可以使用点表示法如下:
const student = {
id: 1,
name: "Jackson",
age: 20,
requiredCourses:['Linear Alberia ','Intorduction of Computer',' Avanced Mathematics'],
optionalCourses:['Software Engineering',' Signal and System','Principle of Compiling',' Data Structure']
};
//读取属性值
student.id //1
student.name //Jackson
student.age //20
student.requiredCourses //['Linear Alberia ','Intorduction of Computer',' Avanced Mathematics']
student.optionalCourses //['Software Engineering',' Signal and System','Principle of Compiling',' Data Structure']
//更新对象属性值
student.id = 2
student.age = 21
console.log(student.id) //2
console.log(student.age) //20
读取动态属性值
现在,如果您想要读取的属性存储在一个变量中呢?例如:
const key = "id"; //属性名保存在变量 key 里面
student.key; // undefined
我们不能在这里使用点语法,因为属性是动态的。当您编写 student.key 时,JavaScript 将查找名为 key 的属性,student 中并没有 key 这个属性,所以返回 undefine。
为此,您必须使用方括号,如下所示:
const student = {
id: 1,
name: "Jackson",
age: 20,
requiredCourses:['Linear Alberia ','Intorduction of Computer',' Avanced Mathematics'],
optionalCourses:['Software Engineering',' Signal and System','Principle of Compiling',' Data Structure']
};
const key = "id";
student[key]; // 1
对象简写
JavaScript 对象中有一个漂亮的特性是对象简写。假设您有一个变量 id,并且您想创建一个带有键的对象 student , 并且它的 id 值是一个变量 id
const id = 1;
const student = {
name: "John",
id: id,
};
这 id: id 有点多余,因此您可以如下编写:
const id = 1;
const student = {
name: "John",
id,
};
对象简写调试技巧
对象速记可以用作非常有用的调试技巧。假设您有以下代码:
const sum = (num1, num2) => {
console.log(num1); // 10
console.log(num2); // 8
let total = num1 + num2;
console.log(total); // 18
return total;
};
// 用例
sum(10, 8);
以上是您在用 console.log 调试代码,希望在控制台打印出每一步骤的值,但是我们不知道这些值的对应关系
这时,对象简写可以巧妙解决此问题,您调用 console.log 打印变量时,可以将每个变量包装{}中 ,代码如下所示:
const sum = (num1, num2) => {
console.log({ num1 }); // {num1: 1}
console.log({ num2 }); // {num2: 3}
let total = num1 + num2;
console.log({ total }); // {total: 4}
return total;
};
// 用例
sum(1, 3);
# 阅读
- 基本数据类型 (opens new window)
- JavaScript 对象基础 - MDN (opens new window)
- 对象 - JavaScript 现代教程 (opens new window)
- JavaScript 对象 - W3School (opens new window)
- 什么是 JavaScript 对象?键值对和点符号解释 (opens new window)
- JavaScript 对象键教程——如何使用 JS 键值对 (opens new window)
# 编码
创建一个叫做 bankAcount 的银行账户对象。
该对象应该包含 4 个属性:
- 你的名称 name
- 你的存款 balance
- 你的财富排行 rank
- 你的银行利率 interestRatePercent
该对象还应该具有 2 个方法:
- deposit(amount) - 向存款中存入 amount 数量的钱
- withdraw(amount) - 向存款中取出 amount 数量的钱
添加一个返回账户消息的 printAccountInfo() 方法,在控制台打印出用户的存款,财富排名以及银行利率
<script>
//your complement console.log(savingsAccount.printAccountSummary());
//您的存款总值:¥1000 ,您的财富排名为:1,您的银行利率为:1%
</script>
- 封装一个函数,检验 bankAcount 是否有 vip 这个属性,如果有就返回 true ,如果没有就返回 false
- 封装一个函数,遍历 bankAcount 的属性,并且控制台中打印出来
- 封装一个 isEmpty(obj) 判空函数,当对象没有属性的时候返回 true,否则返回 false。
# 对象遍历
- Object.keys,values,entries (opens new window)
- How to Access Object's Keys, Values, and Entries in JavaScript (opens new window)
- Object.entries() - JavaScript | MDN (opens new window)
- Object.keys, values, entries - TIL coding (opens new window)
# 编码
编码实现以下方法
let shoppingList = {
hamburger: 12,
milk: 5,
orange: 25,
banana: 49,
ipad: 10111,
};
/**
* @description 获取购物清单所有的商品
* @method getKeys
* @param {Object} obj 对象
* @return {Array} 返回包含对象所有键名的数组
*/
function getKeys(obj) {
// your complement
}
/**
* @description 获取购物清单所有商品的价格
* @method getVals
* @param {Object} obj 对象
* @return {Array} 返回包含对象所有键值的数组
*/
function getVals(obj) {
// your complement
}
/**
* @description 计算购物清单总价
* @method sumshoppingList
* @param {Object} obj 对象
* @return {Number} 返回购物清单的总价
*/
function sumshoppingList(obj) {
// your complement
}
/**
* @description 给购物清单排序
* @method sumshoppingList
* @param {Object} obj 对象
* @param {Boolean} ascendingOrder 如果值为true,就从小到大排序,值为false,就从大到小排序
* @return {Object} 返按从大到小或者从小到大规律排序的购物清单列表
*/
function sumshoppingList(obj, ascendingOrder) {
// your complement
}
# 对象解构赋值
# 编码
- 使用解构赋值实现交换 num1,和 num2 的值
let num1 = 1
let num2 = 0
//your complement
console.log(num1,num2) // - > 0 , 1
- 使用解构赋值实现对象的解构
/*
* 解构要求
* name 属性赋值给变量 name。
* years 属性赋值给变量 age。
* math 属性复制给变量 mathScore。
* chemistry 属性复制给变量 chemistryScore。
* biology 属性复制给变量 biologyScore。
* sport 属性复制给变量 hobby1。
* dance 属性复制给变量 hobby2。
* marriageStaus 属性赋值给变量 marriageStaus(如果属性缺失则取默认值 false)
*/
let person = {
name: "Amy",
years: 30,
score: {
math: 99,
chemistry: 80,
biology: 78,
},
hobbies: ["sport", "dance"],
};
// your complement
console.log(name); // Amy
console.log(age); // 30
console.log(mathScore); // 99
console.log(chemistryScore); // 80
console.log(biologyScore); // 78
console.log(hobby1); // sport
console.log(hobby2); // dance
# 对象引用和复制
# 编码
了解值类型和引用类型的区别,了解各种对象的读取、遍历方式,并在 util.js 中实现以下方法:
// 使用递归来实现一个深度克隆,可以复制一个目标对象,返回一个完整拷贝
// 被复制的对象类型会被限制为数字、字符串、布尔、日期、数组、Object对象。不会包含函数、正则对象等
function deepClone(src) {
// your implement
}
// 测试用例:
var srcObj = {
a: 1,
b: {
b1: ["hello", "hi"],
b2: "JavaScript"
}
};
var abObj = srcObj;
var tarObj = deepClone(srcObj);
srcObj.a = 2;
srcObj.b.b1[0] = "Hello";
console.log(abObj.a);
console.log(abObj.b.b1[0]);
console.log(tarObj.a); // 1
console.log(tarObj.b.b1[0]); // "hello"
如果您完成速度较快,可以试着使用不同的方法实现一下对象的深拷贝
# 对象属性配置
# 编码一
了解 Object.defineProperty(),实现一个简易的数据双向绑定
<label>姓名:</label><input type="text" class="name" onchange="changeName()" />
<button onclick="changeInput()">恢复姓名为rose</button>
//利用通过 Object.defineProperty()来实现简易的双向数据绑定 //创建person对象 var
person = { name:'' } function changeName(){
//修改person对象中的name的值为输入框中的值 } Object.defineProperty(person,
'name', { // 这里实现双向绑定,监听name值变化,input也跟着变化 }) function
changeInput(){ //按钮事件 修改person对象中的name的值为rose }
题目要求
- 当改变姓名输入框的值敲击回车,console 打印 person.name 的值与姓名输入框的值一致
- 当在调试环境代码行输入 person.name = amber,姓名输入框的值自动变成 amber ,如下图所示
- 点击
恢复姓名为rose
按钮,修改 person.name 的值为 rose (不要直接修改姓名输入框的值),输入框的值自动变成 rose。
# 编码二
在上一个任务的基础上,完成如下要求
function addID(id){
//给person对象添加一个ID属性
//值为'1'
//不可重写,只可读
//不可删除
//不可枚举
}
//测试用例
addID(1)
console.log(persion.id); // logs 1
delete persion.id; // Nothing happens
console.log(persion.id); // logs 1
person.propertyIsEnumerable('id'); // false
person.id = 2; // throws TypeError: "id" is read-only
# 自测问题
- 与原始类型相比,对象和它们的区别是什么?
- 不用将代码粘贴到控制台中,能判断出这段代码的输出内容吗?
let a = {};
let b = a;
let c= {};
console.log( a == b );
console.log( a === b );
console.log( a == c )
- 下面这段代码会输出什么内容?
let animal = { species : "fish" };
Object.assign(user, { species: "dog" });
console.log(animal.species);
- 什么是浅拷贝?什么是深拷贝?请说说它们的区别
- 下面这段代码输入什么结果?怎么将它修改正确?
function makeAccount() {
return {
name: "Amy",
ref: this
};
}
let user = makeAccount();
console.log( user.ref.name ); // 结果是什么?