2016-02-02 86 views
0

我知道这个问题可能在其他Q & A(如How does JavaScript .prototype work?问题)中被触及,但是(我希望!)这是一个更具体的问题,为什么在某些情况下使用.prototype有些“覆盖”有些则没有。为了帮助说明(从ejohn.org为例):为什么一些原型函数覆盖工作而另一些不覆盖?

function Ninja() { 
    this.swingSword = function() { return true; }; 
}; 
Ninja.prototype.swingSword = function() { return false; }; 

var my_ninja = new Ninja(); 
alert(my_ninja.swingSword()); 

上面的例子会提醒“真”,根据ejohn.org网站的例子,说明这是有道理的,但随后这个作品也完全矛盾根据上面的代码,我认为是不可能的:

var _send = XMLHttpRequest.prototype.send; 
XMLHttpRequest.prototype.send = function(){ 
    alert("Overridden!"); 
    _send.apply(this, arguments); 
}; 

两者如何都能成立?一个准确地不被覆盖,另一个是?据我所知,它们都是对象,并且swingSwordsend函数都是函数?那么我们如何覆盖XMLHttpRequestsend函数,而不是NinjaswingSword函数呢?

预先感谢您的任何见解和帮助!

回答

1

在JavaScript中没有重写的真正概念。当使用new实例化时,原型对象仅在新对象中引用(如__proto__),而对对象中不存在的属性的任何访问都将被路由到原型对象。仍然调用“构造函数”函数,以便在调用者使用它之前有机会修改新对象。如你所知,在构造函数中,新对象被引用为this。在你的情况下,你实际上会将swingSword函数添加到之前不存在的新对象中。如果没有,则对swingSword属性(函数)的所有访问都将回退到原型。换句话说,你“覆盖”原型功能,而不是相反!

确保您了解执行顺序。仅仅因为你在定义构造函数之后在原型上设置函数并不意味着它优先。实际上,构造函数在使用new时执行。

现在应该清楚为什么第二种方案有效; XHR的构造函数不会创建发送函数,因此始终会使用原型对象上的函数。既然你把它取代原来的原型,你基本上“覆盖”了它。顺便说一下,这就是为什么原始文件保存在_send变量中;否则您将无法引用它或恢复它!

+0

哦,我明白了!所以在XHR构造函数中没有创建'send'函数!一切都变得更有意义了,谢谢!那么接下来是一个小的分拆问题,那么如何知道可用的函数是否是构造函数创建的或以其他方式创建的呢? –

+1

@ChrisKempen好问题!幸运的是,它有一个简单的答案:使用['hasOwnProperty'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty)。 – tne

+0

啊啊,谢谢!我的头痛终于消散了! +1 –