JavaScript:对象

2023-12-21 06:16:48


对象是什么

对象的定义

对象是 JavaScript 数据类型的一种,之前已经学习了数值类型、字符串类型、布尔类型、undefined。对象数据类型可以被理解成是一种数据集合。
对象数据类型,有点类似于数组,它是多个数据的集合,不同的是,对象内部的数据,都是对这个对象的描述,先为大家展示一个对象:

let person = {
            name: "张三",
            age: 18,
            dance: function(){
                document.write("张三会跳舞");
            },
            cook: function(){
                document.write("张三会做饭");
            }
        }

这是一个名为person的对象,它内部有四个属性,分别是name,age,以及cook函数,dance函数。这四个属性都是对这个person对象的描述,代表其名字为张三,十八岁,会做饭,会跳舞。
其中,后两个函数,一般不称为属性,而称为方法。


对象的组成

对象由其内部的属性和方法组成,属性就是一些基础数据,而方法本质就是一些函数,当我们使用这个对象的时候,就可以执行它的某一个函数,比如我们在刚刚的对象中,可以调用它的函数dance,这样屏幕就会输出一句”张三会跳舞“。可以把输出这句话的功能,称之为这个对象的方法。


对象的使用

对象声明

那么我们要如何声明一个对象?我们有两种方式:直接声明和利用函数声明。

利用函数声明

语法:let 对象名 = new Object()
由于对象也是一个数据类型,和其它数据类型一样,需要使用let,var,const这种关键字。
这种函数方法其实不常用,以上语法会得到一个空对象,也就是其内部没有任何属性,不过后续有增加属性的方法,不必担心,在此不对此方法过多赘述了。

直接声明

语法:

let 对象名 = {
            属性1: 属性值1,
            属性2: 属性值2
        }

这种直接声明的方式,和数组十分类似,我们只需用一个大括号把对象的属性括起来,每两个属性之间用逗号隔开即可。这样我们就可以得到一个初始化过的对象,当然,你也可以一个属性值都不写,直接得到一个空对象。


访问对象

既然我们得到了一个对象,我们就需要访问这个对象的值,就好比得到了一个数组,我们也需要去访问数组的元素。
访问对象有两种方法:对象名.属性对象名['属性']
对象名.属性
示例:
在这里插入图片描述
我们在此访问person这个对象,获取它的name属性,通过对象名.属性,即person.name就可以得到张三这个值。

对象名['属性']
我们再利用另一个方法访问一下age这个属性:
在这里插入图片描述
可以发现我们一样访问到了属性的值,这里要十分注意[]内部的属性要加上引号,单引号或双引号都可以。

那么为什么需要两种方法呢?
我们为person这个对象在加一个属性:previous-name:"张四"来代表曾用名:
在这里插入图片描述
报错了,说明这个语法是有问题的,当我们的属性名字太长,需要使用特殊符号来区分的时候,需要为其加上引号:
在这里插入图片描述
加上引号后,这个报错就消失了,此时的previous-name:"张四"是合法的。
尝试以不同方式访问这个previous-name
在这里插入图片描述

这里一共用了四种方式访问,主要问题在于,访问时要不要加引号?用哪种方式访问?
首先person.'previous-name'已经报错,毫无疑问是不行的,删除后再执行一次:
在这里插入图片描述
运行后,程序报错了:第25行的previous没有定义,这里不加引号就已经违背基础语法了,报错是毫无疑问的。把它注释掉,再执行一次:
在这里插入图片描述
用一个点访问的方式全军覆没了,不论加不加引号,解析都会有问题。
最后得出结论,这种带有特殊字符,需要用引号引起的属性名,必须使用中括号的形式来访问
两种方法都有自己的应用面,都非常重要。


对象方法的调用

我们刚刚的访问,都是基于对象的属性,没有访问对象的后两个方法,因为方法的本质是函数,函数调用又是额外的语法:对象名.方法名(函数参数)对象名['方法名'](函数参数)
分析一下,其实不难发现,相比于访问对象的属性,调用对象的方法只是在访问完毕后,加上一个调用函数的小括号而已,而函数的传参是在小括号里面也不难理解。
示例:
在这里插入图片描述
最后函数都正常执行了,也就是方法成功调用了。


增加与改变对象属性

增加或改变对象的属性,语法是完全一致的,只需要直接赋值即可,当被赋值的属性在对象中存在,那么可以直接修改;如果被赋值的属性在对象中不存在,那么就会增加这个属性。
示例:
在这里插入图片描述
原先age是存在的,于是person.age = 20;就直接修改了age属性的值;
原先weight不存在,于是person.weight = "100kg";增加了该属性。


删除对象属性

删除对象的属性,需要用到关键字delete,语法:delete 对象名.属性名或者delete 对象名['属性名'],这样就能删除对应的对象。
示例:
在这里插入图片描述
最后,age属性和previous-name属性都被删掉了。


遍历对象

