• js数据类型自动转化规律


    1. 原始数据遇运算符

    1. +运算符

    1) 如果算子两侧都是字符串,返回拼接结果;

    2) 如果算子两侧不全是字符串,则根据实际情况:

    • 如果需要字符串,就调用String();
    true + "1"; // "true1"
    • 如果需要数字转为数字,就调用Number();
    true + 1; //2
    • 如果都可以,优先转为数字。
    true + true; //2

    2. -*/减法、乘法、除法运算符

    所有的算子全部转为数字,使用Number()/+。

    '4' - '5'; // -1
    4-'5'; //-1
    true - false; // 1
    '4'/'5'; 0.8

    3.非相等比较运算符

    >,>=,<,<=

    1)如果算子两侧都是字符串,按照Unicode码点依次比较大小

    2)如果算子两侧不全是字符串,转为数字进行比较(Number()/+)。

    true < '8'; // true
    '7' < 8; // true

    4.相等比较运算符(==)

    1) 如果是不同原始类型的值,将字符串和布尔值都转为数字(Number()或者+)。

    true == '1'; //true 
    'true' == true; // false Number('true')->NaN
    // NaN用于任何运算符返回值都是false

    2)如果其中一方是对象,先将其转为原始类型的值

        如果两侧都是对象,则永远不相等。

    3) null == undefined

    4)null和undefined都不等于其他值

    null == 0; //false
    undefined == 0; //false

    4) NaN 和任何值都不相等

    5.严格相等运算符(===)

    1)如果类型不相同,直接返回false

    2)如果类型相等,值也相同,直接返回true

    2. 对象遇到运算符

    1.+运算符

    最终结果是对象需要转化成原始数据。

    1)对象首先调用valueOf()方法,如果不自定义,一般都返回自身;

    2)再调用toString()方法,返回对应的字符串。

    但是,Date对象不同,是先调用toString(), 后调用valueOf()

    var arr = [5];
    arr + 1;//  "51"
    var obj = {
        toString() { return "hello"},
        valueOf() {return 1}
    };
    obj + "2"; // "12"  不管另一个算子是什么类型,都是先调用valueOf()
    var date = new Date();
    date.toString = function(){return "hello"};
    date.valueOf = function(){return 1};
    date + 1; // "hello1" 不管另一个算子什么类型,都是先调用toString()

    2. -*/减法、乘法、除法运算符

    和直接调用Number()一样; 

    Date对象和其他对象一样,遵循Number()函数的调用规则;

    var obj = {
        valueOf(){return "8"},
        toString() {return "9"}
    }
    obj - 8; // 0
    var date = new Date();
    date.valueOf = function(){return "8"};
    date.toString = function(){return "9"};
    date - 8; // 0

    3.非相等比较运算符

    规则和+运算符(Number()工具函数)一致。 

    1)先调用valueOf()方法,如果返回值不是原始值,再调用toString()方法

    2)调用toString()后还不是原始值,返回NaN

    Date对象和其他对象一样,遵循上面的规则!

    var obj = {
        valueOf(){return "8"},
        toString() {return "9"}
    }
    obj > 8; // false
    var date = new Date();
    date.valueOf = function(){return "8"};
    date.toString = function(){return "9"};
    date > 8; // false

    4. 相等运算符(==)

    如果运算符两侧都是对象,除非地址相同,否则返回都是false;

    如果比较符一侧是原始类型的值:

    1)先调用valueOf(),如果返回不是原始类型的值,再调用toString();

    2) 如果toString()的值返回的还不是原始类型,返回NaN

    Date类型相反,先调用toString();

    var obj = {
        valueOf(){return "8"},
        toString() {return "9"}
    }
    obj == 8; // true
    var date = new Date();
    date.valueOf = function(){return "8"};
    date.toString = function(){return "9"};
    date ==  8; // false

    应用:

    若使得下面条件成立,a应该使什么值?

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <script type="noscript">
        a什么情况下,使得下面的条件成立
        if(a == 1 && a ==2 && a ==3) {
          console.log(1);
        }
      </script>
      <script>
        //有两类解决方案:1)数据拦截 2)类型转换 
        /**
         * 1)数据拦截
         * a本身可以看作window,使用Object.defineProperty
         */
        var i = 1;
        Object.defineProperty(window, 'a', {
          get() {
            return i++;
          }
        })
        /**
         * 2)类型转换
         *   >  使用==时,如果是对象,会先转成原始类型的值
         *      先调用valueOf(),如果是原始类型的值返回;
         *      否则再调用toString()
         */
        // 1)重写valueOf方法
        var a = {
          index: 1,
          valueOf() {
            return this.index++;
          }
        }
        // 2)重写toString方法
        var a = {
          index: 1,
          toString() {
            return this.index++;
          }
        }
        /* 
         * >  使用==时,如果是对象,会先转成原始类型的值
         *    对象转原型类型本质上是调用的[Symbol.toPrimitive]方法
         *    该方法被调用时,会传入一个参数,表示其转为的预期类型
         *    default/number/string中的一个
        */
        var a = {
          index: 1,
          [Symbol.toPrimitive](hint) {
            // 预期是number/string都可以
            if(hint === 'default') {
              return this.index++;
            }
          }
        }
    
    
        // 运行
        if(a == 1 && a ==2 && a ==3) {
          console.log(1);
        }
      </script>
    </body>
    </html>
    View Code

    5. 严格相等运算符(===)

    如果比较符两侧都是对象,除非地址相同,否则都是false;

    var obj1 = {};
    var obj2 = obj1;
    obj1 === obj2;  // true
    var obj3 = {};
    obj1 === obj3; //false

    如果比较符一侧是原始值,直接返回false

    3. String()工具函数遇对象

    转化规律:

    1)先调用toString(),如果返回原始类型的值,对这个值使用String()方法,结束;如果是对象,继续执行;

    2)调用原对象的valueOf()方法,如果返回的是原始类型的值,对这个值使用String()方法,结束;

    3)如果上面的步骤执行完成后还是不是原始值,报错!

    var obj = {
        valueOf(){ return 5; },    
        toString() { return 'hello'; }
    };
    String(obj); // "hello"
    // 当执行完都不返回原始值时
    var obj = {
      valueOf: function () { return {};},
      toString: function () { return {};}
    };
    String(obj); //Uncaught SyntaxError: Invalid or unexpected token

    4. Number()工具函数遇对象

    转化规律:

    1)先调用valueOf()方法,如果返回原始值,对这个值使用Number()函数,结束;否则继续

    2)调用原对象toString()方法,如果返回原始值,对这个值使用Number()函数,结束;

    3)如果都不是原始值,报错

    var obj = {
        valueOf(){ return 5; },    
        toString() { return 'hello'; }
    };
    Number(obj); // 5
    // 当执行完都不返回原始值时
    var obj = {
      valueOf: function () { return {};},
      toString: function () { return {};}
    };
    Number(obj); //Uncaught SyntaxError: Invalid or unexpected token

     5. 当遇到函数时

    当遇到函数调用,就会自动调用函数的toString()方法;

    所以执行a();会打印两次2

    function a() {
        var obj = function(){
    
        }; 
        obj.valueOf= function(){console.log(1); },    
        obj.toString = function() {console.log(2);} 
        return obj; // 2
    }; 
    a(); // 2  
  • 相关阅读:
    自动发送邮件功能
    工作中常用的Android系统ADB命令收集
    商城系统必须知道的【订单、优惠金额、退货、实际营收】解释
    商城系统项目必须知道的专业数据指标
    接口加密思路
    Selenium使用Chrome模拟手机浏览器方法解析
    PHP上传图片基本代码示例
    iframe子页面获取父页面的点击事件
    javascript实现网页倒计时效果
    Crontab常用命令总结
  • 原文地址:https://www.cnblogs.com/lyraLee/p/11627350.html
Copyright © 2020-2023  润新知