JavaScript 数据类型

196 阅读7分钟

1、七种数据类型

七种数据类型

1.1 null

  1. 基本类型中唯一一个假值
  2. null是空值,指曾经赋值过,但是目前没有值
  3. 是一个特殊关键字,不是标识符,我们不能将其当作变量来使用和赋值

1.2 undefined

  1. 没有值,从未赋值
  2. 是一个标识符,可以当做变量使用和赋值

2 其他

2.1 typeof

数据类型 typeof
null "object"(是语言的bug)
number "number"
boolean "boolean"
string "string"
boolean "boolean"
object "object"
Symbol "symbol"
undeclared "undefined"
NaN "number"

2.2 undeclared

报 错:ReferenceError: a is not defined

2.3 NaN

  1. 是 JavaScript 中唯一一个不等于自身的值。
  2. isNaN(..) 有一个严重的缺陷,“检查参数是否不是NaN,也不是数字”,输入字符串返回true
  3. ES6 Number.isNaN(..)

3总结

3.1 数据类型总结

  1. JavaScript 中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。
  2. JavaScript 不做“类型强制” --- JS不是强类型语言
  3. 在对变量执行 typeof操作时,得到的结果并不是该变量的类型,而是该变量持有的值的类 型,因为 JavaScript 中的变量没有类型。
  4. undefined(声明但还没有赋值的变量)不同于 undeclared(未声明)。 变量未声明,是undeclared;对象属性不存在,是undefined

3.2 数组

  1. 在 JavaScript 中,数组可以容纳任何类型的值
  2. delete删除数组元素,length 属性不会变化
  3. 稀疏”数组(sparse array):含有空白或空缺单元的数组\
  4. 数组通过数字进行索引,也可以包含字符串键值和属性,但是不计算在数组长度内
  5. 如果字符串键值能够被强制类型转换为十进制数字的话,它就会被当作数字索引来处理。
  6. 类数组 用slice转换成数组 var arr = Array.prototype.slice.call( arguments );
  7. arguments 对象从 ES6 开始已废止

3.3 字符串

  1. 字符串经常被当成字符数组,但实际上字符串和字符数组并不是一回事
  2. 字符是类数组,有length 属性以及 indexOf(..)(从 ES5开始数组支持此方法)和concat(..) 方法
  3. JavaScript 中字符串是不可变的,而数组是可变的。所以str[0]='a' 赋值失败,正确的方法应该是 a.charAt(1)。
  4. 字符串不可变是指字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符串。而数组的成员函数都是在其原始值上进行操作。
  5. 数组有一个字符串没有的反转函数 reverse():

3.4 数字

  1. JavaScript 只有一种数值类型:number(数字),包括“整数”和带小数的十进制数,“整数”之所以加引号是因为JavaScript 没有真正意义上的整数
  2. JavaScript 中的“整数”就是没有小数的十进制数。所以 42.0 即等同于“整数”42。
  3. JavaScript 使用的是“双精 度”格式(即 64 位二进制)。
  4. 数字前面的 0 可以省略 .42
  5. 小数点后小数部分最后面的 0 也可以省略 42.
  6. log时小数部分最后面的 0 被省略 a=43.30000 输出a为43.3
  7. 指数
var a = 5E10;
a; // 50000000000 
a.toExponential(); // "5e+10" -- 有引号
  1. tofixed(..) 方法可指定小数部分的显示位数 输出结果实际上是字符串
  2. toPrecision(..)方法用来指定有效数位的显示位数(加上整数,不加指数,输出字符串)
  3. 数字常量也可以调用Number对象的方法,但是要多加一个.
// 无效语法:
42.toFixed( 3 ); // SyntaxError
// 下面的语法都有效: 
(42).toFixed( 3 ); // "42.000"
 0.42.toFixed( 3 ); // "0.420" 
 42..toFixed( 3 ); // "42.000"
 42 .toFixed(3); // "42.000"

3.5各种进制

  1. 八进制 OO Oo 十六进制 OX Ox 二进制 OB Ob
  2. 浮点数 0.1 + 0.2 === 0.3; // false
  3. 3、设置一个误差范围值,叫机器精度(machine epsilon),JS中这个值通常是 2^-52 (2.220446049250313e-16)。
  4. ES6,Number.EPSILON Math.abs( n1 - n2 ) < Number.EPSILON
  5. 最大浮点数 Number. MAX_VALUE 中。最小浮点数定义在 Number.MIN_VALUE 中,它不是负数,但 无限接近于 0 !
  6. 能够被“安全”呈现的最大整数是2^53 - 1,在ES6中被定义为 Number.MAX_SAFE_INTEGER。
  7. 最 小 整 数 是 -9007199254740991, 在 ES6 中 被 定 义 为 Number. MIN_SAFE_INTEGER。
  8. JavaScript 的数字类型无法精确呈现 64位数值,所以必须将它们保存(转换)为字符串。
  9. 检测一个值是否是整数,可以使用 ES6 中的 Number.isInteger(..) 方法
  10. 检测一个值是否是安全的整数,可以使用 ES6 中的 Number.isSafeInteger(..) 方法
  11. 数位运算符|只适用于32位 整数

