JavaScript数据类型
简单数据类型
- Undefined:当使用var和let声明变量但是没有赋值的时候,就相当于给变量赋值了一个undefined值,一般来说,不用显式地给某个变量设置undefined值,字面值undefined主要用于比较,增加这个特殊值就是为了明确空对象指针null和变量为初始化区别
- Null:逻辑上讲null值表示一个空指针对象,这也是typeof null = object 的原因。undefined是由null派生而来的,因此ECMA-262将他们定义为表面相等即
null == undefined
结果为true,虽然是派生而来的,但是它们两个的使用方式完全不同,undefined尽量不要主动给一个变量赋值为undefined,而null值则不同,当变量要保存对象,但是现在还没有时,可以给一个变量赋值为null。 - Boolean:就两个值
true
和false
数据类型 | true | false |
---|---|---|
String | 非空字符串 | “”(空字符串) |
Number | 非零数值(包括无穷值) | 0、NaN |
Object | 任意对象 | null |
Undefind | N/A(不存在的) | undefined |
-
Number:最常用的是10进制数字,直接写就行,整数也可以用8进制字面量来表示。第一个数字必须为0,然后是相应的八进制数值(0-7)。如果字面量中包含超过应有的范围,JavaScript引擎就会忽略前面的0当成10进制处理。
let num1 = 070 // 八进制的56
let num2 = 079 // 无效的八进制值,当成79处理八进制在严格模式下是无效的,会导致JavaScript引擎抛出语法错误。ECMAScript 2015中的八进制通过前缀
0o
表示;严格模式下0会被视为语法错误,如果要表示八进制值,应使用前缀0o
要创建十六进制字面量,必须给数值加前缀 0x (x 区分大小写),然后是十六进制数字(0-9,A-F),
使用八进制和十六进制格式创建的数值在所有数学操作中都被视为十进制数值浮点数:定义浮点数,数值中必须含有小数点,而且小数点后面至少跟一位数字
let float1 = 1.1;
let float2 = 0.1;
let float3 = .1 // 不推荐(不要为了装X这样写)
浮点数的内存空间为整数的两倍。
科学计数法:100000 = 1E+5; 或者 10000 = 1e+5; 0.00001 = 1E-5 或者 1e-5
浮点值的精确度最高可达到17位小数,没有整数准确,比如 0.1+0.2 !== 0.3值的范围:
- 最小值:Number.MIN_VALUE
- 最大值:Number.MAX_VALUE
- 正无穷:Infinity
- 负无穷:-Infinity
注意:: 由于JavaScript保存数值的方式,实际中可能存在正零(+0)和负零(-0)。正零和负零在所有情况下都被认为是等同的。
NaN:Not a Number,用于表示本来要返回的数值的操作失败了,并不是抛错。任何涉及NaN的操作返回的结果都是NaN。NaN不等于包括NaN在内的任何值 NaN==NaN (false)。可以通过isNaN(),接收任意数据类型。可以判断这个数值是否为NaN。可以通过这个函数测试对象。
- 首先会调用对象的valueOf()方法。valueOf方法返回Math对象的原始值。这个原始值由Math对象派生的所有对象继承。valueOf()方法通常由JavaScript在后台自动调用,并不显示地出现在代码中。
- 再确定返回的值是否可以转为数值。
- 如果不能再调用toString()方法,并测试其返回值。
数值转化
有三个函数可以将非数值:Number()、parseInt()和parseFloat()。Number()是转型函数、可以用于任何函数类型。后两个函数主要用于将字符串转换成数值。Number函数转化
-
布尔值,true转为1,false转为0
-
数值,直接返回
-
null,直接返回0
-
undefined,返回NaN
-
字符串
- 如果字符串包含数值字符,直接转成数值返回(忽略前面的0)
- 如果字符串包含有效的浮点型格式,则会转为相应的浮点值(忽略前面的0)
- 如果字符串包含有效的十六进制格式如0xf,则会转为该十六进制对应的十进制整数
- 如果是空字符串,返回0
- 如果字符串包含上述情况之外的其他字符,返回NaN
-
对象:调用valueOf方法,并按照上述规则转化返回的值,如果转化的结果是NaN,则调用toString()方法。
parseInt():字符串最前面的空格会被忽略,从第一个非空字符串开始转化。如果第一个字符串不是数值字符、加号或减号,parseInt()立即返回NaN。这就意味着空字符串也会返回NaN。Number()转空字符串结果为0。
123abc会被转为123, 123.2会被转为123
。 parseInt还接受第二个参数,用于指定进制数,parseInt(10,2)= 2。如果传入第二个参数会按照相应的形式解析let num1 = parseInt(10, 2) // 2,会按照二进制解析 let num2 = parseInt(10, 8) // 8,会按照八进制解析 let num3 = parseInt(10, 10) // 10,按照十进制解析 let num4 = parseInt(10, 16) // 16,按照16进制解析
parseFloat():与parseInt的用法差不错,与之不同的是这个函数可以识别所有的浮点型格式,以及十进制格式(开头的0始终忽略)。十六进制数值始终会返回0.因为它只能解析10进制值,所以不能解析指定进制数,如果是字符串表示的整数(没有小数点或者小数点后面有一个0)则会返回整数。
let num1 = parseFloat('123blue'); // 123,会按照整数解析 let num2 = parseFloat('0xA); // 0, 始终为0 let num3 = parseFloat('22.3'); // 22.3 let num4 = parseFloat('0908.5); // 908.5 let num5 = parseFloat('22.35.5'); // 22.3 let num6 = parsFloat('3.123e7); // 31250000
-
String:字符串,表示零或多个16为的Unicode字符序列。可以使用双引号,单引号,反引号标示。
字符串字面量
字面量 | 含义 |
---|---|
\n | 换行 |
\t | 制表 |
\b | 退格 |
\r | 回车 |
\f | 换页 |
\ | 反斜杠(\) |
\’ | 单引号(’) |
\" | 双引号(”) |
\` | 反引号(`) |
\xnn | 以16进制编码nn表示字符(n是以16进制数字0-F),\x41 = “A” |
\unnnn | 以16进制编码nnnn表示Unicode字符(n是以16进制数字0-F) \u03a3 = “∑“ |
字符串特点:
Es6规定的字符串是不能变的,一旦创建值就不能改变了。要修改某个字符串的值,必须先销毁原始字符串,然后将包含新的另一个字符串保存到改变量。
字符串转化:
toSting()
首先几乎所有的值都可以使用toString()方法。这个方法的唯一用途就是返回当前值字符串表示,toString()方法可以转化数值、布尔值、对象和字符串值(字符串也有toString()方法,该方法只是简单地返回自身的一个副本。)null和undefined没有toString()方法。默认toString()不需要接收参数,但是数值字符串可以传入一个底数参数,通过传入的底数可以得到数值字符串的进制结果。
let num = 10;
num.toString() // "10" 十进制结果
num.toString(2) // "1010" 二进制结果
num.toString(8) // "12" 八进制结果
num.toString(16) // "a"
String()
因为null和undefined没有toString()方法,可以使用String()转型函数,它始终会返回相应类型的字符串
- 如果值有toString()方法,则调用toString()方法
- 如果是null,返回null
- 如果是undefined,返回undefined
其实还有更加简单的方式在值的后面 +"",这也转化字符串的方法
字符串插值:
let num1 = 9;
let num2 = 15;
let str = `衬衫的价格是${num1}镑${num2}便士。`;
console.log(str); // 衬衫的价格是9镑15便士。
所有插入的值都会使用toString()强制转型为字符串,而且任何JavaScript表达式都可以用于插值。嵌套的模板字符串无须转义
模板字面量支持标签函数(tag function),通过标签函数可以自定义插值行为。标签函数会接收被插值记号分割后的模板和对每个表达式求值的结果。
let a = 6;
let b = 9;
function simpleTag(strings, aValExpression, bValExpression, sumExpression) {
console.log(strings);
console.log(aValExpression);
console.log(bValExpression);
console.log(sumExpression);
return 'str';
}
let untaggedResult = `${a} + ${b} = ${a + b}`;
let taggedResult = simpleTag`${a} + ${b} = ${a + b}`;
// ["", " + ", " = ", ""]
// 6
// 9
// 15
console.log(untaggedResult); // "6 + 9 = 15"
console.log(taggedResult); // "str"
因为表达式参数的数量是可变的,所以通常应该使用剩余操作符(rest operator)将它们收集到一个数组中。
let a = 6;
let b = 9;
function simpleTag(strings, ...expressions) {
console.log(strings);
for(const expression of expressions){
console.log(expressions);
}
return 'str';
}
let taggedResult = simpleTag`${a} + ${b} = ${a + b}`;
// ["", " + ", " = ", ""]
// 6
// 9
// 15
对于n个插值的模板字面量,传递给标签函数的表达式参数的个数始终是n,而传给标签函数的第一个参数所包含的的字符串个数始终是n+1.因此,如果想要把这些字符串和对表达式求值的结果拼接起来作为默认字符串,可以这样做
let a = 6;
let b = 9;
function zipTag(strings, ...expressions) {
return strings[0] + expressions.map((e,i) => `${e}${string[i + 1]}`).join('');
}
let untaggeDResult = `${a}+${b} = ${a+b}`;
let taggedResult = zipTag`${a}+${b} = ${a+b}`;
console.log(untaggeDResult); // “6+9=15”
console.log(taggedResult); // "6+9=15"
原始字符串:
使用模板字面量也可以直接获取原始的模板字符串内容,而不是被转换后的字符表示,可以使用String.raw标签函数。
console.log(`\u00A9`); // © 也是版权符号
console.log(String.raw`\u00A9`); // \u00A9
// 换行符提示
console.log(`first line\nsecond line`);
// first line
// second line
console.log(String.raw`first line\nsecond line`); // "first line\nsecond line"
另外,也可以通过标签字符串的第一个参数,即字符串数组的.raw属性取得每个字符串的原始内容。
function printRaw(strings) {
console.log('Actual characters:');
for (const string of strings) {
console.log(string);
}
console.log('Escaped characters;');
for(const rawString of strings.raw) {
console.log(rawString);
}
}
printRaw`\u00A9${'and'}\n`;
// Actual characters;
// ©
// 换行符
// Escaped characters;
// \u00A9
// \n