吴志勇的博客 吴志勇的博客
  • h5

    • HTML5&CSS3
  • scss

    • css预处理语言
  • JavaScript

    • JavaScript教程
    • Ajax
    • ES6教程
    • NodeJS
    • Typescript
  • 框架

    • Jquery
    • VUE
    • React
  • Swing专题
  • java基础
  • javaweb
  • 框架
  • 数据库
  • netty
  • 设计模式
  • 微服务及架构
  • 云原生
  • maven
  • 单元测试
工具
我的
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

吴志勇

......
  • h5

    • HTML5&CSS3
  • scss

    • css预处理语言
  • JavaScript

    • JavaScript教程
    • Ajax
    • ES6教程
    • NodeJS
    • Typescript
  • 框架

    • Jquery
    • VUE
    • React
  • Swing专题
  • java基础
  • javaweb
  • 框架
  • 数据库
  • netty
  • 设计模式
  • 微服务及架构
  • 云原生
  • maven
  • 单元测试
工具
我的
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • HTML5&CSS3

  • CSS预处理语言

  • JavaScript

    • JavaScript

      • 01 【基础语法与基本数据类型】
      • 02 【JS表达式与操作符】
      • 03 【流程控制语句】
      • 04 【对象】
        • 1.对象基础
          • 1.1 对象介绍
          • 1.2 对象分类
          • 1.3 对象的语法
          • 1.4 属性是否加引号
          • 1.5 属性的增加
          • 1.6 属性的删除
          • 1.7 属性的更改
          • 1.8 属性的访问
        • 2.基本数据类型和引用数据类型
        • 3.对象的方法
          • 3.1 认识方法
          • 3.2 方法和函数
          • 3.3 对象的遍历
        • 4.深拷贝和浅拷贝
          • 4.1 复习基本类型值和引用类型值
          • 4.2 对象是引用类型值
          • 4.3 浅拷贝
          • 4.4 深拷贝
      • 05 【函数(上)】
      • 06 【函数(下)】
      • 07 【数组及常用方法】
      • 08 【标准库之Date对象】
      • 09 【标准库之Math对象和String对象】
      • 10 【标准库之RegExp对象】
      • 11 【标准库之JSON对象 JSON5】
      • 12 【语法之错误处理机制】
      • 13 【语法之编程风格】
      • 14 【语法之console 对象与控制台】
      • 15 【严格模式】
      • 16 【DOM概述】
      • 17 【Document 节点】
      • 18 【节点的关系和内部操作】
      • 19 【节点的增删改查】
      • 20 【节点的集合】
      • 21【节点的属性】
      • 22 【事件监听】
      • 23 【事件对象与鼠标事件】
      • 24 【键盘事件】
      • 25 【进度事件和表单事件】
      • 26 【触摸事件和其它常见事件】
      • 27 【三大家族scroll、offset、client】
      • 28 【事件传播】
      • 29【定时器和延时器】
      • 30【BOM和浏览器环境概述】
      • 31【window 对象】
      • 32 【Navigator 对象和Screen 对象】
      • 33 【History对象和Location对象】
      • 34 【表单和FormData 对象】
      • 35【Storage接口】
      • 36 【节流和防抖】
    • 01 【AJAX概述和基本使用】
    • jquery
    • ES6教程

  • nodejs

  • webpack

  • VUE

  • react

  • Typescript
  • 前端
  • JavaScript
  • JavaScript
wuzhiyong
2024-09-22

04 【对象】

# 04 【对象】

# 1.对象基础

# 1.1 对象介绍

对象是JS中的引用数据类型
对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性
使用typeof检查一个对象时,会返回object

对象(object)是 “键值对” 的集合,表示属性和值的映射关系。

var xiaoming = {
    name: '小明',
    age: 12,
    sex: '男',
    hobbies: ['足球', '编程']
};
1
2
3
4
5
6
  • 属性名(键名,key): 属性值(value)
  • JS 中,大括号表示对象
  • 最后的属性后面不加逗号
  • {} 后加上分号

# 1.2 对象分类

1.内建对象

  • 由ES标准中定义的对象,在任何的ES的实现中都可以使用
  • 比如:Math String Number Boolean Function Object....

