这是我参与8月更文挑战的第3天,活动详情查看8月更文挑战
前言
上次我们对基本数据类型有了基础的认识,今天我们主要了解一下引用数据类型中的 Object 对象的基础知识,以普通对象作为例子,开启探索之旅。
定义
为了了解 Object,我们使用普通对象进行讲解:
普通对象有以下特点:
- 有大括号包裹起来的
- 有零到多组属性名和属性值(键值对)组成,用逗号分隔
- key 不能是引用数据类型,value 可以是任何的数据类型
到底何为属性?是用来做什么的?
属性就是用来描述当前对象特征/特点的,属性名是当前具备这个特征,属性值是对这个特征的描述(专业语法:属性名称为键【key】,属性值称为值【value】,一组属性名和属性值称为一组键值对)
不知道大家,看了上面关于“属性名”和属性值的描述,是否理解?不理解的话,可以看下这个例子:
想象我们在制作一个策略类战争游戏,玩家可以操作一堆士兵攻击敌方。
一个士兵,就好比如是一个对象,那我们看看士兵有什么属性,如下图:
上面的兵种、攻击力、生命值,就是属性,属性也不过如此。
let person = {
name: '追梦玩家',
age: 18
};
// person 就是一个对象,name 和 age 是 person 的属性
属性的操作
其实就是对键值对的增删查改,简称“CURD”
获取
语法:
- 对象.属性名 . 可以理解成 的,对象的属性名都是字符串格式的
- 对象[属性]
person.name // => 点操作符
person['name']
// 硬核玩家的操作 一般来说,对象的属性名都是字符串格式的(属性值不固定,任何格式都可以)
增/改
JS对象中,一个对象当中的属性名是不允许重复的(利用这点,可以实现数组去重),是唯一的。如果重复的话,有可能会报错的,有可能不报错!!!
- 增:对原有对象不存在的属性进行操作就是增加
- 改:对原有对象存在的属性进行操作就是修改
var obj = { name: '追梦玩家', age: 18 };
obj.name = '砖家'; // => 原有对象中存在name属性,此处属于「修改」属性值
obj.sex = '男'; // => 原有对象中**不存在**sex属性,此处相当于给当前对象「新增」一个属性 sex
obj[age] // 这样写不行,会报错,为什么呢?可以尝试一下,后面会讲解
obj['age'] = 28;
删除
注:delete 是关键字
彻底删除:对象中不存在这个属性了
delete obj['age'];
obj.age // undefined
不彻底(假)删除:并没有移除这个属性,只是让当前属性的值为空
obj['sex'] = null;
// obj下的 sex 属性还是存在的,只不过它的值设置为 null 而已
在获取属性值的时候,如果当前对象有这个属性名,则可以正常获取到值(哪怕是 null ),但是如果没有这个属性,则获取的结果是 undefined
obj.age // obj 对象没有 age 属性,返回 undefined
obj.sex // obj 对象有 sex 属性,但是赋值为 null,返回 null
对象的属性名说明
一个对象中的属性名不仅仅是字符串格式的,还有可能是数字格式的「类数组」
当我们存储的属性名不是字符串也不是数字的时候,浏览器会把这个值转换为字符串(toString方法),然后再进行存储
var obj = {
name: '追梦玩家',
0: 100
};
obj[0] // => 100
obj['0'] // => 100
// 错误写法:obj.0 => Uncaught SyntaxError: Unexpected number
// SyntaxError => 语法错误
// 存储的属性名为 true
obj[true] = false;
// 可以在控制台输出 obj,看看
我们怎么验证存储的属性不是字符串也不是数字的时候呢?我们可以在控制台输出 obj,看看。
通过运行 Object.keys(obj) 这个方法,可以看到 obj 的属性名,都是字符串类型的
不知道大家还记不记得,文章开头说,key 不能是引用数据类型。这个要怎么理解呢?
我们可以用一个例子来理解下:
var obj = {
name: '追梦玩家'
};
obj[{}] = 500;
console.log(obj[{xxx:'xxx'}]); // 请问,输出结果?
console.log(obj[{}] === obj[{xxx:'xxx'}]); // 请问,输出结果?
结果,如图:
为什么
obj[{}] === obj[{xxx:'xxx'}] 的结果是 true?
如果理解上面对象的属性名的相关处理,就好理解了。
其实就是会将对象转换为字符串 '[object Object]',作为属性名进行存储。
obj[{}] = 500;
// 先把({}).toString()后的结果作为对象的属性名存储进来 obj['[object Object]'] = 500
obj[{xxx:'xxx'}];
// => 获取的时候也是先把对象转换为字符串'[object Object]',然后获取之前存储的 500,所以存储对象没有用
数组也是对象
- 属性名是数字,数字从零开始,逐级递增,每一个数字代表着当前项的位置=>我们把这种数字属性名叫做“索引”
- 默认有一个 length 属性存储数组的长度,调用数组方法,length 都会自动更新
var obj = {
a : 12
}
var ary = [12,23]; // => 12和23都是属性值,属性名呢?
// 通过观察结果,我们发现数组对象的「属性名」是数字(我们把数字属性名称为当前对象的索引)
// 获取属性值,跟普通对象获取是一样的。
ary[0] // 12
ary['0'] // 12
ary.0 // => 报错 => Uncaught SyntaxError: Unexpected number
ary.length // => 2
ary['length'] // => 2
怎么理解数组和对象的关系呢?
数组是对象的一种细分,对象包含数组。对象拥有的,数组同样可以有,只不过数组在某些形式上特殊一点。数组的属性名是数字,数组是一种特殊的对象,对象有的,它也有,对象没有的,它也有。比如数组,有 push 方法,而对象没有。
关于对象的一点细节知识
先看一下,下面这个代码,输出结果是?
var obj = {
name: '追梦玩家',
age: 18
};
var name = '砖家';
console.log(obj.name);
console.log(obj['name']);
console.log(obj[name]);
结果,如图:
如果没有答对的话,就说明你没有理解'name' 和 name 的区别
// 'name'和name的区别
// => 'name'是一个字符串值,它代表的是本身
// => name(代名词/容器)是一个变量不是字符串值,它代表的是本身存储的这个值
obj.name // => 获取的是 name 属性的值
obj['name'] // => 获取的是 name 属性的值
obj[name] // => 此处的 name 是一个变量,我们要获取的属性名不叫做 name ,是 name 存储的值'砖家' => obj['砖家'] => 没有这个属性,属性值是 undefined
总的来说,就是
obj['key']获取属性名为 key 的属性值obj.key获取属性名为 key 的属性值obj[key]获取 key 这个变量存储的那个值,作为属性名对应的属性值