阅读 58

JavaScript 数据类型、数据转换、检测方法

导读

今天我们来认识一下js中的数据类型,数据之间的显示转换和隐式转换,还有一些如何来检测这些数据类型的方法。js中有7中数据类型,分别如下:

  • undefined 类型
  • null 类型
  • string 字符串类型
  • number 数字类型
  • boolean 布尔值类型
  • Symbol 类型
  • object 类型

数据类型

undefined 类型

undefined是js中的一个特殊值,也是一个假值。一个声明过但是没有初始化的变量,js会自动给变量赋值undefined。

let name;
console.log(name) // undefined
复制代码

有一个方法typeof 用来检测数据类型,但是这个方法有一个问题,请看下面:

let name;
console.log(typeof name) // undefined
console.log(typeof age) // undefined
复制代码

并没有对age声明,但是返回值却是undefined, 所以我们要对我们的变量进行初始化,这样当使用typeof 检测变量时候,返回undefined就说明该变量没有声明,而不是声明了没有初始化

null 类型

null也是js中的一个特殊值,null表示一个空对象的指针,所以用typeof 检测返回object的原因。null也是一个假值,undefined是由null派生出来的,所有表面是相等的 null == undefined,但是null的用法和undefined不一样,如果我们要对一个变量进行对象赋值的时候,通常会先初始化一个null值,来表示这个变量将储存对象

boolean 类型

boolean是布尔值,有两个值true和false,区分大小写,所有True和Flase并不是布尔值。还可以显式将数据转换成boolean, 可以调用Boolean()函数,下面列举了不同数据类型转换boolean的规则

数据类型转换true转换false
Booleantruefalse
String非空字符串"" (空字符串)
Number非零数值(包括无穷值)NaN, 0
Object任意对象null
Undefined不存在undefined

Boolean()是显式转换,还有隐式转换,请看下面:

let message;
if(message) {}
// 在if语句这样写,message就会被隐式转换成Boolean类型来判断
复制代码

Number 类型

number类型是使用IEEE 754 格式来表示整数和浮点数的,长度是64位,内存占8 Byte。

1. 整数可以用十进制,八进制和十六进制来表示

let a = 10  // 十进制 10
let b = 070 // 八进制 56
let c = 0xA // 十六制 10
复制代码

2. 浮点数

let a = 1.1
let b = 0.1
let c = .1 // 不推荐

// 也可以用科学记数法来表示
let floatNum = 3.125e7; // 等于 31250000
复制代码

3. 浮点数的计算可能会带来精度的丢失

例如:0.1 + 0.2 等于  0.300 000 000 000 000 04
但是 0.5 + 0.5 就不会有这样的事情
复制代码

4. 数值的范围

// 最大值
Number.MAX_VALUE
1.7976931348623157e+308
// 最小值
Number.MIN_VALUE
5e-324

// 超出范围会转换成无穷值 Infinity, 可带正负符号
复制代码

5. NaN

NaN 是一个特殊值, 表示不是一个数字

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

复制代码

js 提过了一个isNaN()函数, isNaN()会把传入的参数尝试转换成数值,如果可以转换成数值就返回false, 如果不能就返回true

console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false,10 是数值
console.log(isNaN("10")); // false,可以转换为数值 10
console.log(isNaN("blue")); // true,不可以转换为数值
console.log(isNaN(true)); // false,可以转换为数值 1
复制代码

6. 数值转换规则

js 提供了一个显式转换数值的函数 Number(), 转换规则如下:

  • 数值,直接返回
  • 布尔值, true 返回
  • null, 返回0
  • undefined, 返回NaN
  • 字符串
    • 字符串中只包含数值字符,包括数值字符前面的加号和减号(正负符号),将会以转换一个十进制数值返回,并且会会忽略数值符号前置的0
    Number('123') // 123
    Number('-123') // 123
    Number('-00001') // -1
    复制代码
    • 字符串中只包含有效的浮点数型的数值字符,返回浮点数的数值,同样也是忽略前置0,如果小数点后的数值都是0,则也会忽略
    Number('1.1') // 1.1
    Number('123.0000') // 123
    Number('123.001') // 123.001
    复制代码
    • 字符串只包含有效的十六进制字符串,则会转换成该十六进制相对应的十进制数值
    Number('0xA') // 10
    复制代码
    • 字符串只是空字符串,则返回0
    • 字符串中包含了除上述字符串以外的字符串,则都返回NaN
  • 对象,先调用valueOf()方法,然后依照上述方法进行转换,如果转换结果是NaN,那么就调用toString(), 再依照上述方法进行转换
// 1. 对象{}
Number({}) // NaN
var a = {}
a.valueOf() // {} 还是对象本身
a.toString() // "[object Object]"   
// 所以返回NaN

// 2. 数组 []
Number([]) // 0
var a = []
a.valueOf() // [] 本身
a.toString() // "" (空字符串)
// 所以返回0
复制代码

