七种语言类型:Undefined,Null,Number, Boolean, String, Symbol, Object
类型转换
类型判断
数据类型
- 基本类型:直接存储在栈(stack)中的数据,值类型
- 引用数据类型:存储的是该对象在栈中的引用,真实的数据存放在堆中,引用类型
基本类型
Undefined、Null
Undefined 类型表示未定义,只有一个值 undefined
全局变量 undefined,类型是 Undefined,所以 undefined 是一个变量而非关键字(局部环境可以被赋值),可以使用 void(0)来获取 undefined 的值。
Null 表示定义了但为空,值 null,是 js 的关键字Boolean
真/假 true/falseString
最大长度 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
12var 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 | Symbol.prototype.hello = () => console.log('hello'); |
为什么给对象添加的方法能用在基本类型上?
因为点(.)运算符提供装箱操作,会根据基础类型构造一个临时对象,使我们可以在基础类型上调用对应对象的方法。
参数传递方式
- 值传递,会将一个值类型的数值副本传到函数内部,函数内部不影响函数外部传递的参数变量
引用类型,会将引用类型的地址值复制给传入函数的参数,函数内部修改会影响外部的引用对象。
1
2
3
4
5
6
7
8
9
10
11
12function 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}
数据类型判断
typeof
返回一个表示数据类型的字符串number
、boolean
、string
、symbol
、object
、undefined
、function
1
2
3
4
5
6
7
8
9
10
11console.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 无效instanceof
A instanceof B:判断 A 是否是 B 的实例。返回值是 true/false。
用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,但是不能检测 null 和 undefined1
2
3
4
5
6console.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) //报错constructor
与 instanceof 相似,但是 constructor 检测 Object 与 instanceof 不一样,还可以处理基本数据类型的检测。但是在把类的原型进行重写的过程中,可能把之前的 constructor 覆盖,检测结果不准确。1
obj.constructor == Object//obj的构造函数是不是Object
Object.prototype.toString.call()
是准确最常用的方式。1
2
3
4
5
6
7
8
9
10console.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]Array.isArray()
判断是不是数组
类型转换
转化为字符串类型
方法:.toString()
,不可以转换null
和undefined
String()
+''
1
2
3
4
5null => '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
8null => 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 | var symbolObject = (function(){return this;}).call(Symbol('a')); |
装箱机制会产生临时对象,性能要求高的场景应避免使用。
内置函数 Object 也可以实现以上功能
1 | var symbolObject = Object(Symbol('a')); |
对象私有 Class 属性
1 | var symbolObject = Object(Symbol('a')); |
这种识别具体对象类型的方法比 instanceof 更加准确
但是 call 会产生装箱操作,所有需要先使用 typeof 排除基本类型,再进行对象类型的判断
拆箱转换
对象类型到基本类型的转换,会调用内置的[ToPrimitive]
函数。
对象到 String 和 Number 的转换都遵循“先拆箱再转换”,先把对象变为基本类型,再从基本类型转为对象的 String 或者 Number
拆箱转换会尝试调用 valueOf 和 toString 来获得拆箱后基本类型。如果 valueOf 和 toString 都不存在,或者没有返回基本类型,会产生 TypeError
1 | var o = { |
ES6 之后可以使用显示指定@@toPrimitive Symbol 覆盖原有行为
1 | var o = { |
验证是否为有效数字
1 | const isValidNumber=n=>typeof n==='number'&&!isNaN(n)&&isFinite(n) |
两个日期之前相隔天数
1 | const getDayDiff = (date1, date2) => ((date2 - date1) / (1000 * 3600 * 24)); |