Fork me on GitHub

JS-语言类型

七种语言类型:Undefined,Null,Number, Boolean, String, Symbol, Object
类型转换
类型判断

数据类型

  • 基本类型:直接存储在栈(stack)中的数据,值类型
  • 引用数据类型:存储的是该对象在栈中的引用,真实的数据存放在堆中,引用类型

基本类型

  • Undefined、Null
    Undefined 类型表示未定义,只有一个值 undefined
    全局变量 undefined,类型是 Undefined,所以 undefined 是一个变量而非关键字(局部环境可以被赋值),可以使用 void(0)来获取 undefined 的值。
    Null 表示定义了但为空,值 null,是 js 的关键字

  • Boolean
    真/假 true/false

  • String
    最大长度 UTF16 编码 2^53-1,

  • Number
    特例

    • NaN
    • Infinity, 无穷大,除以+0
    • -Infinity,负无穷大,除以-0
      检测+0 和-0 的方法,检测 1/x 是 Infinity 还是 -Infinity
      差值比较
      Math.abs(0.1+0.2-0.3) <= Number.EPSILON
      左右两边的差,绝对值小于最小精度,就认为两者相等
  • BigInt
    JS 所有数字都保存成 64 位浮点数,-(2^53-1)到(2^53-1),大于此范围的数无法使用 Number 表示。
    BigInt 用来表示整数没有位数限制。
    普通数字+n
    BigInt(num)把普通的类型转为 BigInt

引用数据类型

  • Symbol
    创建使用全局 Symbol 函数
    var mySymbol = Symbol(‘my symbol’)
    括号里面是 Symbol 的描述,即使描述相同,两个 Symbol 值也不会相等

    为对象定义了 Symbol.iterator 属性,就可以使用 for of 遍历

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var o=new Object
    o[Symbol.iterator] = function () {
    var v = 0;
    return {
    next: function(){
    return { value:v++, done: v>10 }
    }
    }
    }
    for( var v of o){
    console.log(v) // 0 2 3 4 5 6 7 8 9
    }
  • Object
    构造器:Number,String,Boolean,Symbol
    使用 new+构造器,生成一个对象,
    直接调用表示强制类型转换,
    其中 Symbol 不能直接与 new 搭配。

在构造器原型上添加方法,基本类型都可以调用

1
2
3
4
Symbol.prototype.hello = () => console.log('hello');
var a = Symbol('a');
console.log(typeof a) //symbol
a.hello() //hello

为什么给对象添加的方法能用在基本类型上?
因为点(.)运算符提供装箱操作,会根据基础类型构造一个临时对象,使我们可以在基础类型上调用对应对象的方法。

参数传递方式

  • 值传递,会将一个值类型的数值副本传到函数内部,函数内部不影响函数外部传递的参数变量
  • 引用类型,会将引用类型的地址值复制给传入函数的参数,函数内部修改会影响外部的引用对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function f(a, b) {
    console.log(1, a, b) // 11 {value: 222}
    a = 10;
    b.value = 100
    console.log(2, a, b) // 10 {value: 100}
    }
    let a = 11,
    b = {
    value: 222
    };
    f(a, b)
    console.log(3, a, b) // 11 {value: 100}

数据类型判断

  1. typeof
    返回一个表示数据类型的字符串
    numberbooleanstringsymbolobjectundefinedfunction

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    console.log(typeof 1) //number
    console.log(typeof true) //boolean
    console.log(typeof '') //string
    console.log(typeof Symbol()) //symbol
    console.log(typeof undefined) //undefined
    console.log(typeof new Function()) //function
    console.log(typeof {}) //object 无效
    console.log(typeof []) //object 无效
    console.log(typeof null) //object 无效
    console.log(typeof new Date()) //object 无效
    console.log(typeof new RegExp()) //object 无效
  2. instanceof
    A instanceof B:判断 A 是否是 B 的实例。返回值是 true/false。
    用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,但是不能检测 null 和 undefined

    1
    2
    3
    4
    5
    6
    console.log([] instanceof Array)   //true
    console.log({} instanceof Object) //true
    console.log(new Date() instanceof Date) //true
    console.log(new RegExp() instanceof RegExp) //true
    console.log(null instanceof Null) //报错
    console.log(undefined instanceof undefined) //报错
  3. constructor
    与 instanceof 相似,但是 constructor 检测 Object 与 instanceof 不一样,还可以处理基本数据类型的检测。但是在把类的原型进行重写的过程中,可能把之前的 constructor 覆盖,检测结果不准确。

    1
    obj.constructor == Object//obj的构造函数是不是Object
  4. Object.prototype.toString.call()
    是准确最常用的方式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    console.log(Object.prototype.toString.call(' ')) //[object String]
    console.log(Object.prototype.toString.call(1)) //[object Number]
    console.log(Object.prototype.toString.call(true)) //[object Boolean]
    console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
    console.log(Object.prototype.toString.call(null)) //[object Null]
    console.log(Object.prototype.toString.call(new Function())) //[object Function]
    console.log(Object.prototype.toString.call(new Date())) //[object Date]
    console.log(Object.prototype.toString.call(new RegExp())) //[object RegExp]
    console.log(Object.prototype.toString.call([])) //[object Array]
    console.log(Object.prototype.toString.call(new Error())) //[object Error]
  5. Array.isArray()
    判断是不是数组

