• JS高级学习笔记(1)-数据类型及转换规则


    必读:

    深入理解Javascript中的valueOf与toString

    JavaScript类型系统之基本数据类型与包装类型

    toString()

    toString() 作用是返回 object 的字符串表示,JavaScript中object默认的toString()方法返回字符串”[object Object]“。

    注意,基本数据类的 toString() 方法,是由基本包装类型提供。
    对象toString返回值
    Array 以逗号分割的字符串,如[1,2]的toString返回值为"1,2",跳过null,undefined
    Boolean "True"
    Date 可读的时间字符串,如"Tue Oct 15 2019 12:20:56 GMT+0800 (中国标准时间)"
    Function 声明函数的JS源代码字符串
    Number "数字值"
    Object "[object Object]"
    String "字符串"

    valueOf()

    valueOf()函数的作用是返回该object自身。与toString()一样,定义类时可以实现新的valueOf()方法,覆盖原生的 valueOf() 方法。

    MDN对valueOf()的描述:

    JavaScript调用valueOf方法将对象转换为原始值。你很少需要自己调用valueOf方法;当遇到要预期的原始值的对象时,JavaScript会自动调用它。

    默认情况下,valueOf方法由 Object 后面的每个对象继承。 每个内置的核心对象都会覆盖此方法以返回适当的值。如果对象没有原始值,则valueOf将返回对象本身。

    JavaScript的许多内置对象都重写了该函数,以实现更适合自身的功能需要。因此,不同类型对象的valueOf()方法的返回值和返回值类型均可能不同。
    对象valueOf返回值
    Array 数组本身
    Boolean 布尔值
    Date 返回毫秒形式的时间戳
    Function 函数本身
    Number 数字值
    Object 对象本身
    String 字符串值
    // Array:返回数组对象本身
    var array = ["ABC", true, 12, -5];
    console.log(array.valueOf() === array);   // true
    
    // Date:当前时间距1970年1月1日午夜的毫秒数
    var date = new Date(2013, 7, 18, 23, 11, 59, 230);
    console.log(date.valueOf());   // 1376838719230
    
    // Number:返回数字值
    var num =  15.26540;
    console.log(num.valueOf());   // 15.2654
    
    // 布尔:返回布尔值true或false
    var bool = true;
    console.log(bool.valueOf() === bool);   // true
    
    // new一个Boolean对象
    var newBool = new Boolean(true);
    // valueOf()返回的是true,两者的值相等
    console.log(newBool.valueOf() == newBool);   // true
    // 但是不全等,两者类型不相等,前者是boolean类型,后者是object类型
    console.log(newBool.valueOf() === newBool);   // false
    
    // Function:返回函数本身
    function foo(){}
    console.log( foo.valueOf() === foo );   // true
    var foo2 =  new Function("x", "y", "return x + y;");
    console.log( foo2.valueOf() );
    /*
    ƒ anonymous(x,y) {return x + y;}
    */
    
    // Object:返回对象本身
    var obj = {name: "张三", age: 18};
    console.log( obj.valueOf() === obj );   // true
    
    // String:返回字符串值
    var str = "http://www.xyz.com";
    console.log( str.valueOf() === str );   // true
    
    // new一个字符串对象
    var str2 = new String("http://www.xyz.com");
    // 两者的值相等,但不全等,因为类型不同,前者为string类型,后者为object类型
    console.log( str2.valueOf() === str2 );   // false

    对象转换为布尔值

    直接转换为true(包装类型也一样),不调用valueOf和toString

    对象转换为数字

    对象转换为数字会依次调用valueOf和toString方法,具体规则如下:

    1. 如果对象具有valueOf方法且返回原始值(string、number、boolean、undefined、null),则将该原始值转换为数字(转换失败会返回NaN),并返回这个数字

    2. 如果对象具有toString方法且返回原始值(string、number、boolean、undefined、null),则将该原始值转换为数字(转换失败会返回NaN),并返回这个数字

    3. 转换失败,抛出TypeError

    // 保存原始的valueOf
    var valueOf = Object.prototype.valueOf;
    var toString = Object.prototype.toString;
    
    // 添加valueOf日志
    Object.prototype.valueOf = function () {
      console.log('valueOf');
      return valueOf.call(this);
    };
    // 添加toString日志
    Object.prototype.toString = function () {
      console.log('toString');
      return toString.call(this);
    };
    var a = {};
    console.log(++a); // valueOf toString NaN
    1. valueOf方法返回的是对象本身,不是原始值,继续执行

    2. toString方法返回的是"[object Object]",是原始值(字符串),将字符串转换为数字NaN

    // 保存原始的valueOf
    var valueOf = Object.prototype.valueOf;
    var toString = Object.prototype.toString;
    
    // 添加valueOf日志
    Object.prototype.valueOf = function () {
      console.log('valueOf');
      return "1"; // 强制返回原始值
    };
    // 添加toString日志
    Object.prototype.toString = function () {
      console.log('toString');
      return toString.call(this);
    };
    var a = {};
    console.log(++a); // valueOf 2

    分析:valueOf返回原始值(字符串),直接将该字符串转换为数字,得到1

    对象转换为字符串

    对象转换为数字会依次调用toStringvalueOf方法,具体规则如下:

    1. 如果对象具有toString方法且返回原始值(string、number、boolean、undefined、null),则将该原始值转换为字符串,并返回该字符串

    2. 如果对象具有valueOf方法且返回原始值(string、number、boolean、undefined、null),则将该原始值转换为字符串,并返回该字符串

    3. 转换失败,抛出TypeError

    // 保存原始的valueOf
    var valueOf = Object.prototype.valueOf;
    var toString = Object.prototype.toString;
    
    // 添加valueOf日志
    Object.prototype.valueOf = function () {
      console.log('valueOf');
      return valueOf.call(this);
    };
    // 添加toString日志
    Object.prototype.toString = function () {
      console.log('toString');
      return toString.call(this); // '[object Object]'  toString方法先调用 ,如果返回结果是字符串,则停止调用 valueOf,不是字符串,那么就调用 valueOf
    };
    var a = {};
    console.log(a.toString()); // valueOf toString [object Object]str
    // alert(a) // alert主动调用toString方法,返回了字符串"[object Object]",对象最终转换为该字符串

      

    加强记忆

    demo1:

    var colors = ["red", "blue", "green"]; // 创建一个包含3 个字符串的数组 
    console.log('原数组:', colors); // ["red", "blue", "green"]
    // valueOf 返回本身
    console.log(colors.valueOf()); // ["red", "blue", "green"]
    // toString 返回字符串
    console.log(colors.toString()); // red,blue,green 
    
    colors.valueOf = function () {
        return '改写了Array的valueOf'
    }
    colors.toString = function () {
      return '改写了Array的toString'
    }
    console.log(colors.valueOf()); // 改写了Array的valueOf
    console.log(colors.toString()); // 改写了Array的toString

    demo2:

    var colors = {
      name: 'red'
    };
    colors.valueOf = function () {
      console.log('改写了colors的valueOf')
      return []
    }
    colors.toString = function () {
      console.log('改写了colors的toString')
      return 2
    }
    console.log(Number(colors));
    /*
    改写了colors的valueOf
    改写了colors的toString
    2
    */
     
    1. valueOf 方法返回的是 简单数据类型,那么就用返回的 简单数据类型 调用Number() 方法
    2. valueOf 方法返回的是 复杂数据类型,那么就去调用 toString 的方法,然后判断 toString 方法的返回值,再根据这个返回值调用Number() 方法

    number相关

    将非number类型的值转换为number类型

    • 一种是隐式转换,如进行(*、/)操作时,会自动其余类型的值转为number类型

    • 一种是显示转换-调用Number()、parseInt()、parseFloat()方法转换 

    Number():

    • 如果是boolean值,true和false将分别被替换为1和0

    • 如果是数字值,只是简单的传入和返回

    • 如果是null值,返回0

    • 如果是undefined,返回NaN

    • 如果是字符串,遵循下列规则:

      • 如果字符串中只包含数字,则将其转换为十进制数值,即”1“会变成1,”123“会变成123,而”011“会变成11(前导的0被忽略)

      • 如果字符串中包含有效的浮点格式,如”1.1“,则将其转换为对应的浮点数(同样,也会忽略前导0)

      • 如果字符串中包含有效的十六进制格式,例如”0xf“,则将其转换为相同大小的十进制整数值

      • 如果字符串是空的,则将其转换为0

      • 如果字符串中包含除了上述格式之外的字符,则将其转换为NaN

    • 如果是对象,则调用对象的valueOf()方法,再调用对象的toString()方法,然后再依次按照前面的规则转换返回的字符串值。

    parseInt():

    常常用于将其它类型值转化为整形。parseInt转换与Number()有区别,具体规则如下:

    • parseInt(value,radius)有两个参数,第一个参数是需要转换的值,第二个参数是转换进制(该值介于 2 ~ 36 之间。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。),如果不传(或值为0),默认以10为基数(如果value以 “0x” 或 “0X” 开头,将以 16 为基数)

    • 注意在第二个参数默认的情况下,如果需要转换的string值以0开头,如'070',有一些环境中,会自动转化为8进制56,有一些环境中会自动转化为10进制70。所以为了统一效果,我们在转换为10进制时,会将第二个参数传10

    console.log(parseInt('')) //NaN
    console.log(parseInt('a')) //NaN
    console.log(parseInt('1234blue')) //1234
    console.log(parseInt(true)) //NaN
    console.log(parseInt('070')) //70,但是有一些环境中会自动转换为8进制56
    console.log(parseInt('070', 8)) //56
    console.log(parseInt('001.1')) //1
    console.log(parseInt('0xf')) //15,16进制
    console.log(parseInt('AF', 16)) //175,16进制
    console.log(parseInt('AF')) //NaN
    console.log(parseInt('000xf')) //0
    
    var a = {}
    console.log(parseInt(a)) //NaN
    a.toString = function () {
      return 2
    } // 重写valueOf()方法
    console.log(parseInt(a)) //2
    a.valueOf = function () {
      return 1
    } // 重写valueOf()方法
    console.log(parseInt(a)) //2

    parseFloat():

    parseFloat()转换规则基本与parseInt()一致,只有如下不同点

    • parseFloat()遇到浮动数据时,浮点有效(但是只有第一个.有效),如"10.1"会被转为10.1;'10.1.1'会被转为10.1

    • parseFloat()只会默认处理为10进制,而且会忽略字符串前面的0,所以不会有在默认情况下转为8进制的情

    console.log(parseFloat('1234blue')) //1234
    console.log(parseFloat('1234blue', 2)) //1234
    console.log(parseFloat('0xA')) //0
    console.log(parseFloat('10.1')) //10.1
    console.log(parseFloat('10.1.1')) //10.1
    console.log(parseFloat('010')) //10

    由于Number()函数在转换字符串时比较复杂而且不够合理,因此在处理整数的时候更常用的是parseInt()函数-需注意最好第二个参数传10,处理浮点数时更常用parseFloat()

    另外注意,浮点数直接的计算存在误差,所以两个浮点数无法用"="进行判断

    var a = 10.2
    var b = 10.1
    console.log(a - b === 0.1) //false
    console.log(a - 10.1 === 0.1) //false,实际是0.09999999999999964
    console.log(a - 0.1 === 10.1) //true

     

    字符串

    要把一个值转换为一个字符串有三种方式。

    • 第一种是使用几乎每个值都有的toString(基数)方法(除去null和undefined没有)——当需要toString的值为number时,参数可以生效。

    • 第二种是隐式转换,+ 号:要转换的值为对象时,回调用对象的valueOf属性。

    • 第三种是通过转换函数String(),转换规则如下

      • 如果值有toString()方法,则调用该方法(没有参数)并返回相应的结果,(注意不会调用valueOf()方法)

      • 如果值是null,则返回null,如果值是undefined,则返回undefined

    var c = {};
    console.log(c);//[object Object]
    console.log(c + '1');//[object Object]1
    console.log(String(c));//[object Object]
    
    c.valueOf = function () { return '重写c的valueOf方法' };
    console.log(c);// {valueOf: ƒ}   valueOf重写
    console.log(c + '1');// 重写c的valueOf方法1    隐式转换时,valueOf起作用了
    
    console.log(String(c));// [object Object]
    c.toString = function () { return '重写c的toString方法' };
    console.log(c);// {valueOf: ƒ, toString: ƒ}  toString起作用了
    console.log(String(c)); // 重写c的toString方法
    
    console.log(String(null));// null,null和undefined可以String()输出
    console.log(String(undefined));// undefined ,null和undefined可以String()输出
    // console.log(null.toString());//报错,null和undefined不能toString
    
    let d = {}
    d.valueOf = function () {
      console.log('valueOf 执行了')
      return 'valueOf'
    };
    d.toString = function () {
      console.log('toString 执行了')
      return 'toString'
    };
    console.log(d + '1') // 隐式转换 valueOf(转换为原始值) 执行了
    console.log(String(d)) // String toString(获得该值的字符串表示法) 执行了

    对象String()转换字符串

    /* 1.先调用对象的toString方法
    2.判断该方法的返回值是否为基础数据类型(Number,String,Boolean,Undefined,ull)
    3.若返回值为基础数据类型,则转换规则按照相应数据类型的转换规则对其进行转换
    4.若返回值不为基础数据类型,则在该返回值的基础上继续调用valueOf方法
    5.判断valueOf的返回值是否为基础数据类型
    6.判断是否为基础数据类型,若是基础数据类型则进行操作3
    7.若仍旧不为基础数据类型则报错 */
    
    let b = {name: 'houfee'}
    console.log(String(b)); // [object Object]
    let c = []
    console.log(String(c)); // 空字符串
    let d = {}
    console.log(String(d)); // [object Object]

    String与Number的区别则在于

    • Number是先调用valueOf()再调用toString ()

    • 而String是先调用toString()再调用valueOf()

    Number()先转换为原始类型,再转化为字符串形式

    String()先转换为字符串形式,再转化为原始类型

     

    判断数据类型

    function isArray(value) {
      return Object.prototype.toString.call(value) == "[object Array]"
    }
    function isFunction(value) {
      return Object.prototype.toString.call(value) == "[object Function]"
    }
    function isRegExp(value) {
      return Object.prototype.toString.call(value) == "[object RegExp]"
    }

    面试题

    console.log(Number({})); // NaN、
    console.log(String({})); // [object Object]
    console.log(Boolean({})); // true
    
    console.log(Number([])); // 0
    console.log(String([])); // 空字符串
    console.log(Boolean([])); // true
    
    console.log({} + {}) // [object Object][object Object]
    console.log({} + []) // [object Object]
    console.log([] + {}) // [object Object]
    console.log([] + []) // 空字符串
  • 相关阅读:
    Pills
    项链
    IIS7.5 关于ASP连接ACCESS数据库超时问题
    清明
    The New Beginning
    新的开始
    Mysql中文乱码以及导出为sql语句和Excel问题解决
    Spring学习笔记01. 入门知识,IoC/DI
    selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PAT
    Django框架 python3.7+django2.2 报错:AttributeError: ‘str’ object has no attribute ‘decode’解决办法
  • 原文地址:https://www.cnblogs.com/houfee/p/10393843.html
Copyright © 2020-2023  润新知