美文网首页《重学前端》读后感
《重学前端》读后感(05|JavaScript类型:关于类型,有

《重学前端》读后感(05|JavaScript类型:关于类型,有

作者: BlueSeaBoat | 来源:发表于2019-02-25 01:36 被阅读55次

    先看5个问题:
    1、为什么有的编程规范要求用void 0 代替 undefined?
    2、字符串有最大长度吗?
    3、0.1+0.2不是等于0.3么?为什么JavaScript里不是这样的?
    4、ES6新加入的Symbol是个什么东西?
    5、为什么给对象添加的方法能用在基本类型上?

    JavaScript模块会从运行时、文法和执行过程三个角度去剖析JS的知识体系。
    运行时类型是代码实际执行过程中我们用到的类型。所有类型数据都会属于7个类型之一。从变量、参数、返回值到表达式中间结果,任何的JavaScript代码运行过程中产生的数据,都具有运行时类型。

    类型
    JavaScript语言的每一个值都属于某一种数据类型。JavaScript语言规定了7种语言类型。语言类型广泛用于变量、函数参数、表达式、函数返回值等场合。根据最新的语言标准,这7种语言类型是:

    1、Undefined
    2、Null
    3、Boolean
    4、String
    5、Number
    6、Symbol(ES6新加)
    7、Object
    

    Undefined、Null

    Undefined类型表示未定义,它的类型只有一个值,就是undefined。任何变量赋值是Undefined类型、值为undefined,一般我们可以用全局变量undefined来表达这个值,或者void运算把任一一个表达式变成undefined值。

    但是呢,undefined是一个变量,而并非是一个关键字,这也是JavaScript公认的设计失误之一,所以,为了避免无意中被篡改,建议使用void 0来获取undefined值。

    Undefined跟null有一定的表意差别,null表示:定义了但是为空。所以,一般在实际中不会把变量赋值为undefined,这样可以保证所有值为undefined的变量,都是未赋值的自然状态。

    Null类型也只有一个值null,null是关键字,所以在任何代码中都可以放心用null关键字来获取null的值。

    Boolean

    Boolean类型有两个值,true和false,表示逻辑意义上的真和假,同时也是两个关键字。

    String

    String用来表示文本数据。String有最大长度2^53 - 1,有趣的是这个最大长度,并不完全是你理解的字符数。
    因为String的意义并非“字符串”,而是字符串的UTF16编码,字符串的操作charAt、charCodeAt、length等方法针对的都是UTF16编码。所以,字符串的最大长度,实际上是受字符串的编码长度影响的。

    现行的国际标准,字符是以Unicode的方式表示的,每一个Unicode的码点表示一个字符。
    理论上,Unicode的范围是无限的。
    UTF是Unicode的编码方式,规定了码点在计算机中的表示方法,
    常见的有UTF16和UTF8。
    Unicode的码点通常用U+???来表示,其中???是十六进制的码点值。
    0-65536(U+0000 - U+FFFF)的码点被称为基本字符区域(BMP)
    

    JavaScript中的字符是用于无法变更的,一旦字符串被构造出来,无法用任何方式改变字符串的内容,所以字符串具有值类型的特征。
    JavaScript字符串把每个UTF16单元当作一个字符来处理,所以处理非BMP(超过U+0000 - U+FFFF范围)的字符时,应该格外小心。
    JavaScript的这个设计继承自Java,最新的标准中是这样解释的:为了性能和尽可能实现起来简单。因为现实中很少用到BMP之外的字符。

    Number

    Number类型有18437736874454810627(即:2^64 - 2^53 + 3)个值。
    Number类型基本符合IEEE 754-2008规定的双精度浮点规则,但是JavaScript为了表达几个额外的语言场景(比如不让除以0出错,引入无穷大概念),规定了几个例外情况:
    1、NaN,占用了9007199254740990,这原本符合IEEE规则的数字。
    2、Infinity,无穷大。
    3、-Infinity,负无穷大。
    另外,值得注意的是,JavaScript有+0和-0之分,加法没有区别,在除法中的场合就要进行特别的区分,“忘记检测除以0,而得到负无穷大”的情况经常会导致错误,而区分+0和-0的方式,正是检测1/x是Infinity还是-Infinity。
    根据双精度浮点数的定义,Number中有效的整数范围是-0x1fffffffffffff 至 0x1fffffffffffff,所以Number无法精确表示此范围外的整数。
    同样根据浮点数定义,非整数的Number类型无法用==(===也不行)来比较。

      console.log( 0.1 + 0.2 == 0.3);
    

    输出结果是false,说明两边不对等,这是浮点运算的特点,浮点数运算的精度问题导致等式左右的结果并不是严格的相等,而是相差了微小的值。
    所以实际上,错误的不是结论,而是比较的方法,JavaScript提供最小精度值的比较方法:

      console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);
    

    检查等式两边差的绝对值是否小于最小精度,这才是正确的比较浮点数的方法。输出结果为true。

    Symbol

    Symbol是ES6中引入的新类型,它是一切非字符串对象的key集合,在ES6规范中,整个对象系统被用Symbol重塑。
    Symbol具有字符串类型的描述,即使描述相同,Symbol也不相等。
    我们创建Symnol的方式是使用全局Symbol函数,例如:

    var mySymbol = Symbol("my Symbol")
    

    一些标准中提到的Symbol,可以在全局的Symbol函数属性中找到,例如,可以用Symbol.iterator来自定义for...of在对象上的行为:

    var o = new Object
    o[Symbol.iterator] = function({
      var v = 0
      return {
        next:function(){
          return { value : v++; done : v > 10}
        }
      } 
    })
    for(var v of o){
      console.log(v)  // 0 1 2 3 ... 9
    }
    

    Object

    Object表示对象的意思,是一切有形和无形的物体的总称。在JavaScript中,对象的定义是“属性的集合”。属性分为数据属性和访问器属性,二者都是key-value结构,key可以是字符串或者Symbol类型。
    提到对象,就必须提到一个概念——类。JavaScript中的“类”仅仅是运行时对象的一个私有属性,而JavaScript中是无法自定义类型的。
    JavaScript中的几个基本类型,在对象类型中有一个“亲戚”,它们是:

      Number
      String
      Boolean
      Symbol
    

    所以我们就必须认识到3与new Number(3)是完全不同的值,它们一个是Number类型,一个是对象类型。
    Number、String和Boolean,三个构造器是两用的,当跟new搭配时,它们产生对象,当直接调用的时候,它们表示强制类型转换。
    Symbol函数比较特殊,直接用new调用会抛出错误,但它仍然是Symbol的构造器。
    JavaScript语言设计上试图模糊对象和基本类型之间的关系,我们日常代码可以把对象的方法用在基本类型上使用,比如:

        console.log("abc".charAt(0)); //a
    

    甚至在原型上添加方法,都可以应用于基本类型,比如以下代码,在Symbol原型上添加hello方法,在任何的Symbol类型变量都能调用。

        Symbol.prototype.hello = () => console.log("hello");
    
        var a = Symbol("a");
        console.log(typeof a); //symbol,a 并非对象
        a.hello(); //hello,有效
    

    所以文章开头的问题,答案是:. 运算提供了装箱操作,它会根据基础类型构造一个临时对象,使得我们能在基础类型上调用对应对象的方法。

    类型转换

    因为JavaScript是弱类型语言,所以类型转换发生得非常频繁,大部分我们熟悉的运算都会先进行类型转换。
    待续...

    最后上一张总结图


    侵删

    相关文章

      网友评论

        本文标题:《重学前端》读后感(05|JavaScript类型:关于类型,有

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