zoukankan      html  css  js  c++  java
  • 类型转换之引用类型转换

    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

  • 相关阅读:
    js实现对身份证校验
    zip解压缩
    zip压缩
    文件内容编解码
    文件的操作
    Mysql账号管理
    深度优先算法DFS
    Java常见知识问答
    Hibernate的单向OneToMany、单向ManyToOne
    Angularjs在线编辑器
  • 原文地址:https://www.cnblogs.com/fuyun2000/p/2411062.html
Copyright © 2011-2022 走看看