目录
- 前言
- 数据类型
- 1、typeof操作符
- 2、Undefined类型
- 3、Null类型
- 3、Boolean类型
- 4、Number类型
- (1)整数
- (2)浮点数
- (3)值的范围
- (4)NaN(Not a Number)
- (5)数值转换
- 5、String类型
- (1)字符字面量
- (2)转换为字符串
- (3)模板字面量:
- (4)字符串插值
- (5)模板字面量标签函数
- (6)获取原始字符串
前言
本篇笔记 JS 语言基础 第二篇。
主要包含内容为:
- typeof 操作符和 ES5 中的简单数据类型
复杂数据类型 Object 和 ES6 新增的 Symbol 类型在下一篇。
数据类型
六种简单数据类型(原始类型):
Undefined | Null | Boolean | Number | String | Symbol(ES6新增) |
未定义 | 空 | 布尔 | 数值 | 字符串 | 符号 |
复杂数据类型:
Object(对象),是一种无序名值对的集合(感觉可以理解为 python 的字典类型)。
1、typeof操作符
typeof会返回的值:
undefined | boolean | number | string | symbol | object | function |
值未定义 | 值为布尔 | 值为数值 | 值为字符串 | 值为符号 | 值为对象或null | 值为函数 |
console.log(typeof message); // undefined
console.log(typeof true); // boolean
console.log(typeof 1); // number
console.log(typeof 'hello'); // string
console.log(typeof {a: 'a'}); // object
console.log(typeof {}); // object
console.log(typeof null); // object
function test(){}
console.log(typeof test); // function
let sym = Symbol();
console.log(typeof sym); // symbol
调用 “typeof null” 返回的 “object” ,这是因为 null 被认为是一个对空对象的引用。
严格来说,函数在 ECMAScript 中被认为是对象,并不代表一种数据类型。可是,函数也有自己的特殊属性。为此就有必要通过 typeof 来区分函数和其他对象。
2、Undefined类型
Undefined 类型只有一个值,undefined。当使用 var 和 let 声明变量但没有初始化时,就相当于给该变量赋予了 undefined 值。
var message;
let msg;
console.log(message, msg); // undefined undefined
let msg1 = undefined;
console.log(msg1 == undefined); // true
// let msg2;
console.log(typeof msg2);
// undefined, msg2未声明,但返回值也是 undefined
增加 undefined 的目的就是为了正式明确空对象指针( null )和未初始化变量的区别。
当声明了变量值为 undefined 时,使用 if 语句, 如下:
var message;
if (message) {
console.log(message); // 无输出
}
if (!message) {
console.log(message); // undefined
}
3、Null类型
Null 类型同样只有一个值,null。调用 “typeof null” 返回的 “object” ,这是因为 null 被认为是一个对空对象的引用。
console.log(typeof null); // object
- 在定义将来要保存对象值的变量时,建议使用 null 来初始化。这样,只要检查这个变量的值是不是 null 就可以知道这个变量是否在后来被重新赋予了一个对象的引用。
如:
let message = null;
if (!message) {
console.log('message is null'); // message is null
}
- undefined 值是由 null 值派生来的,因此 ECMA-262 将他们定义为表面上相等,如:
console.log(undefined == null); // true
3、Boolean类型
Boolean 类型有两个值,true 和 false。
不同类型值转换为布尔值的转换规则:
数据类型 | 转换为 true | 转换为 false |
Boolean | true | false |
String | 非空字符串 | 空字符串( “” ) |
Number | 非零数值(包括无穷值) | 0、NaN |
Object | 任意对象 | null |
Undefined | N/A(不存在) | undefined |
4、Number类型
Number 类型使用 IEEE 754 格式表示整数和浮点数。
(1)整数
- 十进制整数
let num_10 = 55;
- 八进制整数
let num_8 = 067; // 八进制
console.log(num_8); // 55 十进制
- 十六进制整数
let num_16 = 0x37; // 十六进制
console.log(num_16); // 55 十进制
(2)浮点数
定义浮点数必须包含小数点,且小数点后必须有数字。小数点前可以没有数字。
对于非常大或者非常小的数值,浮点值可以用科学计数法表示。格式为:一个 Number 类型(整数或浮点数)后跟一个 e 或 E,再加上要乘的10的多少次幂。如:
let floatNum = 1.25e4;
console.log(floatNum); // 12500
浮点数的精度最高可到 17 位小数,但在计算中不完全精准,例如:0.1 + 0.2 = 0.30000000000000004,而非0.3。由于这种微小的差异,导致很难测试特定的浮点值。
if (0.1 + 0.2 == 0.3) {
console.log(true);
} else {
console.log(false);
} // false
这种差异是因为使用了 IEEE 754 数值,而非 ECMAScript 自身的问题。因此建议永远不要测试某个特定的浮点值。
(3)值的范围
console.log(Number.MAX_VALUE);
// 1.7976931348623157e+308 可表示的最大值
console.log(Number.MIN_VALUE);
// 5e-324 可表示的最小值
如果某个值超过了 js 可以表示的范围,那么这个数值会被自动转换为一个特殊的 Infinity 值(无穷)。任何无法表示的负值以 -Infinity(无穷小)表示,正值则用 Infinity(无穷大)表示。
Q:怎么判断一个值是不是无穷?
A:可以使用 isFinite() 函数测试一个值是不是无穷。如:console.log(isFinite(Number.MAX_VALUE)) // true
(4)NaN(Not a Number)
特殊值 NaN 用来表示本来要返回数值的操作失败了(而不是抛出错误)。如下:
console.log(0 / 0); // NaN
console.log(1 / 0); // Infinity
console.log(-0 / +0); // NaN
console.log(+0 / -0); // NaN
console.log(1 / +0); // Infinity
console.log(1 / -0); // -Infinity
由上可知,当分子分母同为 0 时,返回值为 NaN;当分子不为0,分母为0时,返回值为 Infinity 或 -Infinity。不会有人会问还有一种情况吧?0 / 1 = 0 不知道啊?👀👀👀
NaN 的几个独特属性:
- 任何涉及NaN 的操作始终返回 NaN。如:
console.log(1 + NaN); // NaN
console.log(1 - NaN); // NaN
console.log(1 * NaN); // NaN
console.log(1 / NaN); // NaN
console.log(NaN / 1); // NaN
- NaN 不等于包括 NaN 在内的所有值。如:
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
Q:怎么判断一个值是不是 NaN 呢?
A:使用 isNaN() 函数,参数可以是任意数据类型。如:console.log(isNaN(NaN)); // true console.log(isNaN(1)); // false 数值 1 console.log(isNaN('1')); // false 可以转换成数值 1 console.log(isNaN('aaa')); // true 不可以转换成数值 console.log(isNaN({a: '1'})); // true 不可以转换为数值 console.log(isNaN(true)); // flase 可以转换成数值 1 console.log(isNaN(null)); // false 可以转换成数值 0
(5)数值转换
有三个函数可以将非数值转换为数值:
- Number()
执行规则:
数据类型 | 转换方式 |
Boolean | true 为 1,false 为 0 |
Number | 直接返回 |
Null | 返回 0 |
Undefined | 返回 NaN |
String | ①如果是纯数值型(包括正负、浮点数、八进制、十六进制)的字符串,转换为十进制数值; ②如果是空字符串,转换为 0; ③如果非以上两种类型,返回 NaN。 |
Object | 先调用 valueof() 方法,按上述规则转换返回的值。如果转换结果为 NaN ,则调用 toString() 方法,再按照转换字符串的规则转换。 |
如下:
console.log(Number(1)); // 1
console.log(Number('1')); // 1
console.log(Number('hello')); // NaN
console.log(Number('')); // 0
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(undefined)); // NaN
- parseInt()
此函数更专注于将字符串是否包含数值模式,在需要得到整数时建议优先使用。
转换时从第一个非空格字符开始转换,①若第一个非空格字符不是数值或正负号,则立即返回 NaN。与 Number() 不同的是,空字符串在此处也会返回 NaN,而不是 0。②若第一个字符是数值或正负号,则依次向下检测,直到碰到非数值字符或字符串末尾结束。如下:
console.log(parseInt(' 123')); // 123
console.log(parseInt('')); // NaN
console.log(parseInt('-123abc')); // -123
console.log(parseInt('abc123')); // NaN
console.log(parseInt('1.1')); // 1
同样的,此函数也能理解不同进制的参数,并返回相应的十进制整数。
上述为接收一个参数的形式,此函数还可以接收第二个参数:
console.log(parseInt('0x56', 16)); // 86 以十六进制输入第一个参数,返回该十六进制数的十进制数
console.log(parseInt('56', 16)); // 86 省略标识 0x 也行,但是得有第二个参数 16
console.log(parseInt('056', 8)); // 46 以八进制输入第一个参数,返回该八进制数的十进制数
console.log(parseInt('56', 8)); // 46 省略标识 0 也行,但是得有第二个参数 8
- parseFloat()
与 parseInt() 函数类似,但是它只解析十进制数,十六进制统统转化为 0 ,八进制转换为 0 后面跟的数值,如:0506 → 506。没有小数点或小数点后为 0,则转换为整数。
5、String类型
字符串可以用双引号,单添加链接描述引号或反引号标识。如:
let str1 = "aaaa";
let str2 = 'aaaa';
let str3 = `aaaa`;
(1)字符字面量
用 \ 定义,例如:\n,\t 等。
(2)转换为字符串
- 首选:toString() 方法
例如:
let num = 111,
bool = true;
console.log(num.toString(), bool.toString()); // 111 true
一般来说,此方法没有接收参数,但是它也可以接受一个参数,表示用几进制来展示该值。如:
let num = 10;
console.log(num.toString()); // 10
console.log(num.toString(2)); // 1010
console.log(num.toString(8)); // 12
console.log(num.toString(10)); // 10
console.log(num.toString(16)); // a
null 和 undefined 没有 toString() 方法。
- 原数据类型 + “”(空字符串)
例如
let num = 111,
bool = true;
console.log(num + "", bool + ""); // 111 true
console.log(typeof (num + ""), typeof (bool + "")); // String String
- String() 函数
此函数与 toString() 方法的区别为:当值为 null 或 undefined 时,会返回 “null” 和 “undefined” 。此区别也适用于 方法二 和 toString() 方法的区别。例如:
console.log(undefined + ""); // undefined
console.log(typeof (undefined + "")); // String
console.log(null + ""); // null
console.log(typeof (null + "")); // String
console.log(String(undefined)); // undefined
console.log(typeof String(undefined + "")); // String
console.log(String(null)); // null
console.log(typeof String(null + "")); // String
(3)模板字面量:
ES6 新增使用模板字面量定义字符串的能力。例如:
let str1 = 'first\nsecond';
console.log(str1);
// first
// second
let str2 = `first
second`;
console.log(str2);
// first
// second
如上,str1 使用了 ”\n“ 转义字符定义了一个可以换行的字符串,而 str2 使用反引号 (``)+ 回车键,即可实现与 str1相同的效果。回车符 “\n” 在 str2 中也占有位置。
console.log(str2.substring(5, 6) === '\n'); // true
因为模板字面量可以直接定义多行的字符串,因此,也很方便用来定义 HTML 模板。如:
let html = ` <div> <a href='#'> hello world! </a> </div>`;
(4)字符串插值
let num = 1;
// 原始插值方式
let result = num + ' + ' + num + ' = 2';
// ES6 新增插值方式
let result1 = `${ num } + ${ num } = 2`;
console.log(result); // 1 + 1 = 2
console.log(result1); // 1 + 1 = 2
插值表达式中也能调用函数和方法:
function test(word) {
return `${ word[0].toUpperCase() }${ word.slice(1) }`;
// 先将 word 的首字母大写,然后插入 word 删去首字母的剩下部分
}
console.log(`${ test('hellow')} , ${ test('world') } !`); // Hellow , World !
插值表达式也能插入自己之前的值。
let value = '';
function test() {
value = `${ value }abc`;
console.log(value);
}
test(); // abc
test(); // abcabc
test(); // abcabcabc
(5)模板字面量标签函数
标签函数本身是一个常规函数,通过前缀到模板字面量来应用自定义行为。如:
let a = 6,
b = 9;
function simpleTag(String, aValue, bValue, sum) {
console.log(String);
console.log(aValue);
console.log(bValue);
console.log(sum);
return `foobar`;
}
let untag = `${ a } + ${ b } = ${ a + b }`;
// console.log(untag); // 6 + 9 = 15
// console.log(simpleTag(untag));
// 6 + 9 = 15
// undefined
// undefined
// undefined
console.log(simpleTag`${ a } + ${ b } = ${ a + b }`)
// ["", " + ", " = ", ""]
// 6 console.log(String)的输出
// 9 console.log(aValue)的输出
// 15 console.log(sum)的输出
// foobar return `foobar`的输出
使用剩余操作符(三个点:…):
剩余操作符
let a = 6,
b = 9;
function zipTag(string, ...exp) {
// exp.map((e, i) =>{
// console.log(e, i)
// })
return string[0] + exp.map((e, i) => `${ e }${ string[i + 1] }`).join('');
}
console.log(zipTag`${ a } + ${ b } = ${ a + b }`); // 6 + 9 = 15
(6)获取原始字符串
使用 String.raw 来获取原始的模板字面量内容。
console.log(`\u00A9`); // ©
console.log(String.raw`\u00A9`); // \u00A9
实际的换行符无法获取。如:
console.log(String.raw`firsr\nsecond`); // firsr\nsecond
console.log(String.raw`firsr
second`);
// first
// second