数据类型检测的方式有哪些?
(1)typeof
其中数组、对象、null都会被判断为object,其他判断都正确。
typeof不能用来判断null和数组,结果都是Object
(2)instanceof
instanceof可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型。
可以看到,
instanceof只能正确判断引用数据类型,而不能判断基本数据类型
(3)constructor
constructor有两个作用,一是判断数据的类型,二是对象实例通过 constrcutor 对象访问它的构造函数。需要注意,
如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了
(4)Object.prototype.toString.call()
Object.prototype.toString.call() 使用 Object 对象的原型方法 toString 来判断数据类型:
这个基本可以判断所有的数据类型
typeof与instanceof的区别
NaN、isNaN 和 Number.isNaN相关题目
NaN 是什么,用 typeof 会输出什么?
NaN:Not a Number,表示非数字
typeof NaN === 'number' // true
NaN 是一个特殊值,它和自身不相等
isNaN 和 Number.isNaN 函数有什么区别?
NaN
NaN 最特殊的地方就是,我们不能使用相等运算符来判断一个值是否是 NaN
因为 NaN == NaN 和 NaN === NaN 都会返回 false。因此,必须要有一个判断值是否是 NaN 的方法。
NaN更多的是表示不是一个数值的状态,而不是一个数值的状态有很多种情况,所以互不相等。
方法
- 函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true ,会影响 NaN 的判断。
- 函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。
总结
和全局函数 isNaN() 相比,Number.isNaN() 不会自行将参数转换成数字,只有在参数是值为 NaN 的数字时,也就是NaN时,才会返回 true。
Number.isNaN() 方法确定传递的值是否为NaN,并且检查其类型是否为Number
instanceof能否判断基本数据类型?
能。
null是对象吗?为什么?
null不是对象。 虽然 typeof null 会输出 object,但是这只是 JS 存在的一个悠久 Bug。
null 和 undefined 有什么区别?
首先 Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null.
undefined 代表的含义是未定义,null 代表的含义是空对象.
一般变量声明了但还没有定义的时候会返回 undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化。
Object.is与===和==有什么区别?
- ==
双等号判等,会在比较时进行[类型转换]
- 如果操作数都是对象,则仅当两个操作数都引用同一个对象时才返回true。
const obj = {name:"张三", age:20}
const obj2 = obj
console.log({name:"张三", age:20} == obj) //false
console.log(obj2 == obj) //true
- 如果一个操作数是null,另一个操作数为undefined,则也返回true
console.log(null == undefined) //true
- 如果两个操作数是不同的类型,就会在进行比较之前进行类型的转换,将其转换为不同的类型
// 1、当数字和字符串进行比较时,会尝试将字符串转化为数字。
console.log("1221" == 1221) //true
// 2、如果操作类型为布尔值,会将true转换为1,false转化为0。
console.log(true == 1) //true
console.log(false == 0) //true
// 3、如果操作数之一为对象,另一个是数字或者字符串,会尝试使用valueOf()和toString()方法将对象转化为原始值。
console.log(Number(10) == 10)
console.log(Number(10))
- 如果操作数的类型相同
/**
1、String类型仅当两个操作数具有相同顺序的字符才返回true。
2、Number类型,仅当两者具有相同的值时才返回true,+0和-0被视为相同的值。
如果任何一个操作数为NaN,则直接返回false.
**/
console.log(+0 == -0) //true
console.log(NaN == NaN) //false
- ===
比较时不进行隐式类型转化,类型不同则返回false。
// 1、如果操作数的类型不同,则返回false。
console.log("12" === 12) //false
// 2、如果两个操作数都是对象时,只有当他们都指向同一个对象时才返回true.
// 3、如果两个操作数都是null,或者两个操作数都是undefined,返回true.
console.log(null === null) //true
console.log(undefined === undefined) //true
// 4、如果存在NaN,则返回false。
console.log(NaN === NaN) //false
// 5、+0和-0在三等号下是相等的。
console.log(+0 === -0) //true。
补充:
- Object.is()
Object.is()和三等运算符很像,但是仍然存在一些差别,比如说对于NaN,对于+0和-0之间的比较
console.log(Object.is(10, 10)) //true
console.log(Object.is(NaN, NaN)) //true !!
console.log(Object.is({}, {})) // false
console.log(Object.is(12, "12")) //false
console.log(Object.is(true, 1)) //false
console.log(Object.is(false, false)) //true
console.log(Object.is(+0, -0)) //false !!
console.log(Object.is(undefined, null)) //false
满足如下条件的Object.is()的返回值为true.
1.都为undefined
2.都是null
3.都是true或者都是false.
4.都是相同长度的字符串并且相同字符换按照相同的顺序排列。
5.都是相同的对象(同一个引用)
6.都是数字,且大都是+0,或者都是-0,或者都是NaN或者都是非零而且非NaN且为同一个值。
- 总结
Object.is()与==运算不同之处在于==需要做类型转化,但是Object.is()不需要做类型转化。Object.is()与===运算不同之处在于,在===下,+0和-0相同,NaN和NaN不同,在Object.is()下,+0和-0不相同,NaN和NaN相同。
'1'.toString()为什么不会报错?
在这个语句运行的过程中做了这样几件事情:
- 第一步: 创建Object类实例。
- 第二步: 调用实例方法。
- 第三步: 执行完方法立即销毁这个实例。 结果还是字符串'1'
0.1+0.2为什么不等于0.3
浮点数转二进制时丢失了精度,计算完再转回十进制时出现的问题
什么是BigInt
BigInt是一种新的数据类型,用于当整数值大于Number数据类型支持的范围时。这种数据类型允许我们安全地对大整数执行算术操作。
[] == ![]结果是什么?
== 中,左右两边都需要转换为数字然后进行比较。 []转换为数字为0。 ![] 首先是转换为布尔值,由于[]作为一个引用类型转换为布尔值为true, 因此![]为false,进而在转换成数字,变为0。 0 == 0 , 结果为true
改造下面的代码,让它输出1,2,3,4,5
for(var i = 1;i <= 5;i++){
(function(j){
setTimeout(function timer(){
console.log(j)
}, 0)
})(i)
}
for(var i=1;i<=5;i++){
setTimeout(function timer(j){
console.log(j)
}, 0, i)
}
for(let i = 1; i <= 5; i++){
setTimeout(function timer(){
console.log(i)
},0)
}
let让JS有函数作用域变为了块级作用域,用let后作用域链不复存在。
下面执行后输出什么?
for(var i = 1; i <= 5; i ++){
setTimeout(function timer(){
console.log(i)
}, 0)
}
结论: 输出5个6。
因为setTimeout为宏任务,由于JS中单线程eventLoop机制,在主线程同步任务执行完后才去执行宏任 务,因此循环结束后setTimeout中的回调才依次执行,但输出i的时候当前作用域没有,往上一级再找,发现了i,此时循环已经结束,i变成了6。因此会全部输出6。
如何判断一个对象是不是空对象?
// 方法1
Object.keys(obj).length === 0
// 方法2
JSON.stringify(obj) === '{}'
js中如何判断一个值是否是数组类型?
先设置一个数组遍量arr
const arr= [];
instanceof
arr instanceof Array; // true
Array.isArray
Array.isArray(arr) // true
const obj = {}
Array.isArray(obj) // false
Object.prototype.isPrototypeOf
方法用于测试一个对象是否存在于另一个对象的原型链上。
Object.prototype.isPrototypeOf(arr, Array.prototype); // true
Object.getPrototypeOf
Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)
Object.getPrototypeOf(arr) === Array.prototype// true
Object.prototype.toString
Object.prototype.toString.call(arr) === '[object Array]' // true
const obj = {}
Object.prototype.toString.call(obj) // "[object Object]"
如何区分数组和对象?
1. 通过 ES6 中的 Array.isArray 来识别
console.log(Array.isArray([]))//true
console.log(Array.isArray({}))//false
2. 通过 instanceof 来识别
console.log([] instanceof Array)//true
console.log({} instanceof Array)//false
3. 通过调用 constructor 来识别
console.log([].constructor)//[Function: Array]
console.log({}.constructor)//[Function: Object]
4. 通过 Object.prototype.toString.call 方法来识别
console.log(Object.prototype.toString.call([]))//[object Array]
console.log(Object.prototype.toString.call({}))//[object Object]
const声明了数组,还能push元素吗,为什么?
可以
数组是引用类型,const声明的引用类型变量,不可以变的是变量引用始终指向某个对象,不能指向其他对象,但是所指向的某个对象本身是可以变的
将数组的length设置为0,取第一个元素会返回什么?
设置 length = 0 会清空数组,所以会返回 undefined
js中类型转换流程
在js中对于相等的判断流程是这样的,两个操作数都会先进行类型转换,然后再比较它们。 转换过程遵循以下规则(其实都是调用valueOf和toString方法)
如果一个操作数是布尔值,则将布尔值转化为数值0或1 如果是字符串和数值比较,则将字符串转化为数值 如果是对象和其余类型比较,则调用对象valueOf()方法
习题
console.log(null == false); //false 因为null和undefined根本就没有valueOf方法.
console.log(null == 0); //false
console.log(undefined == false); //false
console.log(undefined == 0); //false
console.log(undefined == null); //true 是因为在语言设计时,设计者觉得二者很像,才使他们相等
console.log(null.valueOf()); //Cannot read property 'valueOf' of null console.log(undefined.valueof()); //Cannot read property 'valueOf' of null