初步认识JS中的对象(Object)类型

在开始写node相关代码的时候,因为照搬同为脚本语言python的习惯,在需要使用Dictionary,会直接采用 var a = {}。在经过一些调试以及遇到自认和文档相悖的错误的时候,豁然发现原来自己理解错误。

{} 是什么

{} 在js中是定义了一个对象Object,Object在js中是一等公民。因为js中的数据类型就只有两类:一类是包括数字字符串和布尔值的原始类型,另一个就是对象类型Object。对象类型可以理解为属性的集合,这些属性由属性名和属性值来表示(特地不说是键值对)。因此可以通过{key:value,key2:value2}的形式定义一个对象,也可以通过a[key0]=value0;修改或添加属性。

js中的Map

js中的字典数据结构是Map,具体的用法网上由很多,这里是参考的Mozilla的网站。常见的用法列举如下:

var map1 = new Map();//初始化
map1.set('0', 'foo');
map1.set(1, 'bar');
map1.get(1);
map1.keys();//返回包含所有key的迭代器,顺序按插入的先后排列
map1.values();//返回包含所有value的迭代器
map1.has('11');//是否含有key '11'
map1.delete('0');//删除key '0'
map1.clear();//清空
map1.forEach(predefinedFunc);//
for ([key,val] of map1){ }

function predefinedFunc(value, key, map) {
    console.log(`m[${key}] = ${value}`);
}

对象Object 属性的相关操作

对于不是很有js经验的人来说,通过代码来理解对象会是一个比较好的途径。

var student = {};//等价于 new Object();
student.surname = 'John';
student[uID] = 123456;
student['gender'] = 'male'; 
student.notExistProperty; //undefined
delete student['surname'];
delete student.uID;
'gender' in student;//检测是否存在gender属性
student.hasOwnProperty('gender'); //检测是否有自有(而非继承)属性 gender
for (p in student){console.log(p)}; //遍历属性
Object.keys(student);//返回自有属性数组

如上之所以有自有和继承的属性,原因在于js中对象都具有一个名为原型prototype的对象。因此通过student来设置的属性是自有属性,其余的则成为继承属性。需要说明的是,对象的属性名不一定是字符串,也可以是函数或对象。因此想获得所有自有字符串属性时,需要自己实现函数,如:

for (p in obj){
    if(!obj.hasOwnProperty(p) && typeof p !== 'string') continue;
    //xxxx
}

在delete删除属性的时候,通常操作自有属性。严格的说,delete操作不能删除可配置性为false的属性。这里回提到对象的可扩展性:可扩展性指能否自由的给对象添加属性。Object.preventExtensions()可以禁止对象可扩展;Object.seal() 除了禁止对象可扩展外,现有属性也会不能删除或修改。
在调试的时候,经常会需要打印对象的具体内容,Object.prototype由toString方法,但是默认的是返回[object Object]。如果需要打印出属性和值,那么就需要重载该函数。

由此可见,Object.prototype是js中一个神秘但是必须要好好理解的对象。关于prototype,会再另行分解。