1. typeof
对于原始类型,除了 null 都可以调用typeof显示正确的类型。
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
对于引用数据类型,除了函数之外,都会显示"object"。
typeof [] // 'object'
typeof null // object
typeof console.log // 'function'
注意:null 不是对象虽然 typeof null
会输出 object,但是这只是 JS 存在的一个悠久 Bug。在 JS 的最初版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象然而 null 表示为全零,所以将它错误的判断为 object 。
2.instanceof
采用typeof判断对象数据类型是不合适的,采用instanceof会更好,instanceof的原理是基于原型链的查询,只要处于原型链中,判断永远为true。
const Person = function() {}
const p1 = new Person()
p1 instanceof Person // true
var str1 = 'hello world'
str1 instanceof String // false
var str2 = new String('hello world')
str2 instanceof String // true
var a=null
a instanceof Object // false
对于原型链的理解,参考博文:https://juejin.im/post/5bb7183bf265da0a9e5322b1
JS原型链与instanceof底层原理:https://www.jianshu.com/p/6c99d3678283
instanceof能否判断基本数据类型?
能。比如下面这种方式:
class PrimitiveNumber {
static [Symbol.hasInstance](x) {
return typeof x === 'number'
}
}
console.log(111 instanceof PrimitiveNumber) // true
如果你不知道Symbol,可以看看MDN上关于hasInstance的解释。
其实就是自定义instanceof行为的一种方式,这里将原有的instanceof方法重定义,换成了typeof,因此能够判断基本数据类型。
3. 手动实现instanceof的功能
核心: 原型链的向上查找。
function myInstanceof(left, right) {
//基本数据类型直接返回false
if(typeof left !== 'object' || left === null) return false;
//getProtypeOf是Object对象自带的一个方法,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(left);
while(true) {
//查找到尽头,还没找到
if(proto == null) return false;
//找到相同的原型对象
if(proto == right.prototype) return true;
proto = Object.getPrototypeof(proto);
}
}
测试:
console.log(myInstanceof("111", String)); //false
console.log(myInstanceof(new String("111"), String));//true
4.Object.is
语法:Object.is(value1, value2)
如果下列任何一项成立,则两个值相同:
- 两个值都是 undefined
- 两个值都是 null
- 两个值都是 true 或者都是 false
- 两个值是由相同个数的字符按照相同的顺序组成的字符串
- 两个值指向同一个对象
- 两个值都是数字并且
- 都是正零 +0
- 都是负零 -0
- 都是 NaN
- 都是除零和 NaN 外的其它同一个数字
这种相等性判断逻辑和传统的 ==
运算不同,==
运算符会对它两边的操作数做隐式类型转换(如果它们类型不同),然后才进行相等性比较,(所以才会有类似 “” == false 等于 true 的现象),但 Object.is 不会做这种类型转换。
这与 ===
运算符的判定方式也不一样。===
运算符(和== 运算符)将数字值 -0 和 +0 视为相等,并认为 Number.NaN 不等于 NaN。
Object.is('foo', 'foo'); // true
Object.is(window, window); // true
Object.is('foo', 'bar'); // false
Object.is([], []); // false
Object.is(NaN,NaN); //true
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false
Object.is(null, null); // true
// 特例
Object.is(0, -0); // false
Object.is(0, +0); // true
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true
其源码如下:
function is(x, y) {
if (x === y) {
//运行到1/x === 1/y的时候x和y都为0,但是1/+0 = +Infinity,
//1/-0 = -Infinity, 是不一样的
return x !== 0 || y !== 0 || 1 / x === 1 / y;
} else {
//NaN===NaN是false,这是不对的,我们在这里做一个拦截,x !== x,那么一定是 NaN, y 同理
//两个都是NaN的时候返回true
return x !== x && y !== y;
}
}
5. == 与 ===
双等号==:
(1)如果两个值类型相同,再进行三个等号(===)的比较
(2)如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换再比较:
参数类型1 | 参数类型2 | 强制转换 |
---|---|---|
null | undefined | 不转换,总是返回true |
null或undefined | 其它任何非null或undefined的类型 | 不转换,总是返回false |
原始类型:string、number或boolean | Date对象 | 将原始类型转换成数字;将Date对象转换为原始类型。(优先尝试toString方法,再尝试valueOf方法) |
原始类型:string、number或boolean | 非Data对象 | 将原始类型转换成数字;将非Date对象转换为原始类型。(优先尝试toString方法,再尝试valueOf方法) |
原始类型:string、number或boolean | 原始类型:string、number或boolean | 将原始类型转换成数字 |
原始类型:string、number或boolean | Object | 将Object转换成字符串;将原始类型转换成数字 |
原文链接:https://blog.csdn.net/searchin_r/article/details/83047870
三等号===:
(1)如果类型不同,就一定不相等
(2)如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。(判断一个值是否是NaN,只能使用isNaN( ) 来判断)
(3)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。
(4)如果两个值都是true,或是false,那么相等
(5)如果两个值都引用同一个对象或是函数,那么相等,否则不相等
(6)如果两个值都是null,或是undefined,那么相等
博文参考:https://sanyuan0704.github.io/frontend_daily_question/week03/014.html