类型转换之引用类型转换

js中的任何类型在做隐式转换时只存在两种:值类型转值类型,引用类型转换值类型。下面针对引用类型转换为值类型。

当一个引用类型转换为值类型的时候首先会调用valueOf方法,如果此时已经转换为值类型则结束,否则继续调用toString()方法进行转换。下面看例子

 

(function(){
  _toString=Boolean.prototype.toString;
  _valueOf=Boolean.prototype.valueOf;
  Boolean.prototype.valueOf=function(){
    alert('do valueOf');
    return {};
  };
  Boolean.prototype.toString=function(){
    alert('do toString');
    return _toString.call(this);
  }
}());
var obj=new Boolean(true);
var v=false;
alert(obj+v);//truefalse

在上面的例子中,我们通过改写Boolean中的valueOf方法来使其返回一个引用类型对象,这样就迫使其必须再调用一次toString以使其返回值类型,默认的Boolean对象调用一次valueOf就已经转换为值类型(返回true而不是'true',这样参与最后的运算时输出1),所以根本不会再调用toString;最后返回'true'字符串,当’true'+false时false转换为'false'字符串

因此我们发现依次输出

do valueOf

do toString

truefalse

接下来我们再次场次修改Boolean的valueOf使其不返回对象,而是字符串'helllow javascript'

 

Boolean.prototype.valueOf=function(){
    alert('do valueOf');
    return {};
  };

 

,这样意味着执行valueOf后已经返回了值类型,就不需要再次调用toString方法了,因此结果输出

do Valueof

hellow javascript

不过这样还不满足,因为我们只是一味的改 valueOf,我们尝试改下toString试试,我们让其也返回一个对象,那一味着经过toString后还是没有转换为值类型

那已经违背了我们最终必须转换为值类型的定理,因此这样的改动会报错

  Boolean.prototype.toString=function(){
    alert('do toString');
    return {};
  }

 最后执行比较的时候提示”无法将obj转换为原始类型“

讲到这里最后再来一个例子

 

var arr = [];
alert(arr == false);//true

 上面为什么为true,我们来分析下

 1、发现arr为引用类型的对象,因此调用内部的valueOf,返回还是引用类型本身。

2、根据上面valueOf返回的不是值类型,因此再次执行toString,我们知道数组执行toString会展开其内部元素,然后拼接为字符串,

因此空元素的arr.toString()后返回 空的字符串''。

3、最后我们知道空的字符串会转换为false,因此arr==false会输出true了。

空说理论无凭,我们还是以实际代码来验证

(function(){
   _valueOf = Array.prototype.valueOf;
   _toString = Array.prototype.toString;
   Array.prototype.valueOf= function(){
     alert('do valueOf');
     var arrValueOf = _valueOf.call(this);//执行默认的valueOf
     alert(typeof arrValueOf);//输出object
     return arrValueOf;//记得返回该值不至于改变默认的结果,否则相当于重写valueOf后使返回了undefined吗,这样就是告诉引擎已经是值类型了,就不会再调用toString,你可以试试

   };
   Array.prototype.toString = function(){
     alert('do toString');
     var arrToString = _toString.call(this);//执行默认的toString;
     alert(arrToString);//输出空字符串'';
     return arrToString;//记得返回该值不至于改变默认的结果,否则相当于重写toString后使返回了undefined;

   }
}());
var arr = [];
alert(arr == false);//true

 一个很有趣的问题?

![]//false这里的类型转换没有调用到valueOf等
[] == ![]//true

 

 

 

posted @ 2012-03-22 09:38  自由小菜园  阅读(579)  评论(0编辑  收藏  举报