浅析 JavaScript 数据类型 | Object 基础

217 阅读6分钟

这是我参与8月更文挑战的第3天,活动详情查看8月更文挑战

前言

上次我们对基本数据类型有了基础的认识,今天我们主要了解一下引用数据类型中的 Object 对象的基础知识,以普通对象作为例子,开启探索之旅。

定义

为了了解 Object,我们使用普通对象进行讲解:

普通对象有以下特点:

  • 有大括号包裹起来的
  • 有零到多组属性名和属性值(键值对)组成,用逗号分隔
  • key 不能是引用数据类型,value 可以是任何的数据类型

到底何为属性?是用来做什么的?

属性就是用来描述当前对象特征/特点的,属性名是当前具备这个特征,属性值是对这个特征的描述(专业语法:属性名称为键【key】,属性值称为值【value】,一组属性名和属性值称为一组键值对

不知道大家,看了上面关于“属性名”和属性值的描述,是否理解?不理解的话,可以看下这个例子:

想象我们在制作一个策略类战争游戏,玩家可以操作一堆士兵攻击敌方。 一个士兵,就好比如是一个对象,那我们看看士兵有什么属性,如下图: image.png 上面的兵种、攻击力、生命值,就是属性,属性也不过如此。

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 的属性名,都是字符串类型的 image.png

不知道大家还记不记得,文章开头说,key 不能是引用数据类型。这个要怎么理解呢?

我们可以用一个例子来理解下:

var obj = {
    name: '追梦玩家'
};

obj[{}] = 500;
console.log(obj[{xxx:'xxx'}]); // 请问,输出结果?
console.log(obj[{}] === obj[{xxx:'xxx'}]); // 请问,输出结果? 

结果,如图: image.png 为什么 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]);

结果,如图: image.png 如果没有答对的话,就说明你没有理解'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 这个变量存储的那个值,作为属性名对应的属性值