Brendan Eich在设计JavaScript的时候是没有加入类型系统的,所以JavaScript是一门动态语言,类型是进入执行上下文的时候可能才去确定,这就可能出现一个JavaScript变量在上一瞬间是String,下一瞬间就是Number了,在这个过程中,JavaScript变量进行了类型的转换。使用Javascript进行相等运算时,我们可能会用”==”,”===”和Object.is来进行比较两个值是否相等。
- 使用===时,恒等,严格比较运算符,不做类型转换,类型不同就是不等,NaN与NaN不相等。
- 使用Object.is()时,其行为与”===”基本一致,不过有两处不同:
- +0不等于-0。
- NaN等于自身。
- 使用==时,不同类型的值也可以被看作相等。这可能会让很多的JavaScript困开发者感到困惑。使用”==”时,不同的数据类型都发生了哪些类型变化过程呢?
Javascript数据类型
在讲到类型转换之前,我们把JavaScript的数据类型再进行梳理一遍,最新的 ECMAScript标准定义了 8种原始数据类型,8种原始数据类型又分为7种基本数据类型和1种引用类型。
- 基本类型
Undefined、 Null、 String、 Number、 Boolean、Symbol和BigInt这7种数据类型都是属于基本类型,基本类型都是不可变的,不可变是指基本类型本身和一个赋值为基本类型的变量的区别。变量会被赋予一个新值,而原值不能像数组、对象以及函数那样被改变。
- 引用类型:Object(对象),包括了数组(Array)、函数(Function)、正则(RegExp)和日期(Date)。
不同类型的值使用“==”运算符后的转换规则
类型(x) | 类型(y) | 类型(y) |
---|---|---|
null | undefined | true |
undefined | null | true |
数字 | 字符串 | x == toNumber(y) |
字符串 | 数字 | y== toNumber(x) |
布尔值 | 任何类型 | toNumber(x) == y |
任何类型 | 布尔值 | x == toNumber(y) |
字符串或数字 | 对象 | x == toPrimitive(y) |
对象 | 字符串或数字 | toPrimitive(x)== y |
toNumber对不同类型值的转换规则:
- undefined: NaN
- null: +0
- Boolean:true:1,flase: 0
- 数值返回对应的数值
toPrimitive对于基本类型不做转换,输出等于输入,对于对象,如果对象的valueOf方法的结果是原始值,则返回原始值,如果对象的toString方法返回的是原始值,则返回这个值,其他情况则返回一个错误。
toNumber和toPrimitive属于内部的方法ecma对于这两个方法的描述。
例子:
1 console.log('juejin' ? true : false); // true
2 console.log('juejin' == true); // false
复制代码
第一行的代码执行结果是true,第二行代码的执行结果是false,为什么会出现这样的结果呢?
- 按照上面给出的规则,true会被toNumber方法转换成1,即变成了’juejin’ == 1,
- ‘juejin’有被toNumber方法转换成NaN,即最后的表达式变成了NaN == 1,所以返回false。
按照上面的方法,那’juejin’ == false是不是会返回true呢?答案还是false,为什么呢?
- 按照上面给出的规则,false会被toNumber方法转换成0,即变成了’juejin’ == 0,
- ‘juejin’有被toNumber方法转换成NaN,即最后的表达式变成了NaN == 0,所以返回false。
扩展-数据类型判断
- typeof,基本数据类型,除了null之外,可以通过typeof操作符进行类型的判断:
- undefined:typeof instance === “undefined”
- Boolean:typeof instance === “boolean”
- Number:typeof instance === “number”
- String:typeof instance === “string
- BigInt:typeof instance === “bigint”
- Symbol :typeof instance === “symbol”
null也是基本类型, typeof null === “object”,这是JS语言本身的一个bug。不同的对象在底层都表示为二进制,在js中二进制前三位都为0的话会被判断为object类型,null的二进制表示全是0,自然前三位也是0,所以执行typeof时返回”object”。
另外,引用类型里面的function也可以使用typeof判断:
- Function :typeof instance === “function”
其余的引用类型一律返回”object”。
- instanceof
instanceof运算符用来检测constructor.prototype是否存在于某个实例对象的原型链上。
function Class1() {
console.log('Class1');
}
function Class2() {
console.log('Class2');
}
const obj1 = new Class1();
obj1 instanceof Class1; // true
obj1 instanceof Class2; // false
Class1.prototype = {};
obj1 instanceof Class1; // false
复制代码
除此之外,Object.prototype.toString.call和construct也可以进行数据类型的判断。