然而,即使认为“哈希”可能有一个“原型”(例如,在Ruby或Python里委托哈希对象的类),在ECMAScript里,这个术语也是不对的,因为2个表示法之间没有语义上的区别(即用点表示法a.b和a["b"]表示法)。
在ECMAScript中的“property属性”的概念语义上和"key"、数组索引、方法没有分开的,这里所有对象的属性读写都要遵循统一的规则:检查原型链。
在下面Ruby的例子中,我们可以看到语义上的区别:
复制代码 代码如下:
a = {}
a.class # Hash
a.length # 0
# new "key-value" pair
a['length'] = 10;
# 语义上,用点访问的是属性或方法,而不是key
a.length # 1
# 而索引器访问访问的是hash里的key
a['length'] # 10
# 就类似于在现有对象上动态声明Hash类
# 然后声明新属性或方法
class Hash
def z
100
end
end
# 新属性可以访问
a.z # 100
# 但不是"key"
a['z'] # nil
ECMA-262-3标准并没有定义“哈希”(以及类似)的概念。但是,有这样的结构理论的话,那可能以此命名的对象。
对象转换
将对象转化成原始值可以用valueOf方法,正如我们所说的,当函数的构造函数调用做为function(对于某些类型的),但如果不用new关键字就是将对象转化成原始值,就相当于隐式的valueOf方法调用:
复制代码 代码如下:
var a = new Number(1);
var primitiveA = Number(a); // 隐式"valueOf"调用
var alsoPrimitiveA = a.valueOf(); // 显式调用
alert([
typeof a, // "object"
typeof primitiveA, // "number"
typeof alsoPrimitiveA // "number"
]);
这种方式允许对象参与各种操作,例如:
复制代码 代码如下:
var a = new Number(1);
var b = new Number(2);
alert(a + b); // 3
// 甚至
var c = {
x: 10,
y: 20,
valueOf: function () {
return this.x + this.y;
}
};
var d = {
x: 30,
y: 40,
// 和c的valueOf功能一样
valueOf: c.valueOf
};
alert(c + d); // 100
valueOf的默认值会根据根据对象的类型改变(如果不被覆盖的话),对某些对象,他返回的是this——例如:Object.prototype.valueOf(),还有计算型的值:Date.prototype.valueOf()返回的是日期时间:
复制代码 代码如下:
var a = {};
alert(a.valueOf() === a); // true, "valueOf"返回this
var d = new Date();
alert(d.valueOf()); // time
alert(d.valueOf() === d.getTime()); // true
此外,对象还有一个更原始的代表性——字符串展示。 这个toString方法是可靠的,它在某些操作上是自动使用的:
复制代码 代码如下:
var a = {
valueOf: function () {
return 100;
},
toString: function () {
return '__test';
}
};
// 这个操作里,toString方法自动调用
alert(a); // "__test"
// 但是这里,调用的却是valueOf()方法
alert(a + 10); // 110
// 但,一旦valueOf删除以后
// toString又可以自动调用了
delete a.valueOf;
alert(a + 10); // "_test10"
Object.prototype上定义的toString方法具有特殊意义,它返回的我们下面将要讨论的内部[[Class]]属性值。
和转化成原始值(ToPrimitive)相比,将值转化成对象类型也有一个转化规范(ToObject)。
一个显式方法是使用内置的Object构造函数作为function来调用ToObject(有些类似通过new关键字也可以):
复制代码 代码如下:
var n = Object(1); // [object Number]
var s = Object('test'); // [object String]
// 一些类似,使用new操作符也可以
var b = new Object(true); // [object Boolean]
// 应用参数new Object的话创建的是简单对象
var o = new Object(); // [object Object]
// 如果参数是一个现有的对象
// 那创建的结果就是简单返回该对象
var a = [];
alert(a === new Object(a)); // true
alert(a === Object(a)); // true