JavaScript数据类型和他背后不得不说的故事

基本概念

ECMAScript 中有 5 种简单数据类型(也称为基本数据类型,存放在栈中):Undefined、Null、Boolean、NumberString。还有 1 种复杂数据类型——Object(存放在堆内存中)。ES6的Symbol暂且不论。
1018967-20180718111209824-912970736.png
1018967-20180718115535028-421997257.png编程

简单粗暴地描述一下这几个类型:

  1. Undefined 类型只有一个值,即特殊的 undefined。在使用 var 声明变量但未对其加以初始化时,这个变量的值就是 undefined,例如:编程语言

    var message;
    alert(message == undefined); //true
  2. Null 类型是第二个只有一个值的数据类型,这个特殊的值是 null。从逻辑角度来看,null 值表示一个空对象指针。
  3. Boolean类型:truefalse
  4. Number类型:阿拉伯数字的(八进制、十进制、十六进制、整数、浮点数、5e-324 ~ 1.7976931348623157e+30八、NaN……)。
  5. String类型:带引号的,单引号双引号均可以(字符串),还有一些特殊的字符字面量(\n之类的)函数

    var firstName = "Nicholas";
    var lastName = 'Zakas';
  6. Object类型:ECMAScript 中的对象其实就是一组数据和功能的集合(万物皆对象😄)。对象能够经过执行 new 操做符后跟要建立 的对象类型的名称来建立。而建立 Object 类型的实例并为其添加属性和(或)方法,就能够建立自定义对象,以下所示:spa

    var o = new Object();

typeof操做符

鉴于 ECMAScript 是松散类型的,所以须要有一种手段来检测给定变量的数据类型——typeof就是负责提供这方面信息的操做符。对一个值使用 typeof 操做符可能返回下列某个字符串:设计

  • "undefined"——若是这个值未定义;
  • "boolean"——若是这个值是布尔值;
  • "string"——若是这个值是字符串;
  • "number"——若是这个值是数值;
  • "object"——若是这个值是对象或 null;
  • "function"——若是这个值是函数。

有一些须要注意的地方:

  1. 有些时候,typeof 操做符会返回一些使人迷惑但技术上却正确的值。好比,调用typeof null会返回"object",由于特殊值null被认为是一个空的对象引用。从逻辑角度来看,null 值表示一个空对象指针,而这也正是使用typeof操做符检测null值时会返回"object"的缘由。
  2. 首先,任何涉及 NaN 的操做(例如 NaN/10)都会返回 NaN,这个特色在多步计算中有可能致使问题。其次,NaN与任何值都不相等,包括NaN自己。例如,下面的代码会返回 false:3d

    alert(NaN == NaN); //false
  3. 另外,NaN其实是一种特殊的number指针

    typeof NaN 
    "number"
  4. 《JavaScript高级程序设计》原书上写道:“任何数值除以0都会返回NaN”,但实际上只有 0 除以 0 才会返回 NaN,正数除以 0 返回 Infinity,负数除以 0 返回-Infinity。
  5. ECMAScript定义了isNaN()函数帮咱们肯定这个参数是否“不是数值”。isNaN()在接收到一个值以后,会尝试 将这个值转换为数值。某些不是数值的值会直接转换为数值。下面看几个例子:
alert(isNaN(NaN));      //true
    alert(isNaN(10));       //false(10 是一个数值)
    alert(isNaN("10"));     //false(能够被转换成数值 10)
    alert(isNaN("blue"));   //true(不能转换成数值)
    alert(isNaN(true));     //false(能够被转换成数值 1)

再来看一张图:

v2-80f03dfe036ad4ff0e37150aa7938994_1200x500.jpg

若是被这我的猥琐的笑容吓到了能够先看最下面的《JavaScript高级程序设计》原理部分。code

下面对图上的内容进行分析

>   typeof NaN 
<·  "number"

