手记

【三】JavaScript类型:关于类型,有哪些你不知道的细节?

抛出问题

  • 为什么有的编程规范要求用 void 0 代替 undefined?

  • 字符串有最大长度吗?

  • 0.1+0.2不是等于0.3吗?为什么js里面不是这样?

  • es6中的symbol是什么?

  • 为什么给对象添加的方法能用在基本类型上?

一、类型

js语言的每一个值都属于某一种数据类型。js规定了7种语言类型。广泛的用于变量、函数参数、表达式、函数返回值等场合。分别是

  • undefined

  • null

  • boolean

  • string

  • number

  • symbol

  • object

1、undefined、null

undefined表示未定义,它的类型只有一个值,就是undefined。但是js的代码undefined是一个变量,并非一个关键字,会造成可能无意中的篡改,所以使用void 0来获取undefined的值
null表示空值,是js的关键字,所以在任何代码中,都可以用null来获取null的值

2、boolean

boolean有两个值,true和false,表示逻辑上的真和假,同样就具有关键字的true和false来表示

3、string

string表示文本数据。最大长度是2^53-1,一般来说是够用的。但是string的意义并非“字符串”,而是UTF16编码,我们平时的charAt、charCodeAt、length等方法都是针对UTF16编码。所以,字符串最大的长度其实是受字符串的编码长度影响的。

4、number

number表示我们通常意义上的“数字”,大致对应数学中的有理数,当然在计算机中是有精度限制的
js中的number类型有18437736874454810627(即 264-253+3)个值,它基本符合IEEE 754-2008规定的双精度浮点数规则,但是也有几个例外

  • NaN,占用了9007199254740990,这是符合规则的数字

  • Infinity,无穷大

  • -Infinity,无穷小

根据双精度浮点数的定义,number类型中有效的整数范围是-0x1fffffffffffff至0x1fffffffffffff,所以number无法精确表示此范围外的整数

非整数的number类型无法使用==或者===来比较,比如

console.log(0.1 + 0.2 == 0.3)// false

但是我们可以这样干

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

这是使用了js提供的最小精度值,检查等式左右两边差的绝对值是否小于最小精度。

5、symbol

symbol是es6中新引入的类型,是一切非字符串对象key的集合,在es6的规范中,整个对象系统被用symbol重塑
symbol可以具有字符串类型的描述,但是即使描述相同,symbol也不相同
我们创建一个全局的symbol函数

var mySymbol = Symbol("my 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

6、object

object是js中最复杂的类型。也是js的核心机制之一,object是对象的意思。

在js中,对象的定义是“属性的集合”,属性分为数据属性和访问器属性,二者都是key-value的结构,key可以是字符串或者symbol类型

说到对象,我们一定要说一下“类”
在js中,“类”仅仅是运行时对象的一个私有属性,而js中是无法自定义类型的
js中有几个基本类型,都在对象中有自己的“亲戚”

  • number

  • string

  • boolean

  • symbol

所以要知道,3和 new Number(3)是完全[图片上传中...(image.png-75b66f-1549423004254-0)]
不同的值,一个是number的类型,一个是对象类型

二、类型转换

因为js是弱类型语言,所以类型转换发生十分频繁,看图


image.png

装箱变换

装箱变换即把基本类型转换成对应的对象

拆箱变换

拆箱变换即在js中,规定了ToPrimitive函数,它是对象类型到基本类型的转换

    var o = {        valueOf : () => {console.log("valueOf"); return {}},        toString : () => {console.log("toString"); return {}}
    }

    o * 2
    // valueOf
    // toString
    // TypeError

三、写在最后

除了7种用语言类型,还有一些语言的实现者更关心的规范类型

  • list和record:用于描述函数传参的过程

  • set:主要用于解释字符集等

  • completion record:用于描述异常、跳出等语句执行过程

  • reference:用于描述对象属性访问、delete等

  • property descriptor:用于描述对象的属性

  • lexical environment和environment record:用于描述变量和作用域

  • data block:用于描述二进制数据

关于typeof

typeof是用返回操作数的类型,但是我们可以看下图


image.png


可以看出typeof对于object和function是有问题的,这确实是缺陷,但是js之父也说已经错过了修改它的最佳时机了。。



作者:一个致力于GIS的前端爱好者
链接:https://www.jianshu.com/p/b2b9ae0fe090


0人推荐
随时随地看视频
慕课网APP