有没有一种方法可以在JavaScript中隔离本地对象扩展?

3
您可以在JavaScript中扩展原生对象。例如,sugar.js 扩展了数组、字符串和函数等内容。本地对象扩展非常有用,但固有地破坏了封装 - 即如果有人使用相同的扩展名称(覆盖另一个扩展),则会出现问题。
如果您可以为特定范围扩展对象,那将是非常好的。例如,在Node.js中能够执行以下操作:
// myExtension1.js
Object.prototype.x = 5

exports.speak = function() {
  var six = ({}.x+1)
  console.log("6 equals: "+six)
}

// myExtension2.js
Object.prototype.x = 20

exports.speak = function() {
  var twenty1 = ({}.x+1)
  console.log("21 equals: "+twenty1)
}

并且使其正常工作:

// test.js

var one = require('myExtension1')
var two = require('myExtension2')

one.speak(); // 6 equals: 6
two.speak(); // 21 equals: 21

当然,在实际中,第一个输出将是“6等于:21”。

是否有任何机制可以通过任何机制实现这一点?我感兴趣的机制包括:

  • 纯JavaScript
  • Node.js
  • C++扩展到Node.js

有人能排除一个 Node.js 的 C++ 扩展吗? - B T
1
不太对,那是在问如何定义一个非枚举属性。这个问题是在问如何在模块之间隔离本地对象。 - B T
@Bergi 如果我没错的话,能否把顶部的注释删除掉? - B T
是的,抱歉我过于匆忙地投了关闭票 - 我应该更好地阅读问题。实际上,我很想拥有这样的模块范围原型扩展,但它们似乎总是不可能,所以我从未提出过 - +1! - Bergi
2个回答

2
很遗憾,目前在node中你无法做到这一点,因为node在模块之间共享相同的内置对象。这很糟糕,因为它可能会带来意想不到的副作用,就像过去浏览器历史记录中发生的那样,这就是为什么现在每个人都在大喊“不要扩展内置对象”的原因。
其他常见的commonJS环境更多地遵循最初的commonJS规范,所以你不会共享内置对象,而是每个模块都有自己的内置对象。例如,在构建Firefox插件的Mozilla SDK中,Jetpack就是这样工作的:因此,内置对象是每个模块独立的,如果你扩展了其中一个,就不会冲突。
总之,我认为现在扩展内置对象并不是真正必要的,应该避免这样做。

有关CommonJS规范的有趣信息。我不同意“不是必要的”这种观点,因为闭包、对象和任何非汇编语言都“不是必要的”。虽然它确实很有用。 - B T
这就是我的观点,我认为这完全没有用。只是为了 shim,但 shim 也可以是全局的。同时,我在多年中从 JS 的 OOP 方法转向了更多的函数式方法,所以我的观点也受到了这方面的影响。 - ZER0

0
这是不可能的,因为本地类型只有一个原型来源。一般来说,我会劝阻对本地类型的原型进行修改。不仅会限制你的可移植性(正如你所指出的),而且你可能会无意中覆盖现有属性或未来的属性。这还会在你的代码中引入很多"魔法",让未来的维护者难以找到问题。唯一真正的例外是 polyfil。如果你的环境还没有实现某个新功能,那么可以使用 polyfil 来提供该功能。

你是否排除了Node.js扩展或仅使用纯JavaScript? - B T
可能有一个针对此的Node.js扩展,但我猜测可能没有。你可能需要研究一下混合(mixins)来实现你所说的行为类型。 - Evan Borden
我其实在想,是否有可能自己制作一个用于此的Node.js扩展。 - B T

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接