zoukankan      html  css  js  c++  java
  • 关于toString()和valueOf()以及Object.prototype.toString.call()的结合理解

    一、先说说String():

    String()是全局函数,把对象的值转换为字符串。

    语法:String(obj);

    任何值(对象)都有String()方法,执行过程是这样的:首先,如果该对象上有toString()方法,则使用该方法(无参数),其次就是没有toString方法,那就是 null 返回 "null",undefined返回"undefined";

    【个人理解:任何对象都有String()方法,因为这个全局函数;除了null和undefined,其他对象都有toString()方法】;

    二、toString()

    语法:obj.toString();

    可以将除null和undefined外所有对象转为字符串。是所有内建的 JS 对象的成员,它的操作依赖于对象的类型。

    1.将boolean类型的值转化为string类型:

    console.log(true.toString());//"true"
    console.log(false.toString());//"false"

    2.将string类型按其字面量形式输出:

    var str = "test123y";
    console.log(str.toString());//"test123y"

    3.将Object类型转化成string类型(JavaScript原生的Array类型、Date类型、RegExp类型以及Number、Boolean、String这些包装类型都是Object的子类型):

    自定义Object类型(没有重新定义toString方法):

    var obj = {name:"Tom", age:18};
    console.log(obj.toString());//"[object Object]"此时调用的是从Object继承来的原始的toString()方法

    【个人理解:既然都是object的子类型,为什么】

     接下来的三个例子都是以重写的方式实现了toString()方法:

    3.1Array类型:

    var arr = ["tom",12,"rose",18];
    console.log(arr.toString());//"tom,12,rose,18"

    3.2RegExp类型

    var patten = new RegExp("\[hbc\]at", "gi");
    console.log(patten.toString());//"/[hbc]at/gi"

    3.3Date类型

    var date = new Date(2014,02,26);//注意这种格式创建的日期,其月份是3月
    console.log(date.toString());//"Wed Mar 26 2014 00:00:00 GMT+0800"输出格式因浏览器不同而不同,此为firefox的输出格式;

    3.4Number类型也是以重写的方式实现toString()方法的,请看以下例子:

      3.4.1它可以接受一个整数参数,并将调用这个方法的数值转化成相应进制的字符串:

    var num = 16;
    console.log(num.toString(2));//10000 二进制
    console.log(num.toString(8));//20 八进制
    console.log(num.toString(16));//10 十六进制
    console.log(num.toString(5));//31 虽然没有五进制,但是这样传参是可以被toString()方法接受的

      3.4.2再看下面的代码:

    复制代码
    console.log(1.toString());//这种写法会报错语法错误,但是下面的写法都是合法的;
    console.log((1).toString());//"1"
    console.log(typeof (1).toString());//string
    console.log(1..toString());//"1"
    console.log(typeof (1).toString());//string
    console.log(1.2.toString());//"1"
    console.log(typeof (1).toString());//string
    复制代码
      这是因为javascript引擎在解释代码时对于“1.toString()”认为“.”是浮点符号,但因小数点后面的字符是非法的,所以报语法错误;而后面的“1..toString()和1.2.toStirng()”写法,javascript引擎认为第一个“.”小数点,的二个为属性访问语法,所以都能正确解释执行;对于“(1).toStirng()”的写法,用“()”排除了“.”被视为小数点的语法解释,所以这种写法能够被解释执行;
      3.4.3纯小数的小数点后面有连续6或6个以上的“0”时,小数将用e表示法进行输出;
    var num = 0.000006;//小数点后面有5个“0”
    console.log(num.toString());//"0.000006"
    var num = 0.0000006;//小数点后面有6个“0”
    console.log(num.toString());//"6e-7"

      3.4.4浮点数整数部分的位数大于21时,输出时采用e表示法;

    var num = 1234567890123456789012;
    console.log(num.toString());//"1.2345678901234568e+21"

    三、toString方法到底定义在何处?

    先看一下代码:

    复制代码
    var pro = Object.prototype;
    var pr = pro.__proto__;//ie11之前版本不支持该属性
    console.log(typeof pro);//"object"
    console.log(String(pro));//"[object Object]"
    console.log(pro.hasOwnProperty("toString"));//true
    console.log(typeof pr);//"object"
    console.log(String(pr));//"null"
    console.log(pr.hasOwnProperty("toString"));//报错
    复制代码

    由此可见,toString()定义在Object.prototype上;所以所有对象均可用toString()方法。

    【个人理解:但为什么当对象是object的时候,输出的是'[object object]',而其他类型输出的却是类似本身的值?因为其他类型的对象引用的是重写后的toString()方法】

     Object.prototype.toString() 为何能返回这样类型的字符串?
    ECMA-262:
    1
    2
    3
    4
    Object.prototype.toString( ) When the toString method is called, the following steps are taken:
    1. Get the [[Class]] property of this object.
    2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.
    3. Return Result (2)

    上面的规范定义了 Object.prototype.toString 的行为:首先,取得对象的一个内部属性[[Class]],然后依据这个属性,返回一个类似于 "[object Array]" 的字符串作为结果([[]]用来表示语言内部用到的、外部不可直接访问的属性,称为 "内部属性")。利用这个方法,再配合 call,我们可以取得任何对象的内部属性 [[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。还是先来看看在 ECMA 标准中 Array 的描述吧:

    1
    2
    new Array([ item0[, item1 [,…]]])
    The [[Class]] property of the newly constructed object is set to “Array”.

      所以 Javascript 中判断数组的函数可以这样写:

    1
    2
    3
    function isArray(a) {
      Array.isArray ? Array.isArray(a) : Object.prototype.toString.call(a) === '[object Array]';
    }

      

    四、所以,可以使用Object.prototype上的原生toString()方法判断数据类型,使用方法如下:
     Object.prototype.toString.call(value)

     4.1.判断基本类型:

    Object.prototype.toString.call(null);//”[object Null]”
    Object.prototype.toString.call(undefined);//”[object Undefined]”
    Object.prototype.toString.call(“abc”);//”[object String]”
    Object.prototype.toString.call(123);//”[object Number]”
    Object.prototype.toString.call(true);//”[object Boolean]”

    4.2.判断原生引用类型:

    4.2.1函数类型

    Function fn(){console.log(“test”);}
    Object.prototype.toString.call(fn);//”[object Function]”

    4.2.2日期类型

    var date = new Date();
    Object.prototype.toString.call(date);//”[object Date]”

    4.2.3数组类型

    var arr = [1,2,3];
    Object.prototype.toString.call(arr);//”[object Array]”

    4.2.4正则表达式

    var reg = /[hbc]at/gi;
    Object.prototype.toString.call(arr);//”[object Array]”

    4.2.5自定义类型

    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    var person = new Person("Rose", 18);
    Object.prototype.toString.call(arr); //”[object Object]”

    很明显这种方法不能准确判断person是Person类的实例,而只能用instanceof 操作符来进行判断,如下所示:

    console.log(person instanceof Person);//输出结果为true

    4.3判断原生JSON对象:

    var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);
    console.log(isNativeJSON);//输出结果为”[object JSON]”说明JSON是原生的,否则不是;

    注意:Object.prototype.toString()本身是允许被修改的,而我们目前所讨论的关于Object.prototype.toString()这个方法的应用都是假设toString()方法未被修改为前提的。

    五、valueOf()和toString()

    参考文章1:Javascript中valueOf与toString区别浅析

    参开文章2:JavaScript的toString()和valueOf()区别到底是什么

    参开文章3:valueOf()函数详解

  • 相关阅读:
    1082 射击比赛 (20 分)
    1091 N-自守数 (15 分)
    1064 朋友数 (20 分)
    1031 查验身份证 (15 分)
    1028 人口普查 (20 分)
    1059 C语言竞赛 (20 分)
    1083 是否存在相等的差 (20 分)
    1077 互评成绩计算 (20 分)
    792. 高精度减法
    791. 高精度加法
  • 原文地址:https://www.cnblogs.com/bydzhangxiaowei/p/8524536.html
Copyright © 2011-2022 走看看