JavaScript对象的基本理解
JavaScript里的对象,是第八种数据类型,也是八种类型中唯一的复杂数据类型。
对象的定义是,一种无序的键值对(key-value)的集合。它存储的数据没有顺序,键名也就是属性名,键名的值就是对应的属性值。
对象的键名
对象的所有键名都是字符串(ES6 规则又引入了 Symbol 值也可以作为键名)。因为键名跟标识符不同,所以可以是各种特殊字符也可以。键名默认是字符串,所以加不加引号都可以。如果不加引号,那就只能按照标识符的规则来写字符串,否则会报错。如果键名是数值的时候,会被自动转为字符串,所以键名不可以是数值,这点需要注意。
对象的键名还可以用变量来做。这时需要在变量名外加个[],这样设置后会对变量先求值,转换成字符串后用作键名。这里加不加[]的区别非常容易混淆,也是常见考点,需要多多注意。比如:
let name = 'x';
let obj1 = {name:'tom'}; // 键名为name
let obj2 = {[name]:'tom'}; // 键名为x
声明对象的两种语法
语法很简单,如下:
1. let obj = {'name':'tom'; 'height':'180'};
2. let obj = new Object({'name':'tom'; 'height':'180'});
两种方式是等价的,很显然,我们程序猿一般都会选择第一种写法,它比较简便快捷。第一种写法的本质也是new了一个新的Object对象出来。
增删改查————程序猿的宿命
非资深程序猿的工作日常,就是增删改查,无论做哪一块,何种语言大抵都是如此。学习对一个对象进行操作,也需要从增删改查开始。
改和增基本差不多,放在后面,我们先来说删。
删属性
delete obj.name 或者delete obj['nanme']
删除obj对象的name属性,也对应键名的命名,有两种写法如上。
删除时有个问题,对象存不存在你删的键名呢?需要进行一下判定。
'name' in obj === true
那么就说明在obj对象里包含一个name键名。
这里需要注意另一个容易混淆的点:含有键名,跟属性值为 undefined 无关。如果一个键名对应的属性值是undefined,不能判断这个键名有没有包含在对象里面。.
查属性
其实删属性里已经涉及到查,读属性的部分了。这里探讨一下更详细的查属性相关语法。
-
查看自身所有键名 使用
Object.keys(obj)可以得到对象obj的所有键名。 (另外,使用Object.values(obj)可以得到对象obj的所有属性值。) -
查看对象自身及共有属性
console.dir(obj)注意dir和log的区别,dir的原意是目录,可以增加理解。
这一方法也可看到对象的原型的属性,chrome浏览器会显示在obj.__proto__里。
- 查看单一属性 中括号或者点语法皆可。
obj.name``` 或者```obj['nanme']
点语法可能会误导人,再次强调一下键名是字符串,或者新增的symbol。
- 判断一个属性是否共有
obj.hasOwnProperty('toString')
私有返回 true,共有返回 false
关于原型,之前已经探讨过,每个对象都有它的原型存在,原型里存储有对象的共有属性。一般来说obj.__proto__里存着对象原型的地址。
比如 toString / constructor / valueOf 等属性都是对象原型里有的。
修改属性
- 直接赋值修改
obj.name = 'mike'
等价于obj['name'] = 'mike'
- 批量赋值
Object.assign(obj, {name: 'mike', age: 25})
增属性
与修改属性的语法基本一样,已有的属性就会进行修改,没有的属性会自动添加。
修改或添加共有属性
- 无法直接通过自身来增改共有属性,如
obj.toString = 'asd'
只会修改obj自身的属性,改不到原型。
强行要改原型的属性也是可以操作的,这点就体现出JS这门语言的脆弱性了,一些很基本的原型,可以被随意更改里面的方法,导致出现很多问题。
Object.prototype.toString = 'asd'
正常千万不要乱改原型属性。
想新增对象的原型怎么办呢,可以用以下操作
Object.create
let human = {kind: 'human'}; let obj = Object.create(human);
如果要改一个对象的原型,建议一开始就改,不要在操作中途改,很容易出问题。
'name' in obj和obj.hasOwnProperty('name') 的区别
最后再提一句这两个命令的区别。
之前已经说过,判断一个属性是否共有可以用 obj.hasOwnProperty('toString')
如果属性是共有的,不是该对象私有的,会返回 false 值。.
而'name' in obj不在乎属性是否私有,或者从原型那里继承的。只要有,就返回 true。