zoukankan      html  css  js  c++  java
  • 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([] + []) // 空字符串
  • 相关阅读:
    为图片指定区域添加链接
    数值取值范围问题
    【leetcode】柱状图中最大的矩形(第二遍)
    【leetcode 33】搜索旋转排序数组(第二遍)
    【Educational Codeforces Round 81 (Rated for Div. 2) C】Obtain The String
    【Educational Codeforces Round 81 (Rated for Div. 2) B】Infinite Prefixes
    【Educational Codeforces Round 81 (Rated for Div. 2) A】Display The Number
    【Codeforces 716B】Complete the Word
    一个简陋的留言板
    HTML,CSS,JavaScript,AJAX,JSP,Servlet,JDBC,Structs,Spring,Hibernate,Xml等概念
  • 原文地址:https://www.cnblogs.com/houfee/p/10393843.html
Copyright © 2011-2022 走看看