仅在当前作用域中扩展基元 [英] Extend a Primitive only in current scope
问题描述
是否可以复制像 String
的原语,以便只能在当前函数中扩展?
Is it possible to copy a primitive like String
so it can be extended only in the current function?
var foo = function() {
var String = // somehow clone String (the primitive function)
String.prototype.first = function() { return this.charAt(0) };
return 'abc'.first();
}
foo(); // returns 'a'
'abc'.first(); // returns TypeError "abc".first is not a function
解决方案必须复制似乎不可能,或者在函数完成后销毁新方法...
The solution must either copy the primitive which doesn't seem possible, or destroy the new method after the function is complete...
推荐答案
String
是一个全局变量,如果您更改它或添加到它的原型,那么更改是按照定义全局的。因此,要还原更改,您必须还原它们。
String
is a global and if you change it or add to its prototype, then the changes are by definition global. So to revert the changes, you have to revert them.
通常,会尝试派生自定义子类并向其中添加新的原型方法,但内置类型像String一样非常难以子类化,即使你可以用 MyString('abc')来调用它。first()
。
Normally one would try to derive a custom subclass and add the new prototype method to it, but built-in types like String are notoriously hard to subclass, and even if you could you'd have to call it with something like MyString('abc').first()
.
您的问题来自于您错误的增加 String
原型的想法。 污染原型从不是一个好主意。我理解你的想法,通过某种方式删除它添加和使用它后,真正的快速,但这是不现实的,和 setTimeout
方法是一个可怕的,不可靠的黑客。
Your problems stem from your misguided notion of augmenting the String
prototype. It's never a good idea to pollute prototypes. I understand your idea of dealing with that by somehow removing it real quick after adding it and using it, but that's not realistic, and the setTimeout
approach is a horrible, unreliable hack.
但是,如果你真的坚持添加到 String
原型,那么一个想法是将所有新的实例方法添加到一个不太可能与事物碰撞的单一属性。让我们把它叫做
Utils
。我们希望能够致电
However, if you really insist on adding to the String
prototype, then one idea is to add all your new instance methods to a single property which is less likely to collide with things. Let's call it Utils
. We would want to be able to call
'abc'.Utils.first()
但是我们如何才能使这项工作?我们在 Utils
属性中定义一个getter,它返回方法的哈希值。使用getter(而不是 value
)为我们提供了 this
,我们可以传递给方法使用 bind
。
But how can we make this work? We define a getter on the Utils
property which returns a hash of the methods. Using a getter (instead of value
) provides us with the this
, which we can pass along to the methods using bind
.
Object.defineProperty(String.prototype, 'Utils', {
get: function() {
return {
first: function() { return this.charAt(0); }.bind(this)
};
}
});
> 'abc'.Utils.first()
< "a"
这篇关于仅在当前作用域中扩展基元的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!