上面已经提到,在其余编程语言中,任何数值除以 0 都会致使错误,从而中止代码执行。但在 ECMAScript 中,任何数值除以 0 会返回 NaN (原书如此,但实际上只有 0 除以 0 才会返回 NaN,正数除以 0 返回 Infinity,负数除以 0 返回-Infinity),而其被定义为number类型。对象

>   9999999999999999
<·  10000000000000000
>   0.5 + 0.1 == 0.6
<·  true
>   0.1 + 0.2 == 0.3
<·  false

这个是JavaScript的坑,若是非要究其缘由,能够看这篇文章:js中0.1+0.2为何不等于0.3blog

PS:在后面的幂大于20的时候会显示成科学计数法:

>   999999999999999990000
<·  1e+21

上部分的实际结果:

>   0.5 + 0.1
<·  0.6
>   0.1 + 0.2
<·  0.30000000000000004
>   Math.max()
<·  -Infinity
>   Math.min()
<·  Infinity

Math.max() 函数返回一组数中的最大值。
若是没有参数,则结果为 -Infinity。
若是有任一参数不能被转换为数值,则结果为 NaN。
引用自MDN

个人理解是没有参数时,须要比较的一组值就是空,那么空里面的最大值就是-Infinity,Math.min()同理(我的理解,若有错误请指正)。

>   [] + []
<·  ""
>   [] + {}
<·  "[object Object]"
>   {} + []
<·  0
>   true + true + true === 3
<·  true
>   true - true
<·  0
>   true == 1
<·  true
>   true === 1
<·  false
>   (! + [] + [] + ![]).length
<·  9
>   9 + "1"
<·  "91"
>   91 - "1"
<·  90
>   [] == 0
<·  true

这里的大部分运算结果涉及的类型转化能够参考《JavaScript高级程序设计》,文末也有摘抄。

>   true + true + true === 3
<·  true
>   true - true
<·  0
>   true == 1
<·  true
>   true === 1
<·  false

这几个运算可能和书上写的有些误差,“若是有一个操做数是对象、数值或布尔值,则调用它们的 toString()方法取得相应的字符串值,而后再应用前面关于字符串的规则”,——若是是布尔值加减操做,true转为1,false转为0。

>   true + false
<·  1

再看这个

>   [] + {}
<·  "[object Object]"
>   {} + []
<·  0

[] + {}能够理解是调用了各自的toString()方法后再应用字符串相加的规则.

>   [].toString()
<·  ""

>   var obj = {}
<·  undefined
>   obj.toString()
<·  "[object Object]"
相加结果获得"[object Object]"

{} + []为何结果是0?
其实是控制台把{}当作了一个空白表达式,其实是在计算+ []。一元加运算符优先把右边的参数转化为number,就获得了0。若是是上面的obj + []获得的结果就和[] + {}同样都是"[object Object]"

