js数据类型的判断与转换

本文最后更新于:2022年5月31日 上午

ECAMScript 中不能自定义数据类型,只能为下列 7 种

简单数据类型(原始类型)

  • String

  • Number

    • NaN
      typeof NaN === 'number'
      唯一一个自相反的值
      NaN !== NaN
  • Boolean

    • 在条件判断时,除了 undefinednullfalseNaN''0-0,其他所有值都转为 true,包括所有对象。
    • 布尔值与其他类型比较都会转为数字
  • null

    • typeof null = object,null 表示一个空对象指针
    • null 必须手动设置,常用于作为参数传入,说明该参数不是对象
    • 设置为 null 的变量或者对象会被内存收集器回收
    • null 转为数字类型值为 0
  • undefined

    • 调用一个值而它本身没有赋值
    • undefined == null
    • undefined 转为数字类型为 NaN
  • Symbol[ES6 新增]

    • 表示独一无二的值

复杂类型

Object

  • 引用类型的值是指向保存在堆中的对象的指针
  • 使用时要先从栈中读取内存地址,再沿着指针找到堆中的对象
  • Object
  • Array
    • 数组的每一项可以用来保存任何类型的数据
  • Function
    • 每个函数都是 Function 的实例

类型判断

typeOf

  • 对未声明的变量,只有对它调用typeof不报错,return undefined
  • 特殊的几个
typeof undefined; // 'undefined'
typeof Symbol(); // 'symbol'
typeof null; // 'object'
typeof NaN; // number

isNaN

console.log(isNaN(NaN));    //true
console.log(isNaN(10));     //false
console.log(isNaN("10"));   //false
console.log(isNaN("blue")); //true
console.log(isNaN(true));   //false

instanceof

instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,但它不能检测nullundefined

[] instanceof Array // true
{} instanceof Object // true
new Date() instanceof Date // true
new RegExp() instanceof RegExp // true
null instanceof null // error
undefined instanceof undefined // error

constructor

const arr = [];
const obj = {};
console.log(arr.constructor); // [Function: Array]
console.log(obj.constructor); // [Function: Object]

Object.prototype.toString.call()

Object.prototype.toString.call(); // [object Undefined]
Object.prototype.toString.call(""); // [object String]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(new Function()); // [object Function]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(new RegExp()); // [object RegExp]
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call({}); // [object Object]
Object.prototype.toString.call(new Error()); // [object Error]

类型转换

转为数值

Number() 适用于任何类型

let num1 = Number("Hello world!");  // NaN
let num2 = Number(""); // 0
let num3 = Number("000011"); // 11
let num4 = Number(true); // 1

parseInt(string, radix) 主要用于字符串

  • 如果第一个字符不是数值字符、加号或减号,立即返回NaN
    ,这意味着空字符串也会返回 NaN
    let num2 = parseInt("");  // NaN
    let num3 = parseInt("0xA"); // 10
    let num4 = parseInt(22.5); //22
    let num5 = parseInt("abc"); // NaN
    let num6 = parseInt("123abc") // 123
    
    [1,2,3].map(parseInt)
    // [1, NaN, NaN]
    // map调用的回调会默认传入三个参数【当前元素,当前索引,当前数组】
    // parseInt(1,0) => radix为undefined或者0时,相当于radix10
    // parseInt(2,1) => 1进制的2??NaN
    // parseInt(3,2) => 2进制的3?? NaN

    parseFloat(string) 主要用于字符串

  • 只解析十进制
  • 忽略2次出现的小数点
    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

转为字符串

toString()

null和undefined没有toString()方法

String()

  • 优先调用toString()
  • null 转换为 ‘null’
  • undefined 转换为 ‘undefined’

转为布尔值

  • Boolean()
    //除了以下六个转为 false 其他全部都为 true
    undefined
    null
    0
    -0
    NaN
    ''

隐式转换

在 js 中,当运算符在运算时,如果两边数据不统一,CPU 就无法计算,这时我们编译器会自动将运算符两边的数据做一个数据类型转换,转成一样的数据类型再计算.这种无需程序员手动转换,而由编译器自动转换的方式就称为隐式转换

