曾经对 hasOwnProperty() 方法和 in 操作符感到困惑,这回看书看到,就在这里再次归纳总结一下
-----------------------------------------------------------------------------------------
首先要知道, hasOwnProperty 用以检测 “对象是否拥有某个属性”, 而 in 用以检测 “对象是否可以使用某个属性”。
一个是 “拥有”, 一个是 “可用”。
某些情况下,两者效果一致,可以混用:
// 创建一个自定义对象 var obj_1 = { // 对象定义了自己的属性 sayHi: function() { return "Hi~ I'm an object"; } }
obj_1.hasOwnProperty("sayHi"); // 返回 true "sayHi" in obj_1; // 返回 true
都返回 true。
但有时候又不一样:
// 还是自定义对象 var obj_2 = { // 也定义了自己的方法 sayHi: function() { return "Hi~ I'm another object"; } }
obj_2.hasOwnProperty("toString"); // 返回 false "toString" in obj_2; // 返回 true
这里的 hsaOwnProperty 方法不再返回 true。
稍微对比前后两次使用情况,我们就可以发现其中的差别:
前一个 hasOwnProperty 检测的是 sayHi 方法,由对象自己定义,结果返回 true。
后一个 hasOwnProperty 检测的是 toString 方法,来自基类(Object),结果返回 false。
产生什么结果是跟属性的来源有关么? 不是:
// 又是自定义对象 var obj_3 = { // 并且重写了 toString 方法 toString: function() { return "This is function \"toString\" which overridden by obj_3"; } } obj_3.hasOwnProperty("toString"); // 返回 true "toString" in obj_3; // 返回 true
这个 toString 仍是来源于基类,只是它重写。而我们知道, 重写会在实例上新建一个属性。
书上看到的解释大概是这样:
每当程序需要读取某个对象的某个属性时, 解析器都会进行搜索。 搜索首先会从对象实例本身开始, 如果找到, 则返回该属性的值; 如果找不到, 则往上(父类原型)继续搜索, 直至最顶层的基类(原型)。如果搜遍整个原型链都找不到, 则返回 undefined。
使用 hasOwnProperty 方法时,搜索只会在对象实例上进行, 找不到就直接返回 false。
而执行 in 时,解析器的搜索不再限于对象实例, 只有在搜遍整个原型链都找不到的时候才会返回 false。
这就是两者的差别。
总结一下:
hasOwnProperty 用以检测“对象是否拥有某个属性”, 这个属性可以由对象自身定义,也可以由继承的属性重写而来。
in 操作符用以检测“某个属性是否对对象可用”, 这个属性可以是对象自身定义所得, 也可以是来自于继承, 无需重写。