blog icon indicating copy to clipboard operation
blog copied to clipboard

为什么应该避免修改内置对象的原型链?

Open lmk123 opened this issue 8 years ago • 2 comments

写 JavaScript 的应该都知道,我们应该避免修改内置对象(例如 ObjectFunction)的原型链,但今天一个同事问我:为什么要避免这样做?

于是我给他讲了我自己经历过的一件事。

当时我在开发一个工具库的时候,写了如下这段代码:

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 函数,才有了上面的报错。

从此以后,我就知道为什么要避免修改内置对象的原型链了。

lmk123 avatar Feb 22 '17 10:02 lmk123

某种程度上也可以说是命名的问题,取的名字有很大概率会重名(现有的、将来的关键字&函数名)。

比如,加一个前缀:

Object.prototype._watch = function () {
    // your code here
}

重名的概率就要小很多啦

leopku avatar Mar 22 '17 10:03 leopku

@leopku 是的,但我们都无法保证我们取的名字是独一无二的 😂

lmk123 avatar Mar 22 '17 11:03 lmk123