如:
var
o
=
new
Complex(
1
,
2
);
o.constructor == Complex; // 估算为 true
o.constructor == Complex; // 估算为 true
上一节提到的 Complex 类(或其他任何类)的实例并不每人拥有一个唯一的 constructor 属性;相反的,该属性其实是从他的 prototype 对象继承来的。
上一节提到,JavaScript 为每一个 constructor function 生成一个原型对象, 该对象指定为这个 constructor 的 prototype 属性。而我们没有提到的是:这个 prototype 属性在一开始其实不是空的。当它被创建时,已经包含了一个 constructor 属性,指向该 constructor function.
也就是说,对于任何函数 f , 都有
f.prototype.constructor
==
f
(除非我们把它手工指定为其他的)。
因为 constructor function 定义了对象的类别,constructor 属性对于判别对象的类型非常有用。如:
if
((
typeof
o
==
"
object
"
)
&&
(o.constructor
==
Date))
// Then do something with the Date object
// Then do something with the Date object
需要注意的是,constructor 属性并不一定能保证有的。比如某个类的作者可能覆盖掉原型对象里的 constructor 为一个新的。那么新的对象就可能没有有效的 constructor 属性。
8.7.2 toString() 方法
JavaScript 会在需要的时候自动调用该方法。比如在 alert() 或 document.write() 中。
因为默认的 toString() (继承来的) 通常不会输出太多有用的信息,我们在设计类的时候常常需要自己覆盖该方法。比如,一个数组转变为 string 时,通常我们可以把它转变为元素列表组成的字符串;函数转变的时候可以变为他的源代码等。
例子:
Circle.prototype.toString
=
function
( ) {
return " [Circle of radius " + this .r + " , centered at ( "
+ this .x + " , " + this .y + " ).] " ;
}
return " [Circle of radius " + this .r + " , centered at ( "
+ this .x + " , " + this .y + " ).] " ;
}
内建的 object 的 toString() 方法也揭示了一些有用东西,通常是下列形式:
[object 类型名]
这个类型名通常就是其 constructor function 的名字。比如 "Array", "Function", "Date", "Math", "Error". 客户端的 JavaScript 对象以及其他的 JavaScript 实现里定义的类型, 会显示为类似于:"Window", "Document", "Form" 这些。用户自定义的类,总是显示为 "Object".
这里的“类型名” 提供了 typeof 所不能提供的信息。 typeof 对所有对象返回 "Object" 或 "Function".
如果要知道对象原有的 toString() 内容,仅仅这样是不够的:
o.toString()
//
May invoke a customized toString( ) method for the object
因为对象常常实现自己的 toString(). 我们可以这样:
Object.prototype.toString.apply(o);
//
Always invokes the default toString( )
我们现在可以利用这个功能来写一个增强的 "type of" 函数:
//
An enhanced "type of" function. Returns a string that describes the
// type of x. Note that it returns "Object" for any user-defined object types.
function Typeof(x) {
// Start with the typeof operator
var t = typeof x;
// If the result is not vague, return it
if (t != " object " ) return t;
// Otherwise, x is an object. Get its class value to try to
// find out what kind of object it is.
var c = Object.prototype.toString.apply(x); // Returns "[object class]"
c = c.substring( 8 , c.length - 1 ); // Strip off "[object" and "]"
return c;
}
// type of x. Note that it returns "Object" for any user-defined object types.
function Typeof(x) {
// Start with the typeof operator
var t = typeof x;
// If the result is not vague, return it
if (t != " object " ) return t;
// Otherwise, x is an object. Get its class value to try to
// find out what kind of object it is.
var c = Object.prototype.toString.apply(x); // Returns "[object class]"
c = c.substring( 8 , c.length - 1 ); // Strip off "[object" and "]"
return c;
}
8.7.3 toLocaleString() 方法
ECMAScript v3 以及 JavaScript 1.5 中,Object 类定义了 toLocaleString() 方法, 但是仅仅提供了跟 toString() 同样的实现。但一些子类定义了本地化的信息,比如 ECMAScript v3 里, Array, Date, Number 都实现了 toLocaleString() 方法。
8.7.4 valueOf() 方法
valueOf 很像 toString(), 但是在 JavaScript 需要转换对象为基本类型(primitive type) 而不是 string 时。比如一个 number. 根据定义,object 是没有等价的基础类型的表示的。所以 Object 对 valueOf 的实现是简单的返回对象本身。这样一来,Number 和 Boolean 就能够自动的继承得到正确的值。这就是为什么 Number 和 Boolean 类型的对象能够像他们的简单值那样工作的原因。
有些类对它定义 valueOf 是有意义的,比如可以定义 Complex 类的这个函数返回他的实数部分,就好像虚数部分不存在一样。这样在实数环境里就可以简单的进行计算了。比如:
var
a
=
new
Complex(
5
,
4
);
var b = new Complex( 2 , 1 );
var c = Complex.subtract(a,b); // c is the complex number {3,3}
var d = a - b; // d is the number 3
var b = new Complex( 2 , 1 );
var c = Complex.subtract(a,b); // c is the complex number {3,3}
var d = a - b; // d is the number 3
需要注意的是,在某些情况下,toValue() 会比 toString() 有更高的优先级被调用。所以需要得到字符串的场合有时需要严格的调用 toString().
比如:
alert(
"
c =
"
+
c);
//
使用 valueOf(), 显示 "c = 3"
alert( " c = " + c.toString()); // 显示 "c = {3,3}"
alert( " c = " + c.toString()); // 显示 "c = {3,3}"
8.7.5 hasOwnProperty() 方法
如果该对象定义了指定名称的非继承的属性,那么返回 true. 否则为 false.
var
o
=
new
Object( );
o.hasOwnProperty( " undef " ); // false: the property is not defined
o.hasOwnProperty( " toString " ); // false: toString is an inherited property
Math.hasOwnProperty( " cos " ); // true: the Math object has a cos property
o.hasOwnProperty( " undef " ); // false: the property is not defined
o.hasOwnProperty( " toString " ); // false: toString is an inherited property
Math.hasOwnProperty( " cos " ); // true: the Math object has a cos property
8.7.6 propertyIsEnumerable() 方法
如果对象定义了指定名称的属性,并且该属性能够通过 for/in 循环显示出来,那么返回 true. 否则返回 false.
var
o
=
{ x:
1
};
o.propertyIsEnumerable( " x " ); // true: property exists and is enumerable
o.propertyIsEnumerable( " y " ); // false: property doesn't exist
o.propertyIsEnumerable( " valueOf " ); // false: property isn't enumerable
o.propertyIsEnumerable( " x " ); // true: property exists and is enumerable
o.propertyIsEnumerable( " y " ); // false: property doesn't exist
o.propertyIsEnumerable( " valueOf " ); // false: property isn't enumerable
在 ECMAScript 标准中,该方法只考虑对象自身的属性而不考虑继承的属性。这使得该方法的使用价值降低了。因为返回 false 可能是因为该属性不能枚举出来,或者是一个继承的属性。
8.7.7 isPrototypeOf() 方法
判断某对象是否为另一对象的原型。这个方法的效果和使用 constructor 属性类似。比如:
var
o
=
new
Object( );
Object.prototype.isPrototypeOf(o); // true: o.constructor == Object
Object.isPrototypeOf(o); // false
o.isPrototypeOf(Object.prototype); // false
Function.prototype.isPrototypeOf(Object); // true: Object.constructor == Function
Object.prototype.isPrototypeOf(o); // true: o.constructor == Object
Object.isPrototypeOf(o); // false
o.isPrototypeOf(Object.prototype); // false
Function.prototype.isPrototypeOf(Object); // true: Object.constructor == Function
(第八章完)