7. parseInt()

parseInt(string, radix) 解析一个字符串并返回指定基数的十进制整数, radix 是2-36之间的整数,表示被解析字符串的基数。

通常用来将字符串转换成整数,该函数接受两个参数,一个是要转换的数,二是转换成什么样的进制数。 规则如下:

  • 如果第一个字符不是数值或者+、-符号,则直接返回NaN
  • 如果第一个字符是数值或者+、-符号,则继续检索下一个字符,直到字符串末尾或者碰到非数值字符
  • 第二个参数是转换成相应的进制数,有效的是2~36位,默认十进制数
  • 如果第一个字符是数值字符,parseInt()也会自动识别
parseInt('123bbb') // 123
parseInt('12.1') // 12  因为小数点不是有效的数值字符

let num1 = parseInt("10", 2); // 2,按二进制解析
let num2 = parseInt("10", 8); // 8,按八进制解析
let num3 = parseInt("10", 10); // 10,按十进制解析
let num4 = parseInt("10", 16); // 16,按十六进制解析

let num3 = parseInt("0xA"); // 10,解释为十六进制整数
let num4 = parseInt(22.5); // 22
let num5 = parseInt("70"); // 70,解释为十进制值
let num6 = parseInt("0xf"); // 15,解释为十六进制整数
复制代码

8. parseFloat()

parseFloat和parseInt功能类似,区别在于(1)第一次出现的小数点是有效的,第二个出现的小数点是无效的,(2)忽略前置0

let num1 = parseFloat("1234blue"); // 1234,按整数解析
let num2 = parseFloat("0xA"); // 0
let num3 = parseFloat("22.5"); // 22.5
let num4 = parseFloat("22.34.5"); // 22.34
let num5 = parseFloat("0908.5"); // 908.5
let num6 = parseFloat("3.125e7"); // 31250000
复制代码

String 类型

一般情况下有三种方式定义变量是字符串

let name = "abc" // 双引号
let name1 = 'abc' // 单引号
let name2 = `abc` // 模版字面量
复制代码

1. 字符字面量

