美文网首页
隐式转换的规则

隐式转换的规则

作者: imakan | 来源:发表于2019-08-02 00:18 被阅读0次

    问题:隐式转换的规则是什么

    说起JS的隐式转换规则,我们可以说下JS的基础数据类型

    JS的七中类型

    我们所熟知的JS,可以在大体上可以分为2中类型:原始类型,复杂类型(对象类型)

    原始类型

    JS再继续细分的话,原始类型包含:stringnumberbooleannullundefinedsymbol

    对象类型

    JS的对象类型包含:object

    三种隐式转换类型

    JS中一个难点就是隐式转换,因为JS在一些操作符下其类型会做一些变化,所以JS灵活,同时也会造成一些错误,并且难以理解

    这其中涉及隐式转换最多的两个运算符 + ==

    +运算符即可数字相加,也可以字符串相加,所以比较麻烦,== 不同于 ===,也存在隐式转换, */-这些操作符都是针对number类型的,故转换的结果只能是转换成number

    隐式转换中主要是三种转换方式:

    • 将值转换为原始值。toPrimitive(input,type?);
    • 将值转换为数字。toNumber()
    • 将值转换为字符串。toString()

    通过toPrimitive()将值转换为原始值

    ToPrimitive(input,PreferredType?)
    

    input是要转换的值,Preferred是可选参数,可以是Number或者String类型。他只是一个转换标志。转换后的结果并不一定是这个参数所代表的类型,但是转换结果一定是个原始值或者是错误

    ToPrimitive(input,number)

    • 如果输入的已经是一个原始值,则直接返回它,
    • 否则,如果输入的是一个对象,则使用这个对象上面的valueOf()方法。如果valueOf()返回的是一个原始值,则返回这个原始值
    • 否则,调用这个对象上面的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。
    • 否则,抛出一个typeError异常

    ToPrimitive(input,string)

    • 如果输入的已经是一个原始值,则直接返回它。
    • 否则,如果输入的是一个对象,则使用这个对象上面的toString()方法。如果toString()返回的是一个原始值。则返回这个原始值
    • 否则,调用这个对象上面的vaueOf()方法,如果valueOf方法返回一个原始值,则直接返回
    • 否则,抛出typeError异常

    既然第二个参数是可选的,那么如果我们不填写这个参数的话,怎么转换呢?

    规则如下:
    1、如果对象是Date,则第二个参数是string
    2、否则是number

    valueOf方法和toString方法解析

    JS常见内置对象:DateArrayMathNumberBooleanStringRegExpFunction

    1、NumberBooleanString 这三种构造函数生成的基础值的对象形式,通过valueOf转换后会变成相应的原始值。

    比如:

    var num = new Number('123')
    num.valueOf(); // 123
    
    var str = new String('12df');
    str.valueOf(); // '12df'
    
    var bool = new Boolean('fd');
    bool.valueOf(); // true
    
    

    2、Date这种特殊的对象,其原型Date.prototype上内置的valueOf函数是将日期转换为毫秒数的形式的值

    var a = new Date();
    a.valueOf(); // 1515143895500
    

    3、除此之外返回的都是他们自己本身

    var a = new Array();
    a.valueOf() === a; // true
    
    var b = new Object({});
    b.valueOf() === b; // true
    
    

    上面说了valueOf函数,下面说说toString函数

    1、NumberBooleanStringArrayDateRegExpFunction这几种构造函数生成的对象,通过toString转换后会变成相应的字符串的形式,因为这些构造函数上封装了自己的toString方法

    Number.prototype.hasOwnProperty('toString'); // true
    Boolean.prototype.hasOwnProperty('toString'); // true
    String.prototype.hasOwnProperty('toString'); // true
    Array.prototype.hasOwnProperty('toString'); // true
    Date.prototype.hasOwnProperty('toString'); // true
    RegExp.prototype.hasOwnProperty('toString'); // true
    Function.prototype.hasOwnProperty('toString'); // true
    
    var num = new Number('123sd');
    num.toString(); // 'NaN'
    
    var str = new String('12df');
    str.toString(); // '12df'
    
    var bool = new Boolean('fd');
    bool.toString(); // 'true'
    
    var arr = new Array(1,2);
    arr.toString(); // '1,2'
    
    var d = new Date();
    d.toString(); // "Wed Oct 11 2017 08:00:00 GMT+0800 (中国标准时间)"
    
    var func = function () {}
    func.toString(); // "function () {}"
    
    

    除了这些对象及其实例化对象之外,其他的对象返回的都是该对象的类型。都是继承的Object.prototype.toString

    var obj = new Object({})
    obj.toString() // '[object object]'
    
    Math.toString(); // "[object Math]"
    
    

    从上面valueOftoString两个函数对对象的转换可以看出为什么对于ToPrimitive(input, PreferredType?)PreferredType没有设定的时候,除了Date类型,PreferredType被设置为String,其它的会设置成Number
    因为valueOf函数会将NumberStringBoolean基础类型的对象类型值转换成 基础类型,Date类型转换为毫秒数,其它的返回对象本身,而toString方法会将所有对象转换为字符串。显然对于大部分对象转换,valueOf转换更合理些,因为并没有规定转换类型,应该尽可能保持原有值,而不应该想toString方法一样,一股脑将其转换为字符串。
    所以对于没有指定PreferredType类型时,先进行valueOf方法转换更好,故将PreferredType设置为Number类型。
    而对于Date类型,其进行valueOf转换为毫秒数的number类型。在进行隐式转换时,没有指定将其转换为number类型时,将其转换为那么大的number类型的值显然没有多大意义。(不管是在+运算符还是==运算符)还不如转换为字符串格式的日期,所以默认Date类型会优先进行toString转换。故有以上的规则:

    总结

    PreferredType没有设置时,Date类型的对象,PreferredType默认设置为String,其他类型对象PreferredType默认设置为Number

    相关文章

      网友评论

          本文标题:隐式转换的规则

          本文链接:https://www.haomeiwen.com/subject/ubohdctx.html