JavaScript的几种基础数据类型进阶
JavaScriopt有几种基本类型?5种!Are you sure?
JavaScript常见的有五种基本类型:boolean,undefined,null,number,string。ES6新增了symbol,不常见的数据类型是bigInt。所以从严格意义上来说,目前JavaScript有七种基本数据类型。基本类型的判断使用typeof操作符,所有基础类型不可改变。
下面,我们来一探究竟这些数据类型与其转换规则吧!
Boolean类型在实际的工作中被经常使用,当我们在处理某些JS的业务逻辑时,难免需要通过Boolean值来进行相关的判断,如if,三目运算等。
与Boolean类型相关的Boolean值转换方法是Boolean()函数。Boolean()的转换规则如下
Boolean(true); // true
Boolean(false); // false
Boolean(undefined); // false
Boolean(""); // false
Boolean(" "); // true
Booleam({}); // true
Booleam([]); // true
Boolean(NaN); // false
需要注意的是Boolean函数是if语句的隐式转换规则(括号内为非表达式):
var messeage = " ";
if(messeage) { // 这里if语句进行了隐式转换,对message调用Boolean方法
console.log(message); // " "
}
在使用逻辑非操作符时,这里有一个你可能不知道的骚操作:
!!true; // true
!!false; // false
!!undefined; // false
!!""; // false
!!" "; // true
!!{}; // true
!![]; // true
!!NaN; // false
// 你发现了吗?
两个逻辑非操作转换成Boolean值的结果和Boolean()方法相同。
当然,可以通过new操作符对Boolean函数进行实例化,此时的Boolean为构造函数,可以传入一些参数。
undefined表示当前的变量没有被赋值,它是全局对象的一个变量,不可修改,枚举,配置。
var a;
typeof a; // undefined
typeof b; // undefined,没有报错
a === "undefined"; // true,注意:这里是'==='
b === "undefined"; // Uncaught ReferenceError: b is not defined
通过typeof操作符能判断一个未声明或者已声明未赋值的变量是否是undefined。但是在实际中应该避免未声明变量的基本类型判断,因为它并不适合用于判断对象的属性是否存在。
或者细心的你会发现:
// 当JavaScript运行完某个函数时
function test() {
var a = 100;
console.log(a);
};
test();
// 打开浏览器控制台,你会看到以下输出
// 100
// undefined
所以,当函数没有明确的返回值(return nothing)的时候,它会默认返回一个undefined。
学到了吗?我们可以通过typeof判断某个变量是否未定义,或者你可以这样写:
var non;
// 常规的判断方法
if(typeof non === "undefined") {
// ...
};
// 替代typeof的方法
if(non === void 0) {
// ...
};
// 所以你会看到这样一个神奇的效果
undefined === void 0; // true !!!
判断某个变量未定义,可以判断它是否等于void 0
或者void(0)
,或许你已经在HTML中见识过它的强大了
<a herf="javascript: void(0)">这是一个超链接</a> <!-- 点击后不干任何事 -->
用void 0
代替undefined,可以避免undefined被重写。
首先,null不是一个属性,它是一个值(字面量),它也是一个指针,指向一个空对象的引用。
只有在我们主动将某个变量的值设置为null时,这个变量才能为null
var a = null;
a; // null
这里有一个需要注意的问题:
null == undefined; // true,其实是 == 的隐式转换规则导致
null === undefined; // false
-
Number类型
Number是JavaScrit几种基本类型中最复杂难理解的类型,它包含的几种数值转换方法中总有一些让人费解的地方,虽然在实际的项目中可能并没有很大的意义,但还是需要将其理解透彻,以备不时之需,或者说在遇到问题时才能精准定位。
Number包含两种数值类型:整数和浮点数(或许在其他强类型语言中,字符串有单双进度之分,但对于JS来说,它只表示双精度浮点数,记住了!)
-
无穷值Infinity
在JavaScript中,数值有大小正负之分,所以无穷值也有正无穷+Infinity
(Number.POSITIVE_INFINITY)
和负无穷-Infinity(Number.NEGATIVE_INFINITY)
,ECMAscript中最小值保存在Number.MIN_VALUE
中,如果某个值小于它,那这个值就是-Infinity,对应的最大值为Numner.MAX_VALUE
。Infinity的计算有些难以让人理解:
Infinity + 1; // Infinity; Infinity + Infinity; // Infinity; Infinity - Infinity; // NaN -Infinity + Infinity; // NaN 0 / 0; // NaN
再看看下面这段取最大值的代码:
let arr = [1,5,3,7,2]; let maxVal = 0; arr.forEach(item => { if(item > maxVal) maxVal = item; }) console.log(maxVal); // 7 // 这段代码有问题吗?
如果我们不知道arr数组里面具体的数据(可能全部为负值),那么这段代码能拿到数组中的最大值吗?
答案显然是拿不到,原因是
maxVal = 0
导致0始终是最大值,所以maxVal应该初始化为一个无限小的数值-Infinity:let maxVal = -Infinity;
这就是Infinity的一个实际应用场景。
判断一个数值是否是无穷可以使用isFinite(),ES6新增了Number.isFinite();
-
非数值NaN
NaN是一个数值,通常表示一个计算错误时的返回值,看代码:
typeof NaN; // number Math.sqrt(-1); // 尝试对一个负值求平方根,它将会返回NaN
NaN虽然是一个数值,但是NaN的任何操作都会返回NaN:
NaN/0; // NaN NaN == NaN; // false NaN === NaN; // false NaN != NaN; // true NaN !== NaN; // true
判断一个变量是否是数值可以使用isNaN(),ES6新增了Number.isNaN();
a) isNaN()
而在ES6之前,判断一个值是否是NaN的规则如下:
判断参数是否是Number类型,如果是,则返回true;
如果不是,调用Number()方法,将其转换为Number类型;
然后判断转换后的值是否不恒等于(!==)它自己
// isNaN的实现 var isNaN = function(value) { var nan = Number(value); return nan !== nan; // 此处运用到了NaN !== NaN }
所以,我们可以通过NaN的实现对一些难以理解的结果作出更好的解释:
isNaN(NaN); // true Numer(NaN) == NaN; NaN !== NaN; true isNaN('red'); // true Numer('red') == NaN; NaN !== NaN; true isNaN(true); // false Number(false) == 0; 0 !== 0; false isNaN({}); // true Number({}) == NaN; ... ... isNaN([]); // false Number([]) == 0; ... ...
isNaN另一个强大的地方在于:可以通过它来确定某个值是否可以参与数学运算:
function isCompute(x) { if(isNaN(x)) console.log(x + ' can not be computed!'); }
b) Number.isNaN()
相比于
isNaN()
,Number.isNaN()
方法会将传入的参数转化成数值再判断,因为它更专注于number类型,其判断条件更为苛刻。实现如下var Number.isNaN = function(x) { return typeof x === 'number' && isNaN(x); }; Numer.isNaN(NaN); // true Number.isNaN(true); // false Number.isNaN({}); // false Number.isNaN([]); // false // 从直观的角度来看,[]不能表示为一个数值。
NumberisNaN()
的参数只接受数值,如果要让它返回true,这个数值必定为NaN。 -
数值转换
Number类型的数值转换有三种:Number()、parseInt()和parseFloat()。
a) Number()
Number()函数的转换规则如下:
类型 值 true 1 false 0 null 0 undefined NaN {} NaN [] 0 ‘[]’ NaN [2] 2 [2,1] NaN 十六进制数 十进制数 其他非空对象 对象的valueOf() 等于NaN ? 调用toString() b) parseInt()
相比于
Number()
,parseInt()
是更为严格的转换形式,它是通过查找的方式找到数字,直到遇到第一个非空格字符,如果第一个字符不是数字或者负号,就会返回NaN。它可以接受第二个参数,表示转换的进制:当parseInt传入的第一个参数是字符串时,它会对字符串的每个字符挨个进行数值转换;当传入的第一个参数不是字符时,它会尝试将这个参数转化成十进制的字符串,然后再根据第二个参数对字符串按个转换。
parseInt('1234a'); // 1234 parseInt('10', 8); // 8 8进制的10转换成10进制:1*8^1 + 0*8^0 = 8 parseInt('0x10', 16); // 16 16进制的0x10转化成10进制:12 parseInt('0x10', 8); // 0 8进制的0x10转化成10进制:x是8机制不能解析的字符 parseInt(0x10, 8); /* 14 0x10为16进制,转换成10进制为16,所以相当于 parseInt('16', 8); */
c) parseFloat()
parseFloat
只能解析十进制,他和parseInt
大致相同,但是返回的是浮点数,这里就不再赘述。
-
-
String类型
String类型表示由16个Unicode字符组成的元素,将其他类型的值转换成字符串主要有:toString()、String()。
区别:
toString()
是一个属性方法,调用只能通过点语表示法调用,而且null
和undefined
没有这个方法,ES6新增:function.prototype.toString()
,toString()
可以传入一个参数,表示输出的进制数;String()
是一个构造函数,可以将null和undefined转换成对应的字符串。// 可以自己实现一个String方法并设置一些参数 var String = function(value, hex){ if(value === 'null') return 'null'; else if(value === 'undefined') return 'undefined'; else return value.toString(hex); }
-
Symbol类型
Symbol类型是ES6新增的基本数据类型,也可以将它成为atom(原子),它主要是用于设置对象的属性值,通过Symbol()构造函数可以给对象添加一个匿名属性(此时的键和值都是实例化的Symbol对象,且对象不可枚举)
Symbol('a') !== Symbol('a'); // true var a = Symbol(); typeof a ; // symbol let ob = {}; obj[a] = ‘a’; JSON.stringfy(obj); // '{}'
如需查看Symbol更详细的内容,请点击MDN Symbol
-
BigInt类型
在
Number()
类型中我们提到过:当某个计算后的数值大于Numbner.MAX_VALUE或小于Number.MIN_VALUE时,这个数就是对应的安全的无穷值,在ES规范中它用于表示另一种数据类型:大整数。const x = 2n ** 53n; tyopeof x === 'bigInt'; // true
JavaScript基础类型基本就这些了,内容如有不准确的地方,欢迎指正。
贵有恒何必三更眠五更起,最无益只怕一日曝十日寒。