最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 转换类型的那些事儿

    正文概述 掘金(颜酱)   2021-06-02   463

    最近一直在看《你不知道的 JS》,轻总结下,转换类型。

    强制转换分为隐式和显式转化,虽然名声不好,但还是有必要知道转换的规则是啥。

    显式的强制转换,通过减少困惑,增强了代码的可读性和可维护性。

    隐式的强制转换,有其的“隐藏的”副作用,但有些也是为了增强代码的可读性。

    TL;DR

    • ToString:基本类型和函数就是原地加上引号。但对象、数组转化就麻烦点。
    • JSON.stringify:不识别undefined和函数,对于对象可以跳过部分值。可以有第二个和第三个参数。
    • ToNumber:一句话难概括。。。
    • ToBoolean:只有特定的值是可以转化为false,其他都是true
    • parseInt:是从字符串里解析数字,遇到非数字就停止。要始终传字符串类型,且加上进制参数
    • 隐式转化:各种条件表达式、加减乘除、><、==。><尽量转化为数字之后在使用。尽量用===替换==

    ToString()

    一般用xx.toString(xx)或者String(xx)显示转化。

    基本类型有自然的字符串化形式

    String(null); // 'null'
    String(undefined); // 'undefined'
    String(true); // 'true'
    String(1); // '1'
    String(1000000000000000000000.1); // "1e+21", 稍微注意的是,如果数很大或者很小,会变成指数的
    
    • 普通对象,会调用默认的toString(),会返回内部的[[ Class ]]
    • 函数,会返回函数的字符串形式
    • 数组,会将数组每个都字符串化,然后用 **","**拼接每个字符串
    String({}); // "[object Object]"(
    String(function () {}); // "function(){}"
    String([1, 2, {}]); // "1,2,[object Object]"
    

    JSON.stringify(xx)

    stringnumberboolean、和 null 值在 JSON 字符串化时,和xx.toString()的值基本是相同的。

    JSON.stringify(null); // 'null'
    JSON.stringify(true); // 'true'
    JSON.stringify(1); // '1',
    JSON.stringify(1000000000000000000000.1); // "1e+21",稍微注意的是,如果数很大或者很小,会变成指数的
    

    但是,其他类型的都不一样了!!!

    • 遇到 undefinedfunction、和 symbol 时将会自动地忽略它们,返回undefined
    • 遇到array的时候,如果某项是上面的值,会替换成null
    • 遇到对象的时候,如果对象有**toJSON**的方法,会将其返回值字符串化。没有的话,直接转化,会跳过值是undefinedfunction、和 symbol
    JSON.stringify(undefined); // undefined
    JSON.stringify(function () {}); // undefined
    JSON.stringify([1, 2, undefined, function () {}]); // "[1,2,null,null]"
    JSON.stringify({ a: 1, b: 2, c: undefined, hello() {} }); // "{\"a\":1,\"b\":2}"
    JSON.stringify({
      a: 1,
      b: 2,
      toJSON() {
        return { a: this.a };
      },
    }); // "{\"a\":1}"
    

    JSON.stringify 可以不止一个参数

    第二个参数和第三个参数都是可选的。

    第二个参数的作用类似toJSON,可以指定特定的key字符串化,可以是数组,也可以是函数。 第三个参数的作用,就是每级缩进,个人觉得这个,作用不大,知道就行。

    var a = { b: 1, c: 2 };
    JSON.stringify(a, ['b']); // "{\"b\":1}"
    JSON.stringify(a, function (k, v) {
      if (k === 'b') return v;
    }); // "{\"b\":1}"
    JSON.stringify(a, ['c'], '--'); // "{\n--\"c\": 2\n}"
    

    转换类型的那些事儿

    ToNumber

    一般用Number(xx)显示转化。

    • undefined的话,变成NaN
    • null的话,变成0
    • Boolean的话true变成1false变成0
    • 字符串的话,含整数或者小数都可以变成正常数字,其他都是NaN
    Number(undefined); // NaN
    Number(null); // 0
    Number(true); // 1
    Number(false); // 0
    Number('1.2'); // 1.2
    Number('1.2d'); // NaN
    

    对象以及数组,会先转换成基本类型值的等价物,然后根据上面的规则继续转化。

    转换成等价物说白了,就是先调用xx.valueOf()没有这个方法的话,就调用xx.toString(),如果这两方法返回基本类型值的话,则Number(返回值),没返回基本值的话就报错

    var a = {
      valueOf() {
        return '1';
      },
      toString() {
        return '2';
      },
    };
    Number(a); // 1
    
    var b = { c: 1 };
    Number(b); // NaN
    
    var c = {
      c: 1,
      toString() {
        return {};
      },
    };
    Number(c); // 报错
    

    ToBoolean

    一般用Boolean(xx)显示转化。

    将其他类型的值转化为 Boolean 类型的值,其实只要记住哪些转化为false即可,其他的都是true

    • undefined
    • null
    • false
    • +0, -0, NaN
    • ""

    特别注意:

    • 空对象、空函数、空数组转换成 Boolean 的话都是true
    • 用 new 创建基本类型的时候,此时转化成 Boolean 的话也是true
    Boolean({} && [] && function () {}); // true
    Boolean(new String('') && new Number(0) && new Boolean(false)); // true
    

    其他的显式转换

    上面的String(x)/Number(x)/Boolean(x)都是显式转化。

    还有一些其他公认的显式转换:

    // number => string
    1 + '' === String(1);
    // string => number
    +'1' === Number('1');
    // date => number  获取当前时间戳 等同于 Date.now() 或 new Date().getTime()
    +new Date() === Number(new Date());
    // 任意类型 => Boolean
    !!1;
    

    ~x 等同于 -(x+1)

    有时候,还会看到~。 在 JS 里,常和indexOf结合使用。

    -1也是另一种哨兵值,C 语言里-1表示失败。 而 JS 里的indexOf返回值为-1 的话,也表示没找到。

    const isInclude = 'abc'.indexOf('d') !== -1;
    if (isInclude) {
      // ...
    }
    

    这种写法没毛病,但如果用~更简洁,这时候用在 if 里,相当于转换成 Boolean

    const isInclude = ~('abc').indexOf('d')
    if (isInclude).indexOf('d')) {
      // ...
    }
    

    解析数字字符串:和强制转换不一样

    解析数字字符串:从一个字符串中解析出一个数字是 容忍 非数字字符的 —— 从左到右,如果遇到非数字字符就停止解析 。 强制转换是 不容忍 并且会失败而得出值 NaN。

    var a = '42';
    var b = '42px';
    
    Number(a); // 42
    parseInt(a); // 42
    
    Number(b); // NaN
    parseInt(b); // 42
    

    parseInt 是工作在string值上的,所以永远不要传入非 string,不然会强制转换成 string。

    parseInt 还有第二个可选参数,表示将字符串翻译成几进制(2-35),默认是 10 进制,总是在第二个参数值上传递进制,注意,最终返回的结果是 10 进制。

    parseInt('0x16', 10); // 0
    parseInt('0x16', 16); // 22
    parseInt('15', 10); // 15
    // 15作为16进制的翻译,转化为10进制就是21
    parseInt('15', 16); // 21
    

    参数是非字符串的话,会有各种奇怪的现象,所以永远不要传入非 string

    parseInt(1 / 0, 19); // 18  ("I" from "Infinity")
    parseInt(0.000008); // 0   ("0" from "0.000008")
    parseInt(0.0000008); // 8   ("8" from "8e-7")
    parseInt(false, 16); // 250 ("fa" from "false")
    parseInt(parseInt, 16); // 15  ("f" from "function..")
    
    parseInt('0x10'); // 16
    parseInt('103', 2); // 2
    

    其他的隐式转换

    - 、* 、/ 运算符会将两边隐式变成 number 类型

    这个还好,也容易理解。

    '1' - '2' === -1;
    

    + 运算符

    使用加号运算符要小心,加到字符串类型的时候,另一边会强制转化成字符串类型。

    2 + 1 + '1' === '31';
    

    > 和 <

    这种也会发生类型转换,为了消除歧义,最好转化为数字类型之后在使用。

    var a = [42];
    var b = '043';
    
    a < b; // false -- 字符串比较!
    Number(a) < Number(b); // true -- 数字比较!
    
    '1' - '2';
    

    * -> Boolean

    哪个种类的表达式操作(隐含地)要求/强制一个 boolean 转换呢?

    • 在一个if (..)语句中的测试表达式。
    • 在一个for ( .. ; .. ; .. )头部的测试表达式(第二个子句)。
    • while (..)do..while(..)循环中的测试表达式。
    • ? :三元表达式中的测试表达式(第一个子句)。
    • ||(“逻辑或”)和&&(“逻辑与”)操作符左手边的操作数(它用作测试表达式 —— 见下面的讨论!)

    特别注意:一个&&或||操作符产生的值不见得是 Boolean 类型。这个产生的值将总是两个操作数表达式其中之一的值!

    var a = 42;
    var b = 'abc';
    var c = null;
    
    a || b; // 42
    a && b; // "abc"
    
    c || b; // "abc"
    c && b; // null
    
    // 经常可能会写这样的代码
    var a = 42;
    var b = null;
    var c = 'foo';
    
    // 其实这里相当于 if("foo") 因为是if表达式,所以隐式转化为 if(true)
    if (a && (b || c)) {
      console.log('yep');
    }
    

    == 和 ===

    ==两边的转换规则,可能超乎你的想象,所以,最好直接使用===


    起源地下载网 » 转换类型的那些事儿

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元