zoukankan      html  css  js  c++  java
  • JS的隐式转换 从 [] ==false 说起

    前言

    最近和大创扯淡时说到了[] == false,从结果上来看我俩都答错了,从气势上来说我俩的歪理都能出书了(恩,程序猿的骄傲),但是这其实背后隐藏了一潭很深的水,对,很深。。。

     

    隐式类型转换

    JS的数据类型

    首先,回想一下JS的类型都有什么。

    原始值(primitives): undefined, null, booleans, numbers,strings, symbol(es6)

    对象值(objects): Object

    ok, 这就是全部了,我们接下来看看到底发生了什么导致隐式转换如此不可捉摸。

    ToPrimitive

    在发生转换的时候,js其实都是会将操作对象转化为原始的对象,这也是最为诟病的地方,因为js很难直接抛出错误,她会用一套自己的方法去理解我们的错误,并做相应的调整,哪怕这些错误我们是无意识的。所以我们要知道她的转换方式,才能做到知己知彼,对代码的控制更为精准。

    签名:ToPrimitive(input, PreferredType?) //PreferredType: Number 或者 String

    流程如下:

    1.  input为原始值,直接返回;
    2. 不是原始值,调用该对象的valueOf()方法,如果结果是原始值,返回原始值;
    3. 调用valueOf()不是原始值,调用此对象的toString()方法,如果结果为原始值,返回原始值;
    4. 如果返回的不是原始值,抛出异常TypeError。

    其中PreferredType控制线调取valueOf()还是toString()。

    ps: Date类型按照String去调用。

    ok,通过这个隐式装箱,我们得到了操作数的原始值。接下来,我们根据不同情况,看看发生了什么呢~

    数学运算

    想必大家用过以下做法去完成类型转换吧

    var str = '1';
    var num = str - 0;
    
    var num = 2;
    var str = num + '';

    这种类似的数学运算会做类型转换,*/-操作符都是数字运算专用的。当这些运算符与字符串一起使用时,会强制转换字符串为数字类型的值。但是‘+’尤为致命,为啥捏?

    当'+'作为双目运算符时,如a+b。

    它的运行如下:

    1. 计算两个操作数的原始值: prima = ToPrimitive(a), prima = ToPrimitive(b);
    2. 如果原始值有String,全部转换为String,返回String相加后的结果;
    3. 如果原始值没有String,全部转换为Number, 返回Number相加后的结果;

    当'+'作为单目运算符时, 例如 +a.

    流程是这样的:

    1. 将a转换为Number,Number(a);

    举个栗子:

    [] + []

    1. 转换为原始类型 toPrimitive([]);
    
    [].valueOf();//[],不是原始类型
    
    [].toString();//"",真是令人发指的转换
    
    2. 都为string,所以返回字符串想家的结果
    
    return "" + "";

    {} + [] 与 [] + {}

    {} + []
    1. 在浏览器中,JS引擎认为第一个{}为空代码块,所以 这里的 '+'是单目运算符(node中认为是对象,解析为"[object Object]")
    
    ToPrimitive([]); //""
    
    2. Number("");//0
    
    
    [] + {}
    1. ToPrimitive([]); //""
        ToPrimitive({}); //"[object Object]"
    
    2. 都为string
        return "" + "[object Object]";//"[object Object]"
    
    

    PS: [].valueOf 为[], 但在ES6中JS会优先调用[Symbol ToPrimitive]来转换为原始类型。

    比较运算

    首先,比较运算分为2种, 一种为严格比较(===),只有类型相等,值也一致时才会为true,否则为false, 另一种为抽象相等也叫宽松相等(==),先将运算数转化为相同类型,再做比较,具体过程见 Abstract Equality Comparison Algorithm

    这个算法大致说了这么几个情况,x == y

    • xy都为Null或undefined,return true;
    • x或y为NaN, return false;
    • 如果x和y为String,Number,Boolean并且类型不一致,都转为Number再进行比较
    • 如果存在Object,转换为原始值,比较

    回到这篇文章的导火索,[] == false

    1.存在object, 转化为原始值
    ToPrimitive([]); // ''
    
    2.一个string, 另外为boolean,都转为number
    Number('');//0
    Number(false);//0
    
    3.return 0 == 0;/true

    备注

    ToPrimitive

     value toNumber  toString  toBoolean 
     NaN  NaN  "NaN"  false
     Infinity  Infinity  "Infinity"  true
     []  0  '""  true
     [1]  1  "1"  true
    null 0 "null" false
    undefined NaN "undefined" false
    {} NaN "[object Object]" true
    function() NaN "function" true

    ToNumber

    ToString

     

    2017/12/05

    winking说了一个简便的方法去理解[] toPrimitive = ‘’ , 想成join()就好了 (*^▽^*)

  • 相关阅读:
    关于Windows7
    我家妞妞长大了
    我家乡的美景
    WinCE开发的语言思考
    坐看肖大师的精彩表演
    Windows Embedded Compact 7试用笔记(1)——新变化
    数据库介绍1(体系结构、基本管理)
    数据库介绍(MySQL安装 体系结构、基本管理)
    shell编程基础简述
    数据库介绍1MySQL安装
  • 原文地址:https://www.cnblogs.com/nanchen/p/7905528.html
Copyright © 2011-2022 走看看