JavaScript:对象
JavaScript:对象
对象是什么
对象的定义
对象是 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.log
,console
其实就是 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属性也没有了。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!