2. 宿主对象

  • 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
  • 比如 BOM DOM

3.自定义对象

由开发人员自己创建的对象

创建对象
方式一:

	 var obj = new Object();  
1

方式二:

    var obj = {}; 
1

# 1.3 对象的语法

k 和 v 之间用冒号分隔,每组 k:v 之间用逗号分隔,最后一个 k:v 对后可以不书写逗号。

var obj = {
    k: v,
    K: v,
    K: v,
    K: v
};
1
2
3
4
5
6

# 1.4 属性是否加引号

如果对象的属性键名不符合 JS 标识符命名规范,则这个键名必须用引号包裹。

注意:对象中的 key 本身就是字符串格式,只是符合 JS 标识符命名规范的可以省略引号!

var xiaoming = { 
    name: '小明',
    age: 12,
    sex: '男',
    hobbys: ['足球', '游泳', '编程'],
    'favorite-book': '舒克和贝塔'
    // 属性名中有短横,不符合JS标识符命名规范,属性名必须用引号包裹。
};
1
2
3
4
5
6
7
8

# 1.5 属性的增加

向对象中添加属性
语法:
对象.属性名 = 属性值;
对象["属性名"] = 属性值; //这种方式能够使用特殊的属性名

对象的属性名没有任何要求,不需要遵守标识符的规范,但是在开发中,尽量按照标识符的要求去写。
属性值也可以任意的数据类型。

如果对象本身没有某个属性值,则用点语法赋值时,这个属性会被创建出来。

var obj = {
    a: 10
};
obj.b = 40;
1
2
3
4
var obj = {
    a: 10
};
obj['zjr-b'] = 40;
1
2
3
4

# 1.6 属性的删除

删除对象中的属性
语法:

delete 对象.属性名  
delete 对象["属性名"]  
1
2
var obj = {
    a: 1,
    'zjr-b': 2
};
delete obj.a;
delete obj['zjr-b'];
1
2
3
4
5
6

# 1.7 属性的更改

直接使用赋值运算符重新对某属性赋值即可更改属性。

var obj = {
    a: 10
};
obj.a = 30;
obj.a++;
1
2
3
4
5

# 1.8 属性的访问

读取对象中的属性
语法:
对象.属性名
对象["属性名"] "属性名"可以使字符串常量,也可以是字符串变量
如果读取一个对象中没有的属性,它不会报错,而是返回一个undefined

可以用“点语法”访问对象中指定键的值。

xiaoming.name;		// '小明'
xiaoming.age;		// 12
xiaoming.hobbys;	// ['足球', '游泳', '编程'] 
1
2
3

如果属性名不符合 JS 标识符命名规范,则必须用方括号的写法来访问。

方括号 [] 中只能是字符串类型!

任何对象的属性名都可以通过 [] 来访问,只要把属性名写为字符串的形式。

xiaoming['favorite-book'];	// '舒克和贝塔'
1

如果属性名以变量形式存储,则必须使用方括号形式。

var obj = {
    a: 1,
    b: 2,
    c: 3
};

var key = 'b';
console.log(obj.key);	// undefined
console.log(obj[key]);	// 2
1
2
3
4
5
6
7
8
9

# 2.基本数据类型和引用数据类型

基本数据类型
String Number Boolean Null Undefined
引用数据类型
Object
基本数据类型的数据,变量是直接保存的它的值。
变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
引用数据类型的数据,变量是保存的对象的引用(内存地址)。
如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
比较两个变量时,对于基本数据类型,比较的就是值,
对于引用数据类型比较的是地址,地址相同才相同

			var a = 123;
			var b = a;
			a++;
			
			console.log("a = "+a);
			console.log("b = "+b);
			
			var obj = new Object();
			obj.name = "孙悟空";
			
			var obj2 = obj;
			
			//修改obj的name属性
			obj.name = "猪八戒";

			console.log(obj.name);
			console.log(obj2.name);
			
			//设置obj2为null
			obj2 = null;
			
			/*console.log(obj);
			console.log(obj2);*/
			
			var c = 10;
			var d = 10;
			//console.log(c == d);
			
			var obj3 = new Object();
			var obj4 = new Object();
			obj3.name = "沙和尚";
			obj4.name = "沙和尚";
			
			/*console.log(obj3);
			console.log(obj4);*/
			
			/*
			 * 当比较两个基本数据类型的值时,就是比较值。
			 * 而比较两个引用数据类型时,它是比较的对象的内存地址,
			 * 		如果两个对象是一摸一样的,但是地址不同,它也会返回false
			 */
			console.log(obj3 == obj4);
		
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

