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

发布时间:2019-08-15 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了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+308、NaN……)。
  5. String类型:带引号的,单引号双引号都可以(字符串),还有一些特殊的字符字面量(n之类的)

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

    var o = new Object();

@L_777_19@操作符

鉴于 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:

    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高级程序设计》原理部分。

面对图上的内容进行分析

>   typeof NaN"number" 

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

>   999999999999999910000000000000000
>   0.5 + 0.1 == 0.6true
>   0.1 + 0.2 == 0.3false

这个是JavaScript的坑,如果非要究其原因,可以看这篇文章js中0.1+0.2为什么不等于0.3

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

>   9999999999999999900001e+21

上部分的实际结果:

>   0.5 + 0.10.6
>   0.1 + 0.20.30000000000000004
>   Math.max()
<·  -Infinity
>   Math.min()
<·  Infinity

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

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

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

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

>   true + true + true === 3true
>   true - true0
>   true == 1true
>   true === 1false

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

>   true + false1

再看这个

>   [] + {}
<·  "[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。
  • 下表列出了一些特殊情况及比较结果:

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


参考:

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

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

脚本宝典总结

以上是脚本宝典为你收集整理的JavaScript数据类型和他背后不得不说的故事全部内容,希望文章能够帮你解决JavaScript数据类型和他背后不得不说的故事所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。