对象和数组很像,我们在遍历数组的时候,往往是利用下标来一个个访问,但是对象没有下标,该如何访问?
首先介绍一个for in语句,它可以遍历数组:
在这里插入图片描述
我们利用for in语句,可以在每一次循环时,为k一次赋值一个下标,那么我们遍历数组只需要arr[k]就可以了:
在这里插入图片描述
我们成功输出了这个数组的所有值。

这个for in语句对对象同样生效:
在这里插入图片描述
我们利用for in语句,让k每次循环,都得到一个属性名,但是,我们检测k的类型后,发现它是string类型。这说明,k并不直接等于属性名,而是属性名的字符串形式,也就是 k = “属性名” 。这十分重要,因为这意味着我们无法通过属性名.k的形式来获得对应的属性,因为自带一对引号。所以我们要使用属性名[k]的形式,由于k自带引号,无需在对k加引号。
示例:
在这里插入图片描述
这样我们就通过for in语句遍历了整个对象的所有属性。


内置对象

对象不仅可以我们自己创建,JavaScript还提供了丰富的内置对象,我们需要时可以直接调用。
回想一下我们曾经使用过的 console.logconsole其实就是 JavaScript 中内置的对象,该对象中存在一个方法叫 log,然后调用 log 这个方法,即 console.log()
除了 console 对象外,JavaScritp 还有其它的内置的对象
在此我介绍一个Math对象。

Math对象

Math 是 JavaScript 中内置的对象,称为数学对象,这个对象下即包含了属性,也包含了许多的方法。

属性
  • Math.PI,获取圆周率
console.log(Math.PI);

调用得到:3.141592653589793

方法
  • Math.random,生成 0 到 1 间的随机数
Math.random()

0 ~ 1 之间的随机数, 包含 0 不包含 1


  • Math.ceil,数字向上取整
Math.ceil(3.4)

舍弃小数部分,整数部分加1


  • Math.floor,数字向下取整
Math.floor(4.68)

舍弃小数部分,整数部分不变


  • Math.round,四舍五入取整
Math.round(5.46539)
Math.round(4.849)

取整,四舍五入原则


  • Math.max,在一组数中找出最大的
Math.max(10, 21, 7, 24, 13)

  • Math.min,在一组数中找出最小的
Math.min(24, 18, 6, 19, 21)

  • Math.pow,幂方法
Math.pow(4, 2) // 求 4 的 2 次方
Math.pow(2, 3) // 求 2 的 3 次方

求某个数的多少次方


  • Math.sqrt,平方根
Math.sqrt(16)

求某数的平方根


数学对象提供了比较多的方法,这里不要求强记,通过演示数学对象的使用,加深对对象的理解。

在此我们特地讲解一下生成指定随机数的方法:
随机数生成方法:
在调用random方法的时候,会得到一个[0,1)的随机数,如果我们对其乘以N,那么就能得到[0,N)的随机数,也就是Math.random() * N
但是这样的随机数是包括小数的,此时我们就需要对这个结果取整,得到[0,N)的随机整数,即Math.floor(Math.random() * N)
如果我们想得到[M,N]的整数,就是Math.floor(Math.random() * (N - M)) + N,在此不过多推算了。


JavaScript对内存的分配

JavaScript中,主要有两个内存区域:栈区和堆区。而不同的数据类型,对内存的使用是不同的,主要区别为简单类型和复杂类型。

简单数据类型的内存分配

对于简单类型的数据,比如Number,Boolean,String,Undefined。
它们数据存储于栈区中,我们使用的变量,本身指向这个数据。
对于这样一串代码:

	let a = 5;
	let b = false;
	let c = undefined;
	let d = "1234";

它的内存分配是这样的:
在这里插入图片描述


复杂数据类型的内存分配

对于复杂数据类型,比如对象,它会由两部分组成,分别是栈区的变量索引,以及堆区的数据实体。
比如对于下面的代码:

	let person = {
		name: "张三",
		age: 18,
	}

它的内存分配是这样的:
在这里插入图片描述

那么这两种内存分配有啥区别?
首先明确一点,我们操作的变量,其数据是栈区的数据。
当我们进行变量赋值的时候,就会发生区别:

let a = 5;
let b = a;

这个过程中,a在栈区中的数据是5,于是b就得到5这个值:
在这里插入图片描述
而对于复杂数据类型:

let person = {
	name: "张三",
	age: 18,
}

let person2 = person;

person变量在栈区中的数据是指向堆区的索引,于是person2就得到了这个索引:
在这里插入图片描述
由于索引与person一致,所以最终person2和person指向同一个对象。

执行以下代码

let person = {
	name: "张三",
	age: 18,
}

let person2 = person;
delete person2.name;
console.log(person);

输出结果如何呢?
由于person2与person指向同一个对象,最后对person2改变,person也会改变:
在这里插入图片描述
最后person的name属性也没有了。


文章来源:https://blog.csdn.net/fsdfafsdsd/article/details/135115658
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。