深入理解JavaScript系列(18):面向对象编程之E(4)

然而,即使认为“哈希”可能有一个“原型”(例如,在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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgfgzd.html