3.4.1 typeof操作符
| undefined | 表示未定义 |
|---|---|
| boolean | 布尔值 |
| string | 字符串 |
| number | 数值 |
| object | 对象(而不是函数)或null |
| function | 函数 |
| symbol | 符号 |
严格来讲,函数在ECMAScript中被认为是对象,并不代表一种数据类型,可是函数也有自己特殊的属性。因此,可以通过typeof操作符来区分函数和其他对象。
3.4.2 Undefined类型
1.当使用var或者let声明了变量但没有初始化时,相当于给变量赋给了undefined值,也可以手动赋予。 2.增加这个特殊值的目的就是为了正式明确空对象指针(null)和为未初始化变量的区别
3.4.3 Null类型
1.逻辑上讲,null值表示一个空对象指针,这也是typeof传一个null返回obj的原因 2.undefined值是由NULL值派生来的,但是用途完全不一样,任何时候,只要变量要保存对象,而当时又没有那个对象,就该用null来填充变量。这样就可以保持null是空对象指针的含义,并进一步与Undefined分开
类型标签存储在单元的低位中。 其中有五种:000: object. 数据是对象的引用。1: int. 数据是31位有符号整数。010: double. 数据是对双浮点数的引用。100: string. 数据是对字符串的引用。110: boolean. 数据是布尔值。也就是说,最低位是1,然后类型标签只有1位长,即int型。或者最低位为0,那么类型标签的长度为3位,为其余4种类型提供了两个附加位。但有2个值是特殊的:undefined(JSVAL_VOID)是整数−2^30(整数范围之外的数字)。null(JSVAL_NULL) 为机器码NULL的空指针,或者说:为0的object类型标签。
3.4.4 Boolean类型
1.两个字面量值:true/false区分大小写
不同类型与布尔值之间的转换规则
| 数据类型 | 转换为true的值 | 转换为false的值 |
|---|---|---|
| Boolean | true | false |
| String | 非空字符串 | “” |
| Number | 非零数值(包括无穷值) | 0,NaN |
| Object | 任意对象 | null |
| Undefined | 不存在 | undefined |
3.4.5 Number类型
3.4.5.1浮点值
定义浮点值,数值中必须包含小数点,而且小数点后必须至少有一个数字。虽然小数点前面不是必须有整数.
因为储存浮点值使用的内存空间是存储整数值的两倍,所以小数点后面没有数字或者数值本身是整数只是小数点后面跟着0,那也会转换为整数
let floatNum1=1.1;let floatNum2=0.1;let floatNum2=.1;let floatNum2=1.0;//1let floatNum2=2.;//2
科学计数法
3.125e7//31250000以3.125为系数,乘以10的7次幂3e-5//0.00005
浮点值的精确度可达17位小数,在算数运算中远不如整数精确 . 0.1+0.2!=0.3
3.4.5.2值的范围
| 最大值 | Number.MIN_VALUE | 5e-324(-Infinity) |
|---|---|---|
| 最小值 | Number.MAX_VALUE | 1.7976931348623157e+308(Infinity) |
3.4.5.3数值转换
从非空格字符开始转换
| Number( ) | |
|---|---|
| 布尔值 | true为1,false为0 |
| 数值 | 直接返回 |
| null | 0 |
| undefined | NaN |
| 字符串: | |
| 数字 Number(“123”)//123,Number(“00011”)//11,Number(“-50”)//-50,Number(“+50”)//50 | |
| 浮点 Number(“1.1”)//1.1,Number(“0001.1”)//1.1 | |
| 十六进制 Number(“0xf”)//15 | |
| 空字符串 Number(“”)//0 | |
| 其他字符串 Number(“0.1dfd”)//NaN Number(“d0.1fd”)//NaN |
| parseInt( ) | |
|---|---|
| 布尔值 | NaN |
| 数值 | 直接返回 |
| null | NaN |
| undefined | NaN |
| 字符串: | |
| 数字 parseInt(“123”)//123,parseInt(“00011”)//11,parseInt(“-50”)//-50,parseInt(“+50”)//50 | |
| 浮点 parseInt(“1.1”)//1,parseInt(“0001.1”)//1 | |
| 十六进制 parseInt(“0xf”)//15 | |
| parseInt(“10”,2)//2 | 按二进制解析 |
| parseInt(“10”,8)//8 | 按八进制解析 |
| parseInt(“10”,10)//10 | 按十进制解析 |
| parseInt(“10”,16)//16 | 按十六进制解析 |
| 空字符串 parseInt(“”)//NaN | |
| 其他字符串 parseInt(“0.1dfd”)//0 parseInt(“d0.1fd”)//NaN |
| parseFloat( ) | |
|---|---|
| 布尔值 | NaN |
| 数值 | 直接返回 |
| null | NaN |
| undefined | NaN |
| 字符串: | |
| 数字 parseFloat(“123”)//123,parseFloat(“00011”)//11.11,parseFloat(“-50”)//-50,parseFloat(“+50”)//50 | |
| 浮点 parseFloat(“1.1”)//1.1,parseFloat(“0001.10”)//1.1 , parseFloat(“1.12.1”)//1.12 | |
| 十六进制 parseFloat(“0xf”)//0 | |
| 空字符串 parseFloat(“”)//NaN | |
| 其他字符串 parseFloat(“0.1dfd”)//0.1 parseFloat(“d0.1fd”)//NaN |
3.4.5.4NAN
console.log(0/0); //NaNconsole.log(-0/+0); //NaNconsole.log(5/0) //Infinityconsole.log(5/-0) //-Infinityconsole.log(NaN/10); //NaNconsole.log(NaN==NaN);//false
| 判断参数是否不是数值 | ||
|---|---|---|
| isNaN(NaN) | true | |
| isNaN(“string”) | true | 不可以转化为数值 |
| isNaN(“10”) | false | 可以转为数值10 |
| isNaN(10) | false | |
| isNaN(true) | false | 可以转化为数值1 |
3.4.6 String类型
3.4.6.1字符串的特点
字符串是不可变的,要修改某个变量中的字符串值,必须先销毁原始的字符串,然后将包含新值的另一个字符串保存到该变量,如:let lang="java";lang=lang+"script"整个过程中会先分配足够容纳10个字符串的空间,然后填充上"java"和"script"最后销毁原始字符串"java"和字符串"script"
3.4.6.2转换字符串
| toSting() | |
|---|---|
| 数字 | (11).toString()//“11” |
| 转换进制 | |
| (10).toString() //‘10’ | |
| (10).toString(2) //‘1010’ | |
| (10).toString(8) //‘12’ | |
| (10).toString(10) //‘10’ | |
| (10).toString(16) //‘a’ | |
| boolean | (true).toString()//“true” |
| null与undefined | 无此方法 |
| Sting() | |
|---|---|
| 有toString方法的值 | 调用toString(不传参)并返回结构 |
| null/undefined | “null”/“undefined” |
3.4.6.3字符字面量
| 字符字面量 | |||||
|---|---|---|---|---|---|
| \n | 换行 | \t | 制表 | \b | 退格 |
| \r | 回车 | \f | 换页 | \\ | 反斜杠 |
| \‘ \“ \` | 引号 | \xnn \unnnn | 以十六进制编码nn表示的字符[xn],Unicode字符[un] (n:16进制0~F) |
3.4.6.4模版字面量
与使用单引号或双引号不同,模板字面量保留换行字符,可以跨行定义字符串:
let myMultiLineString = 'first line\nsecond line';let myMultiLineTemplateLiteral = `first linesecond line`;console.log(myMultiLineString);// first line// second lineconsole.log(myMultiLineTemplateLiteral);// first line// second lineconsole.log(myMultiLineString === myMultiLinetemplateLiteral); // true
由于模板字面量会保持反引号内部的空格,因此在使用时要格外注意。格式正确的模板字符串看起 来可能会缩进不当:
// 这个模板字面量在换行符之后有 25 个空格符let myTemplateLiteral = `first linesecond line`;console.log(myTemplateLiteral.length); // 47
// 这个模板字面量以一个换行符开头let secondTemplateLiteral = `first linesecond line`;console.log(secondTemplateLiteral[0] === '\n'); // true
3.4.6.5 字符串插值
是可以在一个连续定义中插入一个或多个值,技术上讲,模板字面量不是字符串,而是一种特殊的 JavaScript 句法表达式,只不过求值后得到的是字符串。模板字面量在定义时立即求值并转换为字符串实例,任何插入的变量也会从它们最接近的作 用域中取值。
字符串插值通过在${}中使用一个 JavaScript 表达式实现 , 所有插入的值都会使用 toString()强制转型为字符串,而且任何 JavaScript 表达式都可以用于插值。
let value = 5;let exponent = 'second';let interpolatedTemplateLiteral =`${ value } to the ${ exponent } power is ${ value * value }`;
嵌套的模板字符串无须转义
console.log(`Hello, ${ `World` }!`); // Hello, World!
将表达式转换为字符串时会调用 toString()
let foo = { toString: () => 'World' };console.log(`Hello, ${ foo }!`); // Hello, World!
在插值表达式中可以调用函数和方法
function capitalize(word) {return `${ word[0].toUpperCase() }${ word.slice(1) }`;//toUpperCase() 方法用于把字符串转换为大写}console.log(`${ capitalize('hello') }, ${ capitalize('world') }!`); // Hello, World!
3.4.6.6 模版字面量标签函数 ???
通过标签函数可以自定义插值行为。标签函数会接收被插值记号分隔后的模板和对每个表达式求值的结果。
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 'foobar';}let untaggedResult = `${ a } + ${ b } = ${ a + b }`;let taggedResult = simpleTag`${ a } + ${ b } = ${ a + b }`;// ["", " + ", " = ", ""]// 6// 9// 15console.log(untaggedResult); // "6 + 9 = 15"console.log(taggedResult); // "foobar"
因为表达式参数的数量是可变的,所以通常应该使用剩余操作符(rest operator)将它们收集到一个数组中:
剩余操作符和展开操作符的表示方式一样,都是三个点 ‘…’,但是他们的使用场景会不同,展开操作符(Spread)会”展开“数组编程多个元素,剩余操作符(Rest)一般用在函数的参数里面会把多个元素压缩成一个单一的元素
let a = 6;let b = 9;function simpleTag(strings, ...expressions) {console.log(strings);for(const expression of expressions) {console.log(expression);}return 'foobar';}let taggedResult = simpleTag`${ a } + ${ b } = ${ a + b }`;// ["", " + ", " = ", ""]// 6// 9// 15console.log(taggedResult); // "foobar"
于有 n 个插值的模板字面量,传给标签函数的表达式参数的个数始终是 n,而传给标签函数的第 一个参数所包含的字符串个数则始终是 n+1,则可以????????????
let a = 6;let b = 9;function zipTag(strings, ...expressions) {return strings[0] +expressions.map((e, i) => `${e}${strings[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"
3.4.6.7 原始字符串
用模板字面量也可以直接获取原始的模板字面量内容(如换行符或 Unicode 字符),而不是被转 换后的字符表示。为此,可以使用默认的 String.raw 标签函数:
console.log(`\u00A9`); // ©console.log(String.raw`\u00A9`); // \u00A9console.log(`first line\nsecond line`);// first line// second lineconsole.log(String.raw`first line\nsecond line`);// "first line\nsecond line"// 对实际的换行符来说是不行的// 它们不会被转换成转义序列的形式console.log(String.raw`first linesecond line`);// first line// second line
