我理解这个问题可能已在其他Q& A(例如How does JavaScript .prototype work?问题)中被触及,但(我希望!)这是一个更具体的问题围绕为什么有些& #34;覆盖"在某些情况下使用.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());
以上示例将提醒" true",根据ejohn.org网站的示例和解释,这是有道理的,但随后这也有效,完全与我认为不可能的相矛盾在上面的代码:
var _send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(){
alert("Overridden!");
_send.apply(this, arguments);
};
两者如何才能成立?一个是准确没有被覆盖,另一个是?据我所知,它们都是对象,swingSword
和send
函数都是函数?那么我们如何覆盖XMLHttpRequest
send
函数,而不是Ninja
swingSword
函数呢?
提前感谢您的任何见解和帮助!
答案 0 :(得分:1)
JavaScript中没有真正的覆盖概念。使用new
进行实例化时,只需在新对象中引用原型对象(如__proto__
),对对象中不存在的属性的任何访问都将路由到原型对象。仍然是"构造函数"函数被调用,因此您可以在调用者使用之前修改新对象。
在构造函数中,新对象被引用为this
,如您所知。在您的情况下,您实际上会将swingSword
函数添加到之前不存在的新对象中。如果你没有,那么对swingSword
属性(函数)的所有访问都将回退到原型。换句话说,你"覆盖"原型功能,而不是相反!
确保您了解执行顺序。仅仅因为在定义构造函数之后在原型上设置函数并不意味着它优先。实际上,使用new
时会执行构造函数。
现在应该清楚为什么第二种情况有效; XHR的构造函数不会创建发送函数,因此将始终使用原型对象上的函数。由于您在原始原型上更换它,您基本上已经覆盖了#34;它。顺便说一句,这就是原件保存在_send
变量中的原因;你不会引用它或以其他方式恢复它!