问题
今天同事问了一个问题:为什么Object.prototype.toString()为什么可以改变指向?例如:
var obj = new Object();
console.log( obj.toString() );//->[object Object]
//将Object.prototype.toString指向自定义的函数
Object.prototype.toString=function(){
return "my self toString";
};
console.log( obj.toString() );//->my self toString
我们从上程序的输出结果可以看出Object.prototype.toString指向了我们自定义的函数。
原因
经过一番查询才知道Object.prototype.toString属性的属性被定义了可写的,也就是可以改变指向。
JavaScript中属性(property)有三个属性:
1.writable。该property是否可写。
2.enumerable。当使用for/in语句时,该property是否会被枚举。
3.configurable。该property的属性是否可以修改,property是否可以删除。
JavaScript中还提供了设置和获取property的属性。
设置prototype的属性的方法:
Object.defineProperty():用于设置单个property的属性。
Object.defineProperties():用于设置多个property的属性。
获取property的属性配置:
Object.getOwnPropertyDescriptor():获取property的属性描述。
掌握了上面三个知识点,我们用Object.getOwnPropertyDescriptor()输出Object.prototype.toString的属性配置,输出如下:
Object.getOwnPropertyDescriptor(Object.prototype, "toString");
//->Object {writable: true, enumerable: false, configurable: true}
从结果中我们可以看出toString属性的属性配置writable(可写的)值为ture,所有我们可以改变toString的指向。
定义不可改变指向的属性
//将toString属性配置成不可写
Object.defineProperty(Object.prototype, "toString", {
writable:false
});
var obj = new Object();
console.log( obj.toString() );//->[object Object]
//将Object.prototype.toString指向自定义的函数
Object.prototype.toString=function(){
return "my self toString";
};
console.log( obj.toString() );//->[object Object]
从上述结果可以看出我们的执行并没有生效,第二次调用obj.toString()的结果还是[object Object]。注意:这里指的是不可改变指向,就像java中的final关键字一样是个常量,toString仍然是可以被子类覆盖,不要混淆了。