基本数据类型在内存中的表现

image-20220813142838514

引用数据类型在内存中的表现

这个很像c语言的指针,new object是在堆内存申请了一块内存空间(malloc),并把对应的地址赋值给(指针变量)obj,然后把obj的值(地址)赋值给obj2,两个(指针)就指向同一片内存空间

image-20220813142850159

image-20220813142858409

image-20220813142905754

# 3.对象的方法

# 3.1 认识方法

方法(method)
如果某个属性值是函数,则它也被称为对象的 “方法”。

var xiaoming = {
    name: '小明',
    age: 12,
    sex: '男',
    hobbys: ['足球', '游泳', '编程'],
    'favorite-book': '舒克和贝塔',
    // sayHello方法
    sayHello: function () {
		console.log('你好我是小明,今年12岁,我是个男生');
	}
};  
1
2
3
4
5
6
7
8
9
10
11

使用 “点语法” 可以调用对象的方法。

xiaoming.sayHello();
1

# 3.2 方法和函数

方法也是函数,只不过方法是对象的 “函数属性”,它需要用对象打点调用。

在正式学习了什么是 “方法” 之后,就能深入理解之前我们学习的一些函数的书写形式了,比如:

console.log();
Math.ceil();
1
2

对象.方法名();
函数名()

# 3.3 对象的遍历

和遍历数组类似,对象也可以被遍历,遍历对象需要使用 for...in... 循环。

使用 for...in... 循环可以遍历对象的每个键。

在后续的 ES6 相关课程中,还会学习新的对象遍历的方式。

【for...in...循环】

  循环遍历对象自身的和继承的可枚举属性(不含Symbol属性).  
1
// k: 循环变量,它会依次成为对象的每一个键
// obj: 要遍历的对象
for (var k in obj) {
    console.log('属性' + k + '的值是' + obj[k]);
}
1
2
3
4
5

【案例】

var obj = {
    a: 11,
    b: 22,
    c: 88
};
for (var k in obj) {
    console.log('对象obj的属性' + k + '的值是' + obj[k]);
}