类型转换

  • 转化为字符串类型
    方法:

    1. .toString(),不可以转换nullundefined
    2. String()
    3. +''
    1
    2
    3
    4
    5
    null => 'null' //通过2,3方法转换
    undefined => 'undefined' //通过2,3方法转换
    true => 'true'
    false => 'false'
    [1,2,3] => 1,2,3

    对象转换成字符串会调用对象的toString方法,通常得到"[object Object]"

  • 转化为数字
    方法:Number()

    1
    2
    3
    4
    5
    6
    7
    8
    null => 0
    undefined => NaN
    //Boolean
    true => 1
    false => 0
    //function
    ()=>{} => NaN
    function a(){} => NaN

对对象来说,会先检查该值是否有 valueOf 方法,如果有 valueOf 且返回基本类型,则使用该返回值进行类型转换;否则调用 toString 方法进行类型转换(如果此处返回的不是数字,则会调用上面列举的 4 条规则进行类型转换);如果以上规则均不返回数字,则报 TypeError 错误

  • StringToNumber
    parseInt(str,base)
    转换为整数
    从第一位开始转换,遇到非数字停止,如果第一个字符就是非数字直接返回 NaN。
    base:转化的进制,默认 10 进制,如果 str 是以 0x 开头的字符,转换进制默认是 16 进制。

    parseFloat(str)
    按照 10 进制将原字符转换为浮点数
    从第一位开始转换,遇到非数字停止,如果第一个字符就是非数字直接返回 NaN。

  • 转换为布尔值
    undefined,null,false,+0,-0,NaN,''会被转为false,其他的都会被转换为true

装箱转换

把基本类型的转为对应的对象类型
Symbol 对象无法调用 new 方法来进行装箱转换,下面是可以让其实现装箱转换的方法

1
2
3
4
5
var symbolObject = (function(){return this;}).call(Symbol('a'));

typeof symbolObject //object
symbolObject instanceof Symbol //true
symbolObject.constructor == Symbol //true

装箱机制会产生临时对象,性能要求高的场景应避免使用。
内置函数 Object 也可以实现以上功能

1
2
3
4
5
var symbolObject = Object(Symbol('a'));

typeof symbolObject //object
symbolObject instanceof Symbol //true
symbolObject.constructor == Symbol //true

对象私有 Class 属性

1
2
var symbolObject = Object(Symbol('a'));
Object.prototype.toString.call(symbolObject) //[object Symbol]

这种识别具体对象类型的方法比 instanceof 更加准确

但是 call 会产生装箱操作,所有需要先使用 typeof 排除基本类型,再进行对象类型的判断

拆箱转换

对象类型到基本类型的转换,会调用内置的[ToPrimitive] 函数。
对象到 String 和 Number 的转换都遵循“先拆箱再转换”,先把对象变为基本类型,再从基本类型转为对象的 String 或者 Number
拆箱转换会尝试调用 valueOf 和 toString 来获得拆箱后基本类型。如果 valueOf 和 toString 都不存在,或者没有返回基本类型,会产生 TypeError

1
2
3
4
5
6
7
8
var o = {
valueOf : () => {console.log('valueOf'); return {}},
toString : () => {console.log('toString'); return {}}
}
o*2
// valueOf
// toString
// TypeError

ES6 之后可以使用显示指定@@toPrimitive Symbol 覆盖原有行为

1
2
3
4
5
6
7
8
9
10
11
var o = {
valueOf : () => {console.log('valueOf'); return {}},
toString : () => {console.log('toString'); return {}}
}
o[Symbol.toPrimitive] = () => {
console.log('toPrimitive');
return "hello"
}
o + ""
//toPrimitive
//hello

验证是否为有效数字

1
const isValidNumber=n=>typeof n==='number'&&!isNaN(n)&&isFinite(n)

两个日期之前相隔天数

1
const getDayDiff = (date1, date2) => ((date2 - date1) / (1000 * 3600 * 24));
-------------本文结束感谢阅读-------------