3.6特殊数值

  1. 通过 void 运算符即可得到undefined,比如 void a
  2. void并不改变表达式的结果, 只是让表达式不返回值
  3. 无穷
1 / 0;   Number.POSITIVE_INfiNITY 
-1 / 0;  Number.NEGATIVE_ INfiNITY
Infinity/ Infinity = NaN   
有穷正数 / Infinity =  0
  1. 计算结果一旦溢出为无穷数(infinity)就无法再得到有穷数。可以从有 穷走向无穷,但无法从无穷回到有穷。

3.7 负零 -0

  1. 加法和减法运算不会得到负零
  2. 0和负数的乘除操作会返回-0
  3. JSON.stringify(-0) 返回 "0",而 JSON.parse("-0") 返回 -0。
  4. -0 == 0; // true
  5. 1 / -0 = Number.NEGATIVE_ INfiNITY
  6. 判断负零 isNegZero(..)
  7. ES6 中新加入了一个工具方法 Object.is(..) 来判断两个值是否绝对相等,Object.is( -3 * 0, -0 ); //true 能使用 == 和 ===时就尽量不要使用 Object.is(..),因为前者效率更高,Object.is(..) 主要用来处理那些特殊的相等比较。

3.8 值和引用

  1. JavaScript 中没有指针,变量不可能成为指向另一个变量的引用。JavaScript 引用指向的是值。
  2. JavaScript 对值和引用的赋值传递在语法上没有区别,完全根据值的类型来决定
  3. 简单值(即标量基本类型值)总是通过值复制的方式来赋值 / 传递
  4. 复合值——对象,总是通过引用复制的方式来赋值 / 传递。
  5. 由于引用指向的是值本身而非变量,所以一个引用无法更改另一个引用的指向。
理解以下代码:
var c = [1,2,3];
var d = c; // d是[1,2,3]的一个引用 d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]

var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]
// 然后
b = [4,5,6]; 
a; // [1,2,3] 
b; // [4,5,6]

//我们不能通过引用 x 来更改引用 a 的指向,只能更改 a 和 x 共同指向的值。
function foo(x) {
    x.push( 4 );
    x; // [1,2,3,4]
    // 然后
    x = [4,5,6]; 
    x.push( 7 );
    x; // [4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; // 是[1,2,3,4],不是[4,5,6,7]

//要将 a 的值变为 [4,5,6,7],必须更改 x 指向的数组,而不是为 x 赋值一个新的数组。
function foo(x) { 
    x.push( 4 );
    x; // [1,2,3,4]
    // 然后
    x.length = 0; // 清空数组 x.push( 4, 5, 6, 7 );
    x; // [4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; // 是[4,5,6,7],不是[1,2,3,4]
  1. 想通过值复制的方式来传递复合值(如数组),就需要为其创建一个复本,这样传递的 就不再是原始值。例如foo( a.slice() );
  2. 要将标量基本类型值传递到函数内并进行更改,就需要将该值封装到一个复合值(对象、数组等)中,然后通过引用复制的方式传递。
function foo(x) {
    x = x + 1;
    x; // 3 }
var a = 2;
var b = new Number( a ); // Object(a)也一样
foo( b );
console.log( b ); // 是2,不是3

标量基本类型值是不可更改的(字符串和布尔也是如此)。
如果一个数字对象的标量基本类型值是2,那么该值就不能更改,除非创建一个包含新值的数字对象。
x = x + 1中,x中的标量基本类型值2从数字对象中拆封(或者提取)出来后,
x就神不知鬼不觉地从引用变成了数字对象,它的值为2 + 1等于3。然而函数外的b仍然指向原来那个值为 2 的数字对象。
  1. 基本类型的值是不可变的
var str = "123hello321";
str.toUpperCase();     // 123HELLO321
console.log(str);      // 123hello321
  1. 基本类型的比较是它们的值的比较
var a = 1;
var b = true;
console.log(a == b);    // true
console.log(a === b);   // false
  1. 引用类型的比较是引用的比较
var obj1 = {};    // 新建一个空对象 obj1
var obj2 = {};    // 新建一个空对象 obj2
console.log(obj1 == obj2);    // false
console.log(obj1 === obj2);   // false

相关资料

《你不知道的JS中卷》