字符字面量含义
\n换行
\t制表
\b退格
\r回车
\f换页
\反斜杠(\)
'单引号
"双引号
`反引号
\xnn以十六进制编码 nn 表示的字符(其中 n 是十六进制数字 0~F),例如 \x41 等于 "A"
\unnnn以十六进制编码 nnnn 表示的 Unicode 字符(其中 n 是十六进制数字 0~F),例如 \u03a3 等于希腊字符 "Σ"

2. 特点

js中字符串一点创建了就不能修改,要修改某个字符串变量的值,就必须销毁原来的字符串,将包含新值的新的字符串保存到该变量

3. 转换为字符串

  1. 使用toString(), 默认情况下转换成十进制的字符串,可以自定义有效基数的字符串
let num = 10;
num.toString() // 10

// 传递参数
num.toString(2) // '1010'
num.toString(8) // '12'
num.toString(16) // 'a'
复制代码
  1. 调用String() 函数,规则如下
  • 如果有toString()方法,就调用该方法(不传参)
  • 如果是null, 返回"null"
  • 如果是undefined, 返回"undefined"
  1. 使用一元操作符+
let str = 10 + '' + 123 // "10123"
复制代码

4. 模版字符串

ES6新增语法,使用反引号引起来的字符串,并且内部可以使用插值符号进行变量引用。任何js表达式都可以作为插入值

let name = `h`
let name1 = `${name}i` // hi
let name2 = `${name === 'h' ? 'x': 'y'}i`

// 所有的插入的值都会使用toString()方法来转换成字符串
let obj = {
    toString(){
        return 1
    }
}

let name = `${obj}`
console.log(name) // 1
复制代码

Symbol 类型

Symbol是符号,ES6新增的数据类型,符号是原始数据类型,符号实例是唯一的,不可改变,符号的用途是保证对象属性的唯一性,避免对象属性冲突,因为是原始数据,所有typeof 操作符返回的结果也是"symbol"

let s = Symbol()
console.log(typeof s) // "symbol"

let obj = {
    [s]: 'str'
}
console.log(obj[s]) // 'str'
复制代码

Symbol有很多种用法,后面会单独来讲解

Object 类型

js 中对象就是一组数据和功能的集合,可以给对象添加属性和方法。

let obj = {
    name: 'hi',
    getName: function(){
        return this.name
    }
}
复制代码

数据转换

显式转换

String(), Number(), parseInt(), parseFloat(), Boolean()

String()

转换规则:

  • 基本数据类型
    • 如果有toString()方法,则调用toString()返回数据
    • 如果是null, 返回"null"
    • 如果是undefined, 返回"undefined"
  • 引用类型
    • 先调用toString()方法,如果返回的是基本数据类型,则使用上述基本类型规则转换
    • 如果返回的不是基本数据类型,则调用valueOf() 方法,如果返回的是基本数据类型,则使用上述基本类型规则转换
    • 如果返回的不是,则抛出错误

Number()

转换规则:

  • 如果是布尔值true和false, 则true返回1,false返回0
  • 如果是数值,则直接返回
  • 如果是null, 则返回0
  • 如果是undefined, 则返回NaN
  • 如果是字符串
    • 如果字符串中包含数值字符,包括+、- 符号,则转换成十进制数
    • 如果字符串中包含浮点数,则转换成相应的浮点数
    • 如果字符串包含有效的十六进制格式如 "0xf" ,则会转换为与该十六进制值对应的十进制整数值。
    • 如果字符串是空字符串,则返回0
    • 如果字符串中包含除了上述以外的字符,则返回NaN
  • 如果是对象,先调用valueOf方法,并按照上述的规则转换返回的值,如果转换结果为NaN,则调用toString()方法,再按照转换字符串的规则转换。

Boolean()

转换规则:

  • 如果是布尔值true , 则返回true
  • 如果是布尔值false , 则返回false
  • 如果是非空字符串,则返回true
  • 如果是空字符串,则返回false
  • 如果是非零数值,则返回true
  • 如果是0, NaN, 则返回false
  • 如果是对象,则返回true
  • 如果是null, 则返回false
  • 如果是undefined, 则返回false

隐式转换(通常称为强制类型转换)

1. 只判断变量

隐式使用Boolean()转换规则

var name = ''
if(name) {
  // 不会执行
}
var age = name ? '1' : '2'
复制代码

2. 关系运算符

分为两种情况,一种是关系操作符,一个值相等操作符

2.1 关系操作符(>、<、>=、<=)

规则如下:

  • 如果两边都是数值,则进行数值比较
  • 如果两个都是字符串,则逐个比较对应的字符串编码
  • 如果有一个是数值,则将另一个转换成数值,再进行比较
  • 如果有一个是对象,则调用valueOf()方法,取的的结果在根据上述规则比较,如果没有valueOf()方法,则调用toString()方法,取的的结果在根据上述规则比较
  • 如果有一个是布尔值,则将其转换成数值进行比较

2.2 相等操作符

规则如下:

  • 如果有一个是布尔值,则将其转换成数值进行比较,true为1, false为0
  • 如果有一个是字符串,另一个是数值,则将字符串尝试转换成数值,在进行比较
  • 如果一个是对象,另一个不是,则调用对象上的valueOf()方法获取原始值,再根据上述规则比较,如果valueOf 获取到的值不是基本数据类型,则调用toString()方法获取值,再根据上述规则比较
  • null 和 undefined 值相等,不进行任何数据转换
  • 如果有一个是NaN,则直接返回false, 如果另一个也是NaN,也直接返回false, 根据规则,NaN和任何数据都不相等,包括自身
  • 如果两个都是引用类型对象,则比较两个地址是否指向同一个对象,如果是,则返回true, 反之返回false

检测方法

1. typeof

console.log(typeof "helloworld")    ------------------>"string"     
console.log(typeof 123)             ------------------>"number"
console.log(typeof [1,2,3])         ------------------>"object"
console.log(typeof new Function())  ------------------>"function"
console.log(typeof new Date())      ------------------>"object"
console.log(typeof new RegExp())    ------------------>"object"
console.log(typeof Symbol())        ------------------>"symbol"
console.log(typeof true)            ------------------>"true"
console.log(typeof null)            ------------------>"object"
console.log(typeof undefined)       ------------------>"undefined"
console.log(typeof 'undefined')     ------------------>"string"
复制代码

2. instanceof

[1,2,3] instanceof Array                -------->true
new Date() instanceof Date              -------->true
new Function() instanceof Function      -------->true
new Function() instanceof function      -------->false
null instanceof Object                  -------->false
复制代码

3. 对象原型链判断方法: Object.prototype.toString.call()

console.log(Object.prototype.toString.call("123"))           -------->[object String]
 console.log(Object.prototype.toString.call(123))             -------->[object Number]
 console.log(Object.prototype.toString.call(true))            -------->[object Boolean]
 console.log(Object.prototype.toString.call([1, 2, 3]))       -------->[object Array]
 console.log(Object.prototype.toString.call(null))            -------->[object Null]
 console.log(Object.prototype.toString.call(undefined))       -------->[object Undefined]
 console.log(Object.prototype.toString.call({name: 'Hello'})) -------->[object Object]
 console.log(Object.prototype.toString.call(function () {}))  -------->[object Function]
 console.log(Object.prototype.toString.call(new Date()))      -------->[object Date]
 console.log(Object.prototype.toString.call(/\d/))            -------->[object RegExp]
 console.log(Object.prototype.toString.call(Symbol()))        -------->[object Symbol]
复制代码
文章分类
前端
文章标签