读取js中对象的属性通常有两种方法,一种是使用点运算符,还有一种是使用方括号运算符;
1:obj.xxx
当使用obj.xxx
方式读取属性时,js内部会进行一个转换,转换成一个内部方法的调用,内部方法名字叫做get
,外部无法访问,内部使用,该方法作用是读取某个对象的某一个属性,3个参数
obj.xxx //[[GET]](obj, 'xxx', obj)
第一个参数:代表从哪个对象读取属性
第二个参数:读取的属性名并且一定会把属性名当成字符串
第三个参数:代表读取该属性期间的this指向
2:obj[xxx]
它也是调用内部的get
方法,第二个参数有区别,并不是像上方当成一个字符串
去读取,而是做了一个三目运算处理,首先判断读取的属性名
是不是symbol
,如果是symbol
的话,属性的名字直接就是symbol
,否则会把该属性转换成字符串
obj[xxx];
//[[GET]](obj, xxx是不是symbol ? xxx : String(x), obj);
经典面试题
1.先回顾一下Object.prototype.toString()
方法
语法:
obj.toString()
返回值:
一个表示该对象的字符串。
描述:
每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 “[object type]”,其中 type 是对象的类型。
从 JavaScript 1.8.5 开始,toString() 调用 null 返回[object Null],undefined 返回 [object Undefined]。
2.请问obj现在有几个属性?
const obj = {};
obj[0] = 1;
obj['0'] = 2;
答案:只有一个obj:{0:2}
使用中括号读取属性的方式,首先判断0
是不是symbol
类型,发现不是,就会转换成字符串,而数字0转换成字符串就是字符串的0,所以下方的
obj['0'] = 2
就会覆盖掉上方
3.请问输出结果是什么?
const obj = {};
obj[obj] = 1;
console.log(obj);
输出结果是:{'[object Object]':1}
因为:当使用中括号读取对象属性的方式时,会先判断obj
是否是
symbol
类型,不是会转换成字符串,而对象转字符串会调用原生Object构造函数原型对象上的toString
方法,而对象调用toString()
方法返回值是"[object Object]"
稍微修改一下代码:
const obj = {
toString(){
return 'mmm';
};
obj[obj] = 1;
console.log(obj);
输出结果是:{'mmm':1}
正常会调用原生Object.prototype.toString()
方法,但是在obj对象自身添加了toString
方法,实现了对原型的覆盖,所以看到的结果是:
{'mmm':1}