/*
对象obj的属性a的值是11
对象obj的属性b的值是22
对象obj的属性c的值是88
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var zjr = {
    name: 'jerry',
    love: [180, 18, 1800000],
    home: {
        mm: 'glp',
        bb: 'zyj'
    }
};

for (var i in zjr) {
    console.log(i);
    console.log(typeof i);
}

/*
name
string
love
string
home
object
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

for...in... 循环中,每一个迭代值是对应值的字符串形式。

用的对象设置null即可

# 4.深拷贝和浅拷贝

  1. 首先浅拷贝和深拷贝只针对想Object,Array这样的复杂对象,简单来说,浅拷贝只复制一层对象的属性,二深拷贝则复制了所有的层级。

  2. 对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变,而深复制则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。

# 4.1 复习基本类型值和引用类型值

还记得我们之前学习过的基本类型值和引用类型值吗?

举例 当 var a = b 变量传值时 当用 == 比较时 当用 === 比较时
基本类型值 数字、字符串、布尔、undefined、null 内存中产生新的副本 比较值是否相等 类型相等的前提下,比较值相等
引用类型值 对象、数组等 内存中不产生新的副本,而是让新变量指向同一个对象 比较内存地址是否相同,即比较是否为同一对象 比较内存地址是否相同,即比较是否为同一对象

对于引用类型的比较来说:== 与 === 是没有区别的!

var a = {};
var b = {};
var c = a;

console.log(a == b);	// false
console.log(a === b);	// false
console.log(a == c);	// true
console.log(a === c);	// true
1
2
3
4
5
6
7
8

# 4.2 对象是引用类型值

对象是引用类型值,这意味着:

不能用 var obj2 = obj1 这样的语法拷贝一个对象。

使用 == 或者 === 进行对象的比较时,比较的是它们是否为内存中的同一个对象,而不是比较值是否相同。

【案例】

// 例子1
var obj1 = {
    a: 1,
    b: 2,
    c: 3
};
var obj2 = {
    a: 1,
    b: 2,
    c: 3
};
console.log(obj1 == obj2);      // false
console.log(obj1 === obj2);     // false

console.log({} == {});          // false
console.log({} === {});         // false

// 例子2
var obj3 = {
    a: 10
};
var obj4 = obj3;
obj3.a++;
console.log(obj4);              // {a: 11}
console.log(obj3 == obj4);      // true
console.log(obj3 === obj4);		// true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 4.3 浅拷贝

复习什么是浅拷贝:只拷贝对象的 “表层”,如果对象的某些属性值又是引用类型值,则不进一步拷贝它们,只是传递它们的引用。

常见方法:

  1. 拷贝对象:Object.assgin()/ 展开运算符 {...obj}拷贝对象

  2. 拷贝数组:Array.prototype.concat()或者 [...arr]

使用 for...in... 循环也可实现对象的浅拷贝。

【案例】

// 实现浅拷贝
const obj = {
    name: "ds",
    age: 12,
    arr: [1, 2, 3]
}
const obj2 = {}
// const obj2 = {...obj};
function shallowCopy(newObj, oldObj) {
    for (let k in oldObj) {
            // 每遍历一个 k 属性,就给 obj2 也添加一个同名的 k 属性
          // 值和 obj1 的 k 属性值相同
        newObj[k] = oldObj[k];
    }
}
shallowCopy(obj2, obj);

// 为什么叫浅拷贝呢?比如 c 属性的值是引用类型值,那么本质上 obj1 和 obj2 的 c 属性是内存中的同一个数组,并没有被拷贝分开。
obj1.c.push(77);
console.log(obj2);                  // obj2 的 c 属性这个数组也会被增加 77 数组
console.log(obj1.c == obj2.c);      // true,true 就证明了数组是同一个对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

如果是简单数据类型拷贝值,引用数据类型拷贝的是地址 (简单理解: 如果是单层对象,没问题,如果有多层就有问题)

1. 直接赋值和浅拷贝有什么区别?
直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址
浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会相互影响
2. 浅拷贝怎么理解?
拷贝对象之后,里面的属性值是简单数据类型直接拷贝值
如果属性值是引用数据类型则拷贝的是地址
1
2
3
4
5
6

# 4.4 深拷贝

复习什么是深拷贝:拷贝对象的全貌,不论对象的属性值是否又是引用类型值,都能将它们实现拷贝。

和数组的深拷贝类似,对象的深拷贝需要使用递归。

常见方法:

  1. 通过递归实现深拷贝
  2. lodash的cloneDeep
  3. 通过JSON.stringify()实现

面试时经常会考察深拷贝算法,必须掌握。

【案例】

		<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js
" type="text/javascript" charset="utf-8"></script>		

const obj = {
    name: "ds",
    age: 12,
    arr: [1, 2, 3]
}
// const obj2 = {}
// 拷贝函数
function deepCopy(newObj, oldObj) {
    debugger;
 for (let k in oldObj) {
        // 处理数组的问题  一定先写数组 在写 对象 不能颠倒
        if (oldObj[k] instanceof Array) {
            newObj[k] = []
            deepCopy(newObj[k], oldObj[k])
        } else if (oldObj[k] instanceof Object) {
            newObj[k] = {}
            deepCopy(newObj[k], oldObj[k])
        } else {
            newObj[k] = oldObj[k]
        }
    }
}
// deepCopy(obj2, obj);
const obj2 = _.cloneDeep(obj)

obj2.name = "ds2";
obj2.arr[0] = 0;
console.log(obj);
console.log(obj2);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
上次更新: 2024-09-30 01:09:25

← 03 【流程控制语句】 05 【函数(上)】→

Copyright © 2020-2025 wuzhiyong
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式