着重看一下这个例子:
(! + [] + [] + ![]).length
首先,逻辑非!有着极高的优先级,因此首先计算的是! + []![]
+ []: + 运算符将[]转化为number结果为0,![]结果为false
式子变成了(true + [] + false).length
[].toString()为"",true + """true""true" + false"truefalse".
"truefalse"长度为9。


《JavaScript高级程序设计》:

加性操做符

加法 加法操做符(+)的用法以下所示:

var result = 1 + 2;
  • 若是两个操做符都是数值,执行常规的加法计算,而后根据下列规则返回结果:
  • 若是有一个操做数是 NaN,则结果是 NaN;
  • 若是是Infinity 加 Infinity,则结果是 Infinity;
  • 若是是-Infinity加-Infinity,则结果是-Infinity;
  • 若是是 Infinity 加-Infinity,则结果是 NaN;
  • 若是是+0加+0,则结果是+0;
  • 若是是+0加-0,则结果是+0。
    不过,若是有一个操做数是字符串,那么就要应用以下规则:
  • 若是两个操做数都是字符串,则将第二个操做数与第一个操做数拼接起来;
  • 若是只有一个操做数是字符串,则将另外一个操做数转换为字符串,而后再将两个字符串拼接起来。
    若是有一个操做数是对象、数值或布尔值,则调用它们的 toString()方法取得相应的字符串值,
    而后再应用前面关于字符串的规则。对于 undefined 和 null,则分别调用 String()函数并取得字 符 串"undefined"和"null"。

减法 减法操做符(-)是另外一个极为经常使用的操做符,其用法以下所示:

var result = 2 - 1;

与加法操做符相似,ECMAScript 中的减法操做符在处理各类数据类型转换时,一样须要遵循一些特殊规则,以下所示:

  • 若是两个操做符都是数值,则执行常规的算术减法操做并返回结果;
  • 若是有一个操做数是 NaN,则结果是 NaN;
  • 若是是 Infinity 减 Infinity,则结果是 NaN;
  • 若是是-Infinity 减-Infinity,则结果是 NaN;
  • 若是是 Infinity 减-Infinity,则结果是 Infinity;
  • 若是是-Infinity 减 Infinity,则结果是-Infinity;
  • 若是是+0 减+0,则结果是+0;
  • 若是是+0 减-0,则结果是-0;
  • 若是是-0 减-0,则结果是+0;
  • 若是有一个操做数是字符串、布尔值、null 或 undefined,则先在后台调用 Number()函数将其转换为数值,而后再根据前面的规则执行减法计算。若是转换的结果是 NaN,则减法的结果就是 NaN;
  • 若是有一个操做数是对象,则调用对象的 valueOf()方法以取得表示该对象的数值。若是获得的值是 NaN,则减法的结果就是 NaN。若是对象没有 valueOf()方法,则调用其 toString()方法并将获得的字符串转换为数值。

相等和不相等

ECMAScript 中的相等操做符由两个等于号(==)表示,若是两个操做数相等,则返回 true。而不相等操做符由叹号后跟等于号(!=)表示,若是两个操做数不相等,则返回 true。这两个操做符都会先转换操做数(一般称为强制转型),而后再比较它们的相等性。

在转换不一样的数据类型时,相等和不相等操做符遵循下列基本规则:

  • 若是有一个操做数是布尔值,则在比较相等性以前先将其转换为数值——false 转换为 0,而true 转换为 1;
  • 若是一个操做数是字符串,另外一个操做数是数值,在比较相等性以前先将字符串转换为数值;
  • 若是一个操做数是对象,另外一个操做数不是,则调用对象的 valueOf()方法,用获得的基本类型值按照前面的规则进行比较;

这两个操做符在进行比较时则要遵循下列规则:

  • null 和 undefined 是相等的。
  • 要比较相等性以前,不能将 null 和 undefined 转换成其余任何值。
PS:简要带几句undefined和null的区别,想要深刻理解能够自行查询,这类文章也挺多的。
null 和 undefined 都表示“值的空缺”,你能够认为undefined是表示系统级的、出乎意料的或相似错误的值的空缺,而null是表示程序级的、正常的或在乎料之中的值的空缺。能够认为undefined表示本该有却没有,null是原本就没有。undefined是未初始化的变量,null是一个空指针对象。佛语有云:“色便是空,空便是色”,“色”想要有却没有,“空”本就是空,指针为空,对象为空。然而“色便是空,空便是色”,undefined == null也成立,不是风动,不是幡动,忍者心动。
  • 若是有一个操做数是 NaN,则相等操做符返回 false,而不相等操做符返回 true。重要提示:即便两个操做数都是 NaN,相等操做符也返回 false;由于按照规则,NaN 不等于 NaN。
  • 若是两个操做数都是对象,则比较它们是否是同一个对象。若是两个操做数都指向同一个对象,则相等操做符返回 true;不然,返回 false。
  • 下表列出了一些特殊状况及比较结果:

clipboard.png


参考:

  1. 《JavaScript高级程序设计》
  2. JavaScript 神奇之旅

在下才疏学浅,如发现错误,请批评指正!

相关文章
相关标签/搜索