重学js类型

121 阅读6分钟

js的八大数据类型:Number, String, Boolean, Null, Undefined, Symbol, Object, Bigint.

Undefined

对于一个只申明没有赋初始值的变量,其值是undefined.

let message; // undefined

需要注意的是:对这个message调用typeof返回的是undefined(这很容易理解?!),同时,对一个未申明的变量调用typeof时,也会返回undefined(并不会报错)。

let message;
typeof message; // undefined
typeof age; // undefined

Null

在定义将来要保存对象值的变量时,建议使用null来初始化。

需要注意的是:null类型的变量调用typeof会返回'object'

let car = null;
typeof car; // 'object'

Boolean

Boolean值有两个:truefalse

要将一个其他类型的值转换为布尔值,可以调用特定的Boolean()转型函数

const str = 'this is string'; // typeof str === 'string'
const strToB = Boolean(str); // typeof strToB === 'boolean'

需要注意的是:其他类型转Boolean的转换规则是:**除了"", 0, NaN, null, undefined这5个值转Boolean类型后值为false**外,其他的值转Boolean后的值都为true.

Number

进制

const num1 = 45; // 十进制
const num2 = 070; // 八进制,相当于十进制的56.(非严格模式, 严格模式下使用 0o 开头表示八进制数)
const num3 = 080; // ? 

num3为十进制的80,

因为若是以0开头,其后面的每位数值若是不超过8则表示八进制数,一旦超过则为十进制

科学计数法

默认情况下,ECMAScript会将小数点后至少包含6个零的浮点值转换为科学计数法

console.log(0.0000009); // 打印 9e-7

值的范围

ECMAScript的表示的最大数值保存在**Number.MAX_VALUE中,最小值保存在Number.MIN_VALUE**中。超出这两个值则为Infinity/-Infinity

可以使用**window.isFinite()来判断数值是否在有限范围内.若是在有限范围内(不为Infinity),则返回true**,否则返回false

NaN

特殊值NaN表示Not a Number

NaN不等于NaN

需要注意的是:

ECMAScript中,0-0+0之间相除返回NaN,而**非0值除以0值 **会返回Infinity/-Infinity

console.log(0 / 0); // NaN
console.log(+0 / 0); // NaN
console.log(0 / -0); // NaN

console.log(5 / 0); // Infinity
console.log(5 / -0); // -Infinity
console.log(5 / +0); // Infinity

可以使用window.isNaN()来判断数值是否**‘不是数值’。为什么说,判断数值是否不是数值呢?因为任何不能转换为数值的值都会导致这个函数返回true**

console.log(window.isNaN(NaN)) // true
console.log(window.isNaN('10')) // false => '10'可以转换为数值10
console.log(window.isNaN('a')) // true
console.log(window.isNaN(true)) // false => true可以转换为数值1

由此不难得知,window.isNaN(var)会尝试将var转换为数值,若是可以转换则为false,不可以转换就为true

其他类型转Number规则

三种方式将非数值类型转换为数值:Number()parseInt()parseFloat()

Number()

注意:一元加操作符与Number()遵循相同的转换规则

  • Number()是转型函数,可用于任何数据类型。

  • Boolean类型:true转为1false转为0.

  • null转为0

  • undefined转为NaN // 注意与null的区别

  • String类型:

    ​ 从第一个非空字符串开始,最前面的空格会跳过

    ​ 如果只包含数值(包括合法的正负号,合法的小数点符号),则返回对应的数值。

    ​ 如果包含十六进制/八进制格式,则返回对应进制转换为十进制后的数

    ​ 如果是空字符串,则返回0 // 注意与parseInt的区别

    ​ 如果字符串包含其他字符,则返回NaN

  • Object类型:

    ​ 首先调用valueOf()方法,并按照上述规则转换返回的值。

    ​ 如果没有定义valueOf()方法,调用toString()方法,再按照转换字符串的规则转换

parseInt()

parseInt()更注重于**字符串是否包含数值**。

对于**非字符串**则直接返回 NaN

对于**空字符串则返回NaN** // 注意与Number()的区别

parseInt()接收第二个参数作为进制底数,即表示按第二个参数对应的进制数解析。//网红面试题警告~

  • 从第一个非空字符串开始,最前面的空格会跳过
  • 如果第一个字符不是数值字符、加号或减号。则直接返回NaN
  • 会转换数字字符直到遇到第一个非数字字符。
  • 对于十六进制/八进制。若是包含非限定字符(比如:0xAg,包含了g不在a-f,0-9内),则直接返回NaN。否则返回对应进制转十进制后的数值

parseFloat()

parseFloat()的解析方式与parseInt()的方式类似.

需要注意的是:parseFloat()只解析十进制值,因此不能指定底数

String

字符串是不可变的

如果字符串中包含双字节字符,则length属性返回的值可能不是准确的字符数。??未验证!

其他类型转String规则

两种方法:toString()String()

toString()

nullundefined 没有toString()方法

toString()方法可用于数值布尔值对象(注意与其转Number的区别)和字符串

没毛病,字符串也有toString()方法。该方法只是简单的返回自身的一个副本

注意了,多数情况下,toString()不接受任何参数。但是,如果调用者是数值,toString()也可以接收一个底数参数,表示将数值 转换为对应的进制之后 再输出字符串

String()

怎么将nullundefined转换为String?

可以使用String(),它始终返回表示相应类型的字符串。

转换规则如下:

  • 如果值有toString()方法,则调用该方法(不传参数)并返回结果
  • 如果值是null,则返回'null'
  • 如果值是undefined,则返回undefined

补充:用加号操作符给一个值加上一个空字符串""也可以将其转换为字符串

模板字面量

值得一提的是:模板字面量标签函数。通过这个自定义插值行为...

标签函数的形式应该都是第一个参数为字符串数组,以及其他内容

let a = 6, b = 9
const str = `${a} + ${b} = ${a + b}`
const customStr = simpleTag`${a} + ${b} = ${a + b}`

console.log(str) // '6 + 9 = 15'
console.log(customStr) // 'this is custom str: 6 + 9 = 15'

function simpleTag(strings, ...expressions) {
    // strings[0] === ["", " + ", " = ", ""]
    return 'this is custom str: ' + strings[0] + expressions.map((item, i) => `${item}${strings[i + 1]}`).join('')
}

需要知道的是:

  • 标签函数的第一个参数永远是以插值分割字符串<类似split(插值)>的数组其长度永远是n+1
  • 而对于有n个插值的模板字面量,传给标签函数的表达式的个数始终是n

原始字符串

通过借用模板字面量可以直接获取原始的模板字面量内容(如换行符),而不是转义后的字符串表示。

标签函数的第一个字符串数组会包含一个raw属性,可以返回数组每一项的原始字符串

// 默认字符串数组没有

可以使用默认的**String.raw标签函数**来获取原始字符串的内容:

const str1 = `a\nb`
const str2 = String.raw`a\nb`

console.log(str1)
/*
a
b
*/
console.log(str2)
// a\nb

Symbol

符号是原始值,且符号实例是唯一、不可变的

符号用来创建唯一记号

Symbol()函数不能与new关键字一起作为构造函数使用。这是为了避免创建对象包裹的symbol

...

不清楚... 不明白... 不透彻....

...

symbol作为对象属性时:

使用for...in 获取不到symbol属性

Object.getOwnPropertyNames()返回对象实例的常见属性数组Object.getOwnPropertySymbols()返回对象实例的symbol属性数组 // (它返回的结果是互斥的,也就是说数组不可能包含另一个数组的数组项)

Reflect.ownKeys()返回这两种类型的键