问题是不言自明的。我知道可以扩展原始数据类型,string
但是可以覆盖它吗?
这是一个在采访中被问到的问题。
不,你不能覆盖任何东西。EcmaScript定义了原始类型 Undefined
、Null
、Boolean
、Number
和String
; 这些是内部的,无论您在做什么(例如覆盖全局String
构造函数)都将使用它们。文字的类型转换和评估不依赖于任何公共函数,而仅使用这些内部类型和为它们指定的算法。
当然,如果有人使用String(myval)
而不是""+myval
分配给全局String
变量进行字符串强制,则会对该代码产生影响。任何内部使用仍将指向“旧”功能。
如果您在谈论原始类型的原型对象(当用作objects时),它们也不是可覆盖的。您可以扩展这些对象,但是一旦您分配给 eg Number.prototype
,您就失去了对实际的原始数字原型对象的引用。Number 构造函数的示例规范:
新建对象的 [prototype] 设置为原始Number 原型对象,即( 15.7.3.1 )的初始值
Number.prototype
是的(编辑:几乎)。打开 Javascript 控制台(如果您使用的是 Chrome,请按 F12)并输入
String = function(){alert('bang!')};
您可以覆盖(编辑:几乎)Javascript 中的所有内容——甚至是window
全局上下文!evil.js是一个使用此技巧尽可能重写许多本机对象的库。
不用说,这是极其危险的。我执行了String
上面的重新映射代码,自从写下它以来,我已经导致了 520 多个 Javascript 错误(我已经看到“砰”的警报很多次了)。原生对象无处不在,您不应该修改它们,以防 3rd 方代码以您不知道的方式依赖它们。这是 Prototype.js 失去人气的原因之一——因为它对原生对象的扩展通常会与其他代码的预期背道而驰。
您可以扩展本机类型的原型。
String.prototype.moo = function() {
console.log( 'Moo!' )
};
'Cow says'.moo();
>> "Moo!"
但是,除非您覆盖对整个对象的引用,否则您不能直接覆盖内置类型的构造函数:
String = function() {
console.log( 'Custom function.' )
};
new String( 'Hello!' );
>> "Custom function."
>> String {} // now you've broken your website ;)
...但仍然:
'Wat?!'
>> "Wat?!" // you can still create strings by typing letters in quotes
所以......答案是“是但不是”。您可以使用本机类型(Number
, Date
, String
...),但您不能完全从头开始重新定义它们。它们是您正在使用的 JS 引擎的一部分(很可能是本机 C++ 代码),这带来了一些限制。
像这样可能,但你必须总是成功而没有副作用。不是好的做法。
function Array() {
var obj = this;
var ind = 0;
var getNext = function(x) {
obj[ind++] setter = getNext;
if (x) alert("Data stolen from array: " + x.toString());
};
this[ind++] setter = getNext;
}
var a = ["private stuff"];
// alert("Data stolen from array: private stuff");