blog
blog copied to clipboard
为什么应该避免修改内置对象的原型链?
写 JavaScript 的应该都知道,我们应该避免修改内置对象(例如 Object、Function)的原型链,但今天一个同事问我:为什么要避免这样做?
于是我给他讲了我自己经历过的一件事。
当时我在开发一个工具库的时候,写了如下这段代码:
function Watching (config) {
// config.watch 是一个可选项,所以没有的时候就给一个默认值
var watchingNode = document.querySelector(config.watch || '.watch-node')
watchingNode.addEventListener(...)
// ...
}
代码上线之后,有用户反馈在 Firefox 浏览器下点了某个按钮没有反应,然后我就用 Firefox 打开那个网页去调试,发现在执行到上面代码的第三行的时候报了个奇怪的错误,调试了一下,发现 config.watch 被传了一个函数进来。
我心想我知道 watch 这个属性应该传一个字符串,所以不会传个函数进来啊,然后我翻遍了所有调用这个构造函数的代码,愣是没找到给 watch 传了个函数的地方。
后来在我的反复调试之下,我才发现——在 Firefox 里,Object.prototype.watch 居然是一个函数(见 MDN),所以当我不传 config.watch 的时候,读取 config.watch 就读到了原型链上的这个 watch 函数,才有了上面的报错。
从此以后,我就知道为什么要避免修改内置对象的原型链了。
某种程度上也可以说是命名的问题,取的名字有很大概率会重名(现有的、将来的关键字&函数名)。
比如,加一个前缀:
Object.prototype._watch = function () {
// your code here
}
重名的概率就要小很多啦
@leopku 是的,但我们都无法保证我们取的名字是独一无二的 😂