• 《你不知道的JavaScript》整理(六)——强制类型转换


    JavaScript中通常分为两种类型转换,“隐式强制类型转换”(implicit coercion)和“显式强制类型转换”(explicit coercion)。

    下面所有代码的源码可以在此处查看

    一、强制转换为字符串(ToString)

    1)ToString

    基本类型值的字符串化规则为:null转换为"null",undefined转换为"undefined",true转换为"true"。数字的字符串化则遵循通用规则,不过那些极小和极大的数字使用指数形式:

    // 1.07 连续乘以七个 1000
    var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
    // 七个1000一共21位数字
    console.log(a.toString()); // "1.07e21"

    对普通对象来说,除非自行定义,否则toString()(Object.prototype.toString())返回内部属性[[Class]]的值

    2)JSON

    JSON.stringify(..)在对象中遇到undefined、function和symbol时会自动将其忽略,在数组中则会返回null(以保证单元位置不变)。

    如果对象中定义了toJSON()方法,JSON字符串化时会首先调用该方法,然后用它的返回值来进行序列化。

    JSON.stringify(undefined); // undefined
    JSON.stringify(function() {}); // undefined
    
    JSON.stringify(
      [1, undefined, function() {}, 4]
    ); // "[1,null,null,4]"
    JSON.stringify({
        a: 2,
        b: function() {}
    }) // "{"a":2}"

    二、强制转换数字(ToNumber)

    1)ToNumber

    1. true转换为1false转换为0

    2. undefined转换为NaNnull转换为0

    3. ""[]转换为0。处理失败时返回NaN

    4. ToNumber对以0开头的十六进制数并不按十六进制处理

    2)对象

    对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。

    为了将值转换为相应的基本类型值,抽象操作ToPrimitive会首先(通过内部操作DefaultValue)检查该值是否有valueOf()方法。

    如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用toString()的返回值(如果存在)来进行强制类型转换。

    var a = {
      valueOf: function() { //先执行valueOf
        return "42";
      }
    };
    var b = {
      toString: function() { //再执行toString
        return "42";
      }
    };
    var c = [4, 2];
    c.toString = function() {
      return this.join(""); // "42"
    };
    Number(a); // 42
    Number(b); // 42
    Number(c); // 42
    Number(""); // 0
    Number([]); // 0
    Number(["abc"]); // NaN

    三、强制转换布尔值(ToBoolean)

    1)假值(falsy value)

    可强制类型转换为false。包括undefinednullfalse+0-0NaN""

    undefined、nullfalse、+0、-0、NaN、""

    2)真值

    []{}function(){}都不在假值列表中。

    []、{}和function(){}

    四、显式强制类型转换

    1)奇特的~运算符

    ~x大致等同于-(x+1)

    ~42;    // -(42+1) ==> -43

    用~~来截除数字值的小数部分~~中的第一个~执行ToInt32并反转字位,然后第二个~再进行一次字位反转,即将所有字位反转回原值,最后得到的仍然是ToInt32的结果。

    //奇特的~
    var a = "Hello World";
    if (~a.indexOf("lo")) { //如果未找到就返回-1,(-1+1)=0就是false 
      // 找到匹配! 
    }
    
    //~~
    Math.floor(-49.6); // -50
    ~~-49.6; // -49

    2)显式解析数字字符串

    解析允许字符串中含有非数字字符,解析按从左到右的顺序,如果遇到非数字字符就停止。

    转换不允许出现非数字字符,否则会失败并返回NaN。

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

    解析字符串中的浮点数可以使用 parseFloat(..) 函数。

    非字符串参数会首先被强制类型转换为字符串(执行toString方法)。

    parseInt(0.000008); // 0 ("0" 来自于 "0.000008")
    parseInt(0.0000008); // 8 ("8" 来自于 "8e-7") 
    parseInt(false, 16); // 250 ("fa" 来自于 "false") 
    parseInt(parseInt, 16); // 15 ("f" 来自于 "function..")
    
    parseInt("0x10"); // 16 
    parseInt("103", 2); // 2

    五、隐式强制类型

    1)字符串和数字之间的隐式强制类型转换

    如果+其中一个操作数是字符串则执行字符串拼接;否则执行数字加法。

    如果其中一个操作数是对象(包括数组), 则对其调用 ToPrimitive 抽象操作。

    var a = "42";
    var b = "0";
    a + b; // "420" 两个都是字符串
    var c = 42;
    var d = 0;
    c + d; // 42 两个都是数字
    var a = [1, 2];
    var b = [3, 4];
    a + b; // "1,23,4" 两个都是对象

    2)隐式强制类型转换为布尔值

    以下情况,非布尔值会被隐式强制类型转换为布尔值,遵循ToBoolean 抽 象操作规则。

    1. if (..)语句中的条件判断表达式。

    2. for ( .. ; .. ; .. )语句中的条件判断表达式(第二个)。

    3. while (..)do..while(..)循环中的条件判断表达式。

    4. ? :中的条件判断表达式。

    5.  逻辑运算符||(逻辑或)和&&(逻辑与)左边的操作数(作为条件判断表达式)。

    六、宽松相等和严格相等

    常见的误区是“ == 检查值是否相等, === 检查值和类型是否相等”。听起来蛮有道理,然而 还不够准确。

    正确的解释是:“ == 允许在相等比较中进行强制类型转换,而 === 不允许

    1)字符串和数字之间的相等比较

    1.如果 Type(x) 是数字, Type(y) 是字符串,则返回 x == ToNumber(y) 的结果。

    2.如果 Type(x) 是字符串, Type(y) 是数字,则返回 ToNumber(x) == y 的结果。

    2)其他类型和布尔类型之间的相等比较

    1.如果 Type(x) 是布尔类型,则返回 ToNumber(x) == y 的结果。

    2.如果 Type(y) 是布尔类型,则返回 x == ToNumber(y) 的结果。

    3)null 和 undefined 之间的相等比较

    1.如果 x 为 null , y 为 undefined ,则结果为 true 。

    2.如果 x 为 undefined , y 为 null ,则结果为 true 。

    4)对象和非对象之间的相等比较

    1.如果 Type(x) 是字符串或数字, Type(y) 是对象,则返回 x == ToPrimitive(y) 的结果。

    2.如果 Type(x) 是对象, Type(y) 是字符串或数字,则返回 ToPromitive(x) == y 的结果。

    var a = "abc";
    var b = Object(a); // 和new String( a )一样
    a === b; // false 
    //b 通过 ToPromitive 进行强制类型转换(也称为“拆封”,unboxed或者unwrapped) ,并返回标量基本类型值 "abc" ,与 a 相等。
    a == b; // true
    
    //null和undefined不能够被封装(boxed),Object(null)和 Object(undefined) 均返回一个常规对象。
    var a = null;
    var b = Object(a); // 和Object()一样
    a == b; // false
    
    var c = undefined;
    var d = Object(c); // 和Object()一样
    c == d; // false
    //NaN能够被封装为数字封装对象,但NaN不等于NaN
    var e = NaN;
    var f = Object(e); // 和new Number( e )一样
    e == f; // false

    5)假值的相等比较

    假值,就是上面ToBoolean中提到的假值。

    "0" == false;//true 按照2)和1)的规则
    false == 0;//true 按照2)的规则
    false == "";//true 按照2)和1)的规则
    false == [];//true 按照4)2)1)的规则
    "" == 0;//true 按照1)
    "" == [];//true 按照4)的规则
    0 == [];//true 按照4)1)的规则
    [] == ![]// true ![]执行后的值是false

    6)安全运用隐式强制类型转换

    1.如果两边的值中有true或者false,千万不要使用==。

    2.如果两边的值中有[]、0或者"" ,尽量不要使用==。

    7)比较图表

    dorey提供的一张在线图表




  • 相关阅读:
    .Net加密保护工具分析介绍
    正则表达式
    easyui datagrid toolbar 添加搜索框
    为jQuery-easyui的tab组件添加右键菜单功能
    苹果系统无法启动的解决步骤
    解决MVC4发布在IIS7后,路径无法访问.apk文件的解决方法
    C#微信公众平台开发者模式开启代码
    ios svn无法连接xp或者win7系统svn的解决方法
    SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败解决方案
    easyui textarea回车导致datagrid 数据无法展示的问题
  • 原文地址:https://www.cnblogs.com/strick/p/6440147.html
Copyright © 2020-2023  润新知