文章目录
JavaScript 对象
在之前的文章 《JavaScript数据类型》中,我们简单的介绍了
JavaScript
的八种数据类型,其中包括七种原始的数据类型(
Number
、
BigInt
、
String
、
Boolean
、
null
、
undefined
和
symbol
)和一种复杂类型
object
(也就是对象类型)。
相比于原始数据类型,
object
之所以被称为复杂类型,是因为原始类型仅仅能表示一种数据,例如
Number
表示数字,
String
表示字符串等,而
object
可以通过键值对的形式,包含所有的原始数据类型。
例如,我们可以使用
symbol
类型表示对象的
ID
,用
String
类型表示对象的名字,用
Boolean
表示对象的性别等等。对象中的每一个类型的数据都被称为对象的一个属性,一个对象理论上可以有无数个属性,这些属性统一在一对花括号
{...}
中创建。
面向对象不仅仅是
JavaScript
的语言特性,实际上在所有的面向对象语言,如
C++
、
Java
、
Python
、
C#
中都是非常重要的概念。想要学好
JavaScript
,必须熟练乃至精通对象的特性,因为对象渗透了
JavaScript
的方方面面。
面向对象 VS 面向过程
面向对象是一种编程思想,并非新的技术。在面向对象出世之前,程序员都是以面向过程的思想组织大量代码的。
何为面向对象?这个问题在学校和面试中会被经常问到。我们可以极其高深的理解回答:万物皆对象,虽然这绝对正确,却并不是面试管或者老师想要的答案。
面向对象是一种编程思想,一种组织代码的方式,是相对于面向过程而言的。在面向过程中,程序员就是上帝,上帝指挥指挥着所有的一切。例如我们常举的一个例子:把大象装进冰箱。
在面向过程中,把上帝需要先把冰箱门打开,然后把大象放进冰箱,最后把冰箱门关上。所有过程由上帝一个人操作。
在面向对象中,冰箱和大象都是存在的一个对象,而且冰箱会自己开门,大象也会自己进冰箱,然后冰箱自己把门关上即可。整个过程由上帝协调,但是具体做事的过程由对象自己完成,比如如何打开冰箱门,如何走进冰箱等。
语法
定义一个对象不需要使用关键字,直接使用花括号
{..}
包裹键值对就能创建对象,语法如下:
let child ={name:'Tom',age:8,}
以上代码就创建了一个简单的对象,并把对象赋值给了变量
child
。
child
对象拥有两个属性(两个值),一个是
name
,另一个是
age
。
所谓键值对(
key:value
),就是简单的名称和值之间的映射。
例如上例中的
name:'Tom'
就是一个键值对,其中
name
是键,
"Tom"
是对应的值。实际使用过程中,可以通过键获得对应的值,就像使用变量名称获得变量值是一样的。
空对象
如果一个对象中没有任何属性,那么这个对象就是一个空对象。我们可以通过简单的把
{}
赋值给一个变量获得空对象,还可以使用另外一种方式:
let nullObj1 ={};//创建也给空的对象let nullObj2 =newObject();//同样创建了一个空对象
对象操作
一个对象创建之后,并非一成不变的,我们在使用对象的过程中,随时都可以查询对象的属性,或者更改对象。
查询属性
查询对象的属性值,需要使用一个新的符号:
.
,语法是
对象名.变量名
。
举个简单的小李子:
let child ={name:'Tom',age:8,};
console.log(child.name);
console.log(child.age)
代码执行结果如下:
在上述案例中,如果我们想查看变量
child
中的
name
属性,只需要简单的使用
child.name
就可以了。
增加属性
在一个对象变量创建完成后,我们还可以随时向变量中添加新的属性,方法如下:
let child ={name:'Tom',age:8,}
child.height =800;//创建了一个新的属性height
console.log(child.height);
代码执行结果如下:
向对象变量中添加新的属性,只需要直接使用
.属性名
,然后直接向新属性赋值即可。
如果我们此时查看变量
child
的内容,可以发现
height
属性已经位列其中了:
对象的属性类型可以是任意的,我们可以直接使用
child.isBoy=true
向对象中添加布尔值,或者使用
child.money=null
添加一个值为空的属性。
更改属性
JavaScript
对象更改属性值也非常简单,直接向变量赋值就可以了,举个简单的小李子:
let child={name:'Tom',age:8,}
child.age=12;
console.log(child);
代码执行结果如下:
可以看到,
age
变量已经从
8
变成了
12
。
删除属性
对象删除属性需要使用一个新的关键字
delete
,使用
delet 对象名.属性名
删除对象的属性:
let child ={name:'Tom',age:8,}delete child.age;
console.log(child);
代码执行结果如下:
从代码的执行结果可以看到属性
age
已经被删掉了。
多单词键值
对象的属性名(键)还能够使用空格隔开的多个单词,不过在创建此类属性时需要使用双引号把键名包裹起来。
举个例子:
let child={
name ='Tom',age:8,"favorite cat":'Jerry',}
以上代码就创建了一个键名为
"favorite cat"
的键值对,但是在访问属性值的时候,如果使用:
child.favorite cat ='Bob';//语法错误
这种方式是错误的,引擎会把
favorite
当作一个键名,并在遇到
cat
时报错。
访问此类键值,就需要方括号。
方括号
.
可以访问普通的属性名,在例如
"favorite cat"
之类的变量时可以使用
[]
,举个例子:
let child={name:'Tom',age:8,"favorite cat":'Jerry',}
console.log(child['favorite cat']);
代码执行结果如下:
方括号提供了
.
之外的属性访问方式,我们完全可以通过方括号代替
.
来操作对象的属性。
例如:
let child ={name:'Tom',age:8,}
child['favorite cat']='Jerry';//增加属性
child['name']='Bob';//修改属性delete child['age'];//删除数
console.log(child['name']);//查看属性
除了常规的属性操作之外,方括号还能通过变量访问对象属性:
let child ={name:'Tom',age:8,}let prop ='name';
console.log(child[prop]);
prop='age';
console.log(child[prop]);
通过变量访问属性值的能力为我们提供了非常有用的变量访问方式,例如我们可以在程序中计算出属性的键名,然后再通过键名访问键值。
举个栗子:
let child ={prop1:0,prop2:1,prop3:2,}let prop ='prop';for(let i=1;i<4;i++){
console.log(child[prop+i]);}
在这里,范围属性值的
key
是通过计算得到的,这一功能用
.
是不能实现的。
计算属性
在创建对象时,我们还可以通过变量指定对象的键名,此类属性叫做计算属性。
举个例子:
let propName ='name';let child ={[propName]:'Tom',age:8,}
代码执行结果如下:
> let propName = 'name';
> let child ={
[propName]:'Tom',
age:8,
> }
> undefined
> child
> {name: 'Tom', age: 8}
上例中的
[propName]
就是一个计算属性,意义也非常简单,就是使用变量
propName
中存储的值(此处为
"name"
)作为对象的键名。
以上的代码本质上和下面的代码作用相同:
let propName='name';let child ={age:8,}
child[propName]='Tom';
方括号中还可以使用复杂的表达式:
let child ={['prop'+2*3]:'Tom',}
代码执行结果如下:
>let child ={['prop'+2*3]:'Tom',}<undefined> child
<{prop6:'Tom'}
属性简写
在实际应用中,或者匿名对象中,我们常常会使用和变量同名的属性,举个例子:
let name ='Tom';let age =8;let child ={name:name,//属性名和变量名一样,都是nameage:age,};
这种情况下,我们就可以简写对象属性,如下:
let name ='Tom';let age =8;let child ={
name,// 等同于name:name;
age,}
代码的执行结果:
>let name ='Tom';let age =8;let child ={
name,
age,}<undefined> child
<{name:'Tom',age:8}
属性命名
和变量命名不同,我们几乎可以使用任何值作为属性的名称,包括关键字和数字:
关键字作为变量名
虽然听起来不可思议,实际上,所有的关键字都可以作为对象的属性名:
let obj ={for:0,while:1,function:2,alert:3,}
代码执行结果:
>let obj ={for:0,while:1,function:2,alert:3,}<undefined> obj
<{for:0,while:1,function:2,alert:3}
数字作为关键字
数字也可以作为关键字的名称,如下:
let obj ={0:'Number',//隐式转换为"0"1:'Number',}
console.log(obj['0']);
数字作为属性名称时,会被隐式转换为字符串,在访问属性时,不能使用
.
,必须使用方括号代替。
属性名称中的陷阱
在命名中,有一个小陷阱,我们不能使用
__proto__
作为属性的名称,这个属性是对象的一个特殊,后继会特别介绍。
举个例子:
let obj ={};
obj.__proto__ =1;
console.log(obj.__proto__);
in 操作符
JavaScript
有一个需要注意的特性,即使访问一个不存的属性时也不会报错,仅仅是返回
undefined
。
那我们如何知道,属性是否存在于对象之中呢?
最简单的方式是使用
if
语句:
let obj ={};if(obj.someProp ===undefined){...}
这么做在大部分情况下是没有问题的,但是当属性名称的值就是
undefined
本身时,就会出现错误:
let obj ={prop:undefined}
obj.prop ===undefined? console.log('no'):console.log('yes');
代码执行结果:
>let obj ={prop:undefined}
obj.prop ===undefined? console.log('no'):console.log('yes');
no
<undefined
虽然
prop
是存在的,但是以上案例并不能正确的返回结果。
这个时候就需要使用
in
let obj ={prop:undefined,};if('prop'in obj){
console.log('yes');}else{
console.log('no');}
这么做是不是优雅了许多呢?
>let obj ={prop:undefined,};if('prop'in obj){
console.log('yes');}else{
console.log('no');}< yes
<undefined
属性遍历
如果我们不知道对象中都存在什么属性,如何取得所有的属性值呢?
这时候就需要使用
for .. in ..
语句了,它类似于
for
循环,但是更简洁。
语法
for(key in obj){...}
举个简单的小李子:
let child ={name:'Tom',age:8,height:180,}for(let key in child){
console.log(key+':'+child[key]);}
代码执行结果如下:
>let child ={name:'Tom',age:8,height:180,}for(let key in child){
console.log(key+':'+child[key]);}< name:Tom
< age:8< height:180<undefined
属性顺序
当我们创建一个对象并遍历其中所有的属性时,属性是如何排列的呢?答案是:特别的顺序排列,并遵循以下规则:
- 数字属性以数字顺序排列;
- 其他属性按照创建顺序排列;
- 数字属性在其他属性之前;
举个例子:
let obj ={name:'Tom',age:99,7:'7',1:'1',9:'9',}for(let key in obj){
console.log(key+':'+obj[key]);}
代码执行结果:
>let obj ={name:'Tom',age:99,7:'7',1:'1',9:'9',}for(let key in obj){
console.log(key+':'+obj[key]);}<1:1<7:7<9:9< name:Tom
< age:99
总结
- 对象是基本属性的集合
- 属性名必须是字符串或
Symbol
- 值可以是任何类型
- 使用
.
访问属性 - 使用
[]
也可以访问属性
版权归原作者 @魏大大(⑉°з°)-♡ 所有, 如有侵权,请联系我们删除。