为什么等式一样,返回结果不一样?

新手上路,请多包涵

刚在阮一峰大神书中看到如下代码,对于最后一个结果是 false 很疑惑。

var obj = {};
obj.hasOwnProperty('toString') // false

// 覆盖掉继承的 hasOwnProperty 方法
obj.hasOwnProperty = function () {
  return true;
};
obj.hasOwnProperty('toString') // true

Object.prototype.hasOwnProperty.call(obj, 'toString') // false(这里有疑惑)

自己一直都认为

Object.prototype.hasOwnProperty.call(obj, 'toString') 
// 等价于
obj.hasOwnProperty('toString') 

然后再chrome 的console里试了下

var obj = {};
obj.hasOwnProperty('toString') === Object.prototype.hasOwnProperty.call(obj, 'toString')

// log: true

这两种表达式是全等的呀,明明只是写法不同。
所以阮大神的那个代码里,最后一个到底为什么是false??

求大神解答,谢谢。

阅读 3.1k
5 个回答

call方法只是调用一个方法,只不是是调用的时候把this设置成了你传入的第一个参数。

Object.prototype.hasOwnProperty.call(obj, 'toString') 
// 怎么可能等价于?他们调用的函数是两个完全不同的函数!
obj.hasOwnProperty('toString') 

下面这样:
var obj = {};
obj.func = function(){
    console.log('func of obj')
}
function func(){
    console.log('func of global');
}

func.call(obj)//执行的还是全局的func

对象查找属性是沿着原型链的,在查找一个属性的时候,会首先查看对象自己有没有这个属性,如果没有就会去对象的原型链上去查找,如果没有就去对象的原型链的原型链查找...

hasOwnProperty是用来判断对象自己是否含有某个属性的函数,不会去查找原型链,我们知道hasOwnProperty是定义在Object.prototype上的。

var obj = {};
obj.hasOwnProperty('toString')

此时obj自身不包含任何属性和方法,所以对obj.hasOwnProperty求值的时候,会去查找原型链,最后在原型上找到了该方法;
因为toString不是obj自身含有的方法,是原型链中的方法,所以返回false

// 覆盖掉继承的 hasOwnProperty 方法
obj.hasOwnProperty = function () {
  return true;
};
obj.hasOwnProperty('toString')

此时obj有一个名字为hasOwnProperty的属性,这个属性的值是一个方法,当对obj.hasOwnProperty求值的时候,因为obj本身含有这个属性,所以不会去原型链上查找,这个函数的作用就是返回true,所以结果是true

Object.prototype.hasOwnProperty.call(obj, 'toString')

此时你调用的是Object.prototype.hasOwnProperty这个方法,obj自身是不包含toString属性的,所以返回false。

var obj = {};
obj.hasOwnProperty('toString') === Object.prototype.hasOwnProperty.call(obj, 'toString')

obj.hasOwnProperty('toString')的结果和Object.prototype.hasOwnProperty.call(obj, 'toString')的结果都是falsefalse === false的结果是true,你应该比较两个函数,而不是函数的返回值;
另外当你没有在obj上定义hasOwnProperty的时候,对obj.hasOwnPeoperty求值的结果就是在原型链中定义的同名函数,也就是Object.prototype.hasOwnProperty,所以你即使使用obj.hasOwnProperty === Object.prototype.hasOwnProperty结果仍然是true

你需要在obj上定义hasOwnProperty之后再去判断两个函数是否相等,此时就不相同了。

var obj = {}
obj.hasOwnProperty = function() {return true}
obj.hasOwnProperty === Object.prototype.hasOwnProperty // false

obj.hasOwnProperty('toString') === Object.prototype.hasOwnProperty.call(obj, 'toString')
你这么写是相等,但是因为两个都是false,才返回的true.

var obj = {};
obj.hasOwnProperty方法继承于Object.prototype,用于检查对象是否具有自己定义的属性
obj没有toString这个属性,所以obj.hasOwnProperty('toString')为 false


obj.hasOwnProperty = function () {
return true;
}
这里定义了一个obj 的自有属性 hasOwnProperty,遮蔽了obj的原型对象 Object.prototype 的 hasOwnProperty
因此obj.hasOwnProperty('toString')顺着原型链先找到了自有属性,所以结果为 true


Object.prototype.hasOwnProperty.call(obj, 'toString'),是用了Object.prototype上的hasOwnProperty属性,不是用的自身属性,所以为 false


所以obj.hasOwnProperty('toString') 和 Object.prototype.hasOwnProperty.call(obj, 'toString')
都是 false
自然是相等的。。。。

因为call方法把hasOwnProperty方法定义到了prototype里,所以会返回false。

var obj = {};
obj.hasOwnProperty('toString') === Object.prototype.hasOwnProperty.call(obj, 'toString')

这个之所以返回true,是因为两个都是object类型,而且都没定义,值都是空。

var obj = {};
obj.hasOwnProperty('toString123') === Object.prototype.hasOwnProperty.call(obj, 'toString456')

这个也是相等的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题