var getClass = Object.prototype.toString;
Object = Number;
var foo = new Object;
alert([foo, getClass.call(foo)]); // 0, "[object Number]"
var bar = {};
// Rhino, SpiderMonkey 1.7中 - 0, "[object Number]"
// 其它: still "[object Object]", "[object Object]"
alert([bar, getClass.call(bar)]);
// Array也是一样的效果
Array = Number;
foo = new Array;
alert([foo, getClass.call(foo)]); // 0, "[object Number]"
bar = [];
// Rhino, SpiderMonkey 1.7中 - 0, "[object Number]"
// 其它: still "", "[object Object]"
alert([bar, getClass.call(bar)]);
// 但对RegExp,字面量的语义是不被改变的。 semantics of the literal
// isn't being changed in all tested implementations
RegExp = Number;
foo = new RegExp;
alert([foo, getClass.call(foo)]); // 0, "[object Number]"
bar = /(?!)/g;
alert([bar, getClass.call(bar)]); // /(?!)/g, "[object RegExp]"
正则表达式字面量和RegExp对象
注意,下面2个例子在第三版的规范里,正则表达式的语义都是等价的,regexp字面量只在一句里存在,并且再解析阶段创建,但RegExp构造器创建的却是新对象,所以这可能会导致出一些问题,如lastIndex的值在测试的时候结果是错误的:
复制代码 代码如下:
for (var k = 0; k < 4; k++) {
var re = /ecma/g;
alert(re.lastIndex); // 0, 4, 0, 4
alert(re.test("ecmascript")); // true, false, true, false
}
// 对比
for (var k = 0; k < 4; k++) {
var re = new RegExp("ecma", "g");
alert(re.lastIndex); // 0, 0, 0, 0
alert(re.test("ecmascript")); // true, true, true, true
}
注:不过这些问题在第5版的ES规范都已经修正了,不管是基于字面量的还是构造器的,正则都是创建新对象。
关联数组
各种文字静态讨论,JavaScript对象(经常是用对象初始化器{}来创建)被称为哈希表哈希表或其它简单的称谓:哈希(Ruby或Perl里的概念), 管理数组(PHP里的概念),词典 (Python里的概念)等。
只有这样的术语,主要是因为他们的结构都是相似的,就是使用“键-值”对来存储对象,完全符合“关联数组 ”或“哈希表 ”理论定义的数据结构。 此外,哈希表抽象数据类型通常是在实现层面使用。
但是,尽管术语上来描述这个概念,但实际上这个是错误,从ECMAScript来看:ECMAScript只有一个对象以及类型以及它的子类型,这和“键-值”对存储没有什么区别,因此在这上面没有特别的概念。 因为任何对象的内部属性都可以存储为键-值”对:
复制代码 代码如下:
var a = {x: 10};
a['y'] = 20;
a.z = 30;
var b = new Number(1);
b.x = 10;
b.y = 20;
b['z'] = 30;
var c = new Function('');
c.x = 10;
c.y = 20;
c['z'] = 30;
// 等等,任意对象的子类型"subtype"
此外,由于在ECMAScript中对象可以是空的,所以"hash"的概念在这里也是不正确的:
复制代码 代码如下:
Object.prototype.x = 10;
var a = {}; // 创建空"hash"
alert(a["x"]); // 10, 但不为空
alert(a.toString); // function
a["y"] = 20; // 添加新的键值对到 "hash"
alert(a["y"]); // 20
Object.prototype.y = 20; // 添加原型属性
delete a["y"]; // 删除
alert(a["y"]); // 但这里key和value依然有值 – 20
请注意, ES5标准可以让我们创建没原型的对象(使用Object.create(null)方法实现)对,从这个角度来说,这样的对象可以称之为哈希表:
复制代码 代码如下:
var aHashTable = Object.create(null);
console.log(aHashTable.toString); // 未定义
此外,一些属性有特定的getter / setter方法,所以也可能导致混淆这个概念:
复制代码 代码如下:
var a = new String("foo");
a['length'] = 10;
alert(a['length']); // 3