基本数据类型介绍
JavaScript中基本数据类型包括7种:Undefined、Null、Boolean、Number、String、Symbol、BigInt
Undefined类型
Undefined类型只有一个唯一的字面值undefined,表示的是一个变量不存在
- 使用只声明而未初始化的变量时,会返回“undefined”
let a;
console.log(a); // undefined
- 获取一个对象的某个不存在的属性(自身属性和原型链继承属性)时,会返回“undefined”
const obj = { name: 'kingx' };
console.log(obj.address); // undefined
- 函数没有明确的返回值时,却在其他地方使用了返回值,会返回“undefined”
function foo() {}
console.log(foo()); // undefined
- 函数定义时使用了多个形参,而在调用时传递的参数的数量少于形参数量,那么未匹配上的参数就为“undefined”
function foo(param1, param2, param3) {
console.log(param3);
}
foo(1, 2); // undefined
Null类型
Null表示一个空指针对象,这个也是typeof null === 'object'的浅层原因。深层原因: null在内存中存储是000,和对象是一样的,这也是js设计初时的一个bug
- 一般情况下,如果声明的变量是为了以后保存某个值,则应该在声明时就将其赋值为“null”。
let returnObj = null;
function foo() {
return { name: 'kingx' };
}
returnObj = foo();
- JavaScript在获取DOM元素时,如果没有获取到指定的元素对象,就会返回“null”
- 在使用正则表达式进行捕获match, 字符串执行正则exec时,如果没有结果,就会返回“null”
Undefined和Null的异同
相同点
- 进行类型转换为Boolean时,都是false
- 进行取值时都会抛出TypeError,也是平常最常见的错误
- Undefined类型派生自Null类型,所以在非严格相等的情况下,两者是相等的。
null == undefined // true
不同点
- null是JavaScript中的关键字,而undefined是JavaScript中的一个全局变量,即挂载在window对象上的一个变量,并不是关键字
- typeof运算符,null是'object',undefined是'undefined'
- 在通过call调用toString()函数时,Undefined类型的值会返回“[object Undefined]”,而Null类型的值会返回“[object Null]”
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
- 在需要进行字符串类型的转换时,null会转换为字符串"null",而undefined会转换为字符串"undefined"
- 在需要进行数值类型的转换时,undefined会转换为NaN,无法参与计算;null会转换为0,可以参与计算,这里进行了(隐式)类型转换
undefined + 0; // NaN
null + 0; // 0
无论在什么情况下都没有必要将一个变量显式设置为undefined。如果需要定义某个变量来保存将来要使用的对象,应该将其初始化为null。这样不仅能将null作为空对象指针的惯例,还有助于区分null和undefined
Boolean类型
true和false,一般用于if判断。if(a)中a可以是任意类型,如果a不是Boolean,那么将会Boolean(a)进行隐式类型转换
注意点:
- String类型,空字符串""或者''都会转换为false,非空字符串(包括' '空格字符串)转换为true
- Number类型,0和NaN都会转换为false,其他都是true
- Oject类型,null转换为false,其他都是true
- Function类型,都会转换为true
- Undefined类型,转换为false
Number类型
js中Number包括整型和浮点型,最基本的是十进制,也可以十六进制和八进制表示
const num1 = 024 // 20
const num2 = 0x3f // 63
其中num1首位为0,表示八进制数,然后判断后面每位数值在0~7内,符合八进制数据表示规则, 如果后面有一位不在范围内,直接会忽略前面的0
num2是十六进制表示,如果后面有一位数不在范围0~9、a~f或A~f内,则会抛出异常"SyntaxError:Invalid or unexpected token"
Number函数
- Boolean转换成Number
true // 1
false // 0
- Null转换为0,Undefined转换为NaN
- String转换成Number需要注意以下几点:
- 如果字符串中只包含数字,则会转换成十进制数;如果前面有0,会直接省略掉,例如"0123"会转换为123
- 如果字符串中包含的是有效的浮点数,则同样按照十进制转换,例如"1.23"会转换为1.23
- 如果字符串中包含有效的十六进制格式,则会按照十进制转换,例如"0x3f"会转换为63
- 如果是空字符串,空格字符串,则转换为0
- 如果字符串中包含了除上述格式以外的字符串,则会直接转换为NaN
- 如果是数字,会按照对应的进制数据格式,统一转换为十进制并返回
Number(10); // 10
Number(010); // 8,010是八进制的数据,转换成十进制是8
Number(0x10); // 16,0x10是十六进制数据,转换成十进制是16
- 如果值为字符串类型,有以下规则
-
如果该字符串只包含数字,则会直接转换成十进制数;如果数字前面有0,则会直接忽略这个0,八进制也会忽略
Number('21'); // 21 Number('012'); // 12 -
如果字符串是有效的浮点数形式,则会直接转换成对应的浮点数,前置的多个重复的0会被清空,只保留一个
-
如果字符串是有效的十六进制形式,则会转换为对应的十进制数值
Number('0x12'); // 18 Number('0x21'); // 33 -
如果字符串包含了任何不是以上情况的其他格式内容,则会返回“NaN”
6. Object类型在转换为Number类型时,会优先调用valueOf()函数,然后通过valueOf()函数的返回值如果是Number直接返回,如果不是再调用toString(),toString的结果再按上述规则进行转换。
const obj = {
valueOf() {
console.log('valueOf');
return {}
},
// valueOf() {
// console.log('valueOf');
// return NaN
// },
toString() {
console.log('toString');
return 1
}
}
console.log(Number(obj));
// valueOf
// toString
// 1
// valueOf
// NaN
parseInt函数
parseInt(string, radix = 10) radix范围是2-36,返回结果是十进制数字
- 如果遇到传入的参数是非字符串类型的情况,则会调用toString()转换为字符串,即使传入的是整型数据
parseInt('0x12', 16); // 18
parseInt(0x12, 16); // 24 这里会将0x12调用toString会转换成十进制数字的字符串'18'
- parseInt()函数在做转换时,对于传入的字符串会采用前置匹配的原则。即从字符串的第一个字符开始匹配,如果处于基数指定的范围,则保留并继续往后匹配满足条件的字符,直到某个字符不满足基数指定的数据范围,则从该字符开始,舍弃后面的全部字符。在获取到满足条件的字符后,将这些字符转换为整数
parseInt("fg123", 16); // 15 直接舍弃了f后面的所有字符,因为g不在16进制范围内
parseInt('0x12',16); // 18 = 16 + 2
parseInt('0x12',10); // 0 x不在十进制范围内
- 对浮点型数的处理,如果传入的值是浮点型数,则会忽略小数点及后面的数,直接取整
- 任何整数以0为基数取整时,都会返回本身。radix不在范围内、第一个字符串不在进制范围内,返回NaN。这里就涉及一个map和parseInt的面试题。
const arr = ['1', '2', '3', '4'];
const result = arr.map(parseInt);
console.log(result); // [1, NaN, NaN, NaN]
parseFloat函数
parseFloat(string)
与parseInt()函数相比,parseFloat()函数没有进制的概念,所以在转换时会相对简单些,注意点:
- 如果在解析过程中遇到了正负号(+ / -)、数字0~9、小数点或者科学计数法(e / E)以外的字符,则会忽略从该字符开始至结束的所有字符,然后返回当前已经解析的字符的浮点数形式
parseFloat('+1.2'); // 1.2
parseFloat('-1.2'); // -1.2
parseFloat('++1.2'); // NaN,符号不能连续出现
parseFloat('--1.2'); // NaN,符号不能连续出现
parseFloat('1+1.2'); // 1,'+'出现在第二位,不会当作符号位处理
- 字符串前面的空白符会直接忽略,如果第一个字符就无法解析,则会直接返回“NaN”
- 对于字符串中出现的合法科学运算符e,进行运算处理后会转换成浮点型数,这点与parseInt()函数的处理有很大的不同
parseFloat('4e3'); // 4000
parseInt('4e3', 10); // 4
```。
4. 对于小数点,只能正确匹配第一个,第二个小数点是无效的,它后面的字符也都将被忽略
```js
parseFloat('11.20'); // 11.2
parseFloat('11.2.1'); // 11.2
parseFloat('11..2'); // 11
Symbol
ES6引入的新的类型,表示唯一标识性ID,特点如下:
- Symbol值的唯一性
- 不能使用new操作符
- 不能参与类型运算
let s4 = Symbol('hello');
s4.toString(); // Symbol(hello)
's4 content is: ' + s4; // TypeError: Cannot convert a Symbol value to a string
- 可以使用同一个Symbol值。使用Symbol.for()方法,接收一个字符串,然后搜索是否有这个参数作为名称的Symbol值,有直接返回,没有创建返回
- Symbol的用法如下:
- 作为对象的属性名
- 用于属性区分,解耦代码
- 属性名遍历,不能通过Object.keys()和forin遍历出来,JSON.stringify也不会显示出来。可以通过Object.getOwnPropertySymbols()、Reflect.ownKeys()遍历Symbol属性
BigInt
ES6引入的新类型,大整数。通过后面加n与普通数字进行区分
- BigInt必须要有参数,参数不能是小数,会报错
BigInt(123) // 123n
BigInt('123') // 123n
BigInt(false) // 0n
BigInt(true) // 1n
BigInt(1.5) // RangeError
BigInt('1.5') // SyntaxError
new BigInt() // TypeError BigInt is not a constructor
BigInt(undefined) //TypeError
BigInt(null) // TypeError
BigInt('123n') // SyntaxError
BigInt('abc') // SyntaxError
- 不能使用new操作符
- 可以参与数学运算,数据类型必须相同。下面两个符号除外
- 不带符号的右移位运算符
>>> - 一元的求正运算符
+
总结
因为js弱类型的原因,数据类型的细节比较多,需要多实践和理解才能掌握。