隐式转换规则

  • 转成 string 类型: +(字符串连接符)
  • 转成 number 类型:++/--(自增自减运算符) + - * / %(算术运算符) > < >= <= == != === !=== (关系运算符)
  • 转成 boolean 类型:!(逻辑非运算符)

字符串连接符与算术运算符

+左右有字符串则转为字符串拼接,否则转为数字计算

//+是字符串连接符: String(1) + 'true' = '1true'
console.log(1 + "true"); //1true
//+是算术运算符 : 1 + Number(true) = 1 + 1 = 2
console.log(1 + true); //2
// +是算术运算符 : 1 + Number(undefined) = 1 + NaN = NaN
console.log(1 + undefined); //   NaN
// +是算术运算符 : 1 + Number(null) = 1 + 0 = 1
console.log(1 + null); //1
//

关系运算符

会把其他数据类型转换成 number 之后再比较关系

此时并不是按照 Number()的形式转成数字,而是按照字符串对应的 unicode 编码来转成数字

console.log("2" > "10"); //true     '2'.charCodeAt() > '10'.charCodeAt() = 50 > 49 = true
console.log("2".charCodeAt()); //数字50
console.log("10".charCodeAt()); //数字49(默认返回第一个字符的编码,如果想要查询第二个字符可以传参下标)
//多个字符从左往右依次比较
console.log("abc" > "b"); //false     先比较'a' 和 'b', 'a' 与 'b'不等,则直接得出结果
console.log("abc" > "aad"); //true     先比较'a'和'a',两者相等,继续比较第二个字符 'b' 与 'a' ,得出结果
console.log("a".charCodeAt()); //数字97
console.log("b".charCodeAt()); //数字98
//2.3 特殊情况(无视规则):如果数据类型是undefined与null,,得出固定的结果
console.log(undefined == undefined); //true
console.log(undefined == null); //true
console.log(null == null); //true
//2.4 特殊情况(无视规则):NaN与任何数据比较都是NaN
console.log(NaN == NaN); //false

复杂数据类型的隐式转换

  1. 先使用valueOf()方法获取其原始值,如果原始值不是number类型,则使用 toString()方法转成string
  2. 再将 string 转成 number 运算
[1, 2] == "1,2"; //true     先将左边数组转成string,然后右边也是string则转成unicode编码运算
[1, 2].valueOf(); // [1,2]
[1, 2].toString(); // '1,2'
var a = {};
a == "[object Object]"; //true
a.valueOf().toString(); //[object Object]

逻辑非隐式转换与关系运算符

如果两个引用类型比较,会比较内存地址,注意要是其中有逻辑非运算符,非运算优先级会大于比较操作

  • 空数组的 toString()方法会得到空字符串''
  • 空对象的 toString()方法会得到字符串[object Object]
console.log(Boolean([])); // true
console.log(Boolean(![])); // false
// Boolean除了0,-0,null,undefined,false,''都转为true


//大坑
console.log([] == 0); //true []转数字为0
console.log(![] == 0); //true  
// 这里有逻辑非运算符,会先转Boolean,![]转布尔false,转数字为0


//神坑
console.log([] == ![]); //true
// ![]转布尔false=>0,0和[]比较,[]转数字为0
console.log([] == []); //false // 内存地址不同


//史诗级坑
console.log({} == !{}); //false
// {}最终转number为NaN,右边转数字为0
console.log({} == {}); //false // 内存地址不同

值的比较

es6 新增Object.is()判断

修复了转布尔值的bug

Object.is(null, null); // true
Object.is(undefined, undefined); // true
Object.is(0, -0); // false
Object.is(0, +0); // true
Object.is(-0, -0); // true
Object.is(NaN, 0); // false
Object.is(NaN, 0 / 0); // true
function _Object.is(x,y){
  if(!Object.is){
    if(x===y){
      return x!==0 || 1/x === 1/y
    }else{
      return x!==x && y!== y
    }
  }
}

hack技巧

  • 转string
    123+'' // ‘123’
  • 转number
    +123 // 123
  • 位运算
    • 向下取整
      ~~1.9 = 1
      1.9 >> 0 = 1
    • Math.floor(N/2)
      124.9 >> 1 = 62

js数据类型的判断与转换
http://yoursite.com/2022/02/24/js中数据类型转换/
作者
tatekii
发布于
2022年2月24日
许可协议