- 原始类型有哪几种,null 是对象吗?
- 对象类型和原始类型的不同之处,函数的参数是对象会发生什么问题?
- typeof 是否能正确判断类型,instanceof 能正确判断对象的原理是什么?
- == 和 === 有什么区别?
- 判断数据类型的几种方式
- 判断数组的几种方式以及它们的区别
数据类型
基本(值)类型 原始类型
- String / Number / Boolean / undefined / null / Symbol / BigInt
对象(引用)类型
- Object 任意对象
- Function 可以执行的特殊对象
- Array 内部数据是有序的,有数值下标的特殊对象
- 原始类型和对象类型不同的是:原始类型存储的是值,对象类型存储的是地址 ( 指针 ) 。
判断数据类型
typeof 返回数据类型的字符串表达
- 可以判断:undefined / 数值 / 字符串 / 布尔
- 不能判断:function 与 Symbol 与 BigInt (constructor 和 Object 上的原型方法 toString 可以判断)
- 不能判断:null 与 object / object 与 array
- 原始类型数据不能判断 null 对象类型数据除了函数都会返回 object
- 另外对于 null 来说,很多人会认为他是个对象类型,其实这是错误的。虽然 typeof null 会输出 object,但是这只是 JS 存在的一个悠久 Bug。在 JS 的最初版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象,然而 null 表示为全零,所以将它错误的判断为 object 。虽然现在的内部类型判断代码已经改变了,但是对于这个 Bug 却是一直流传下来。
- 0.1 + 0.2 精度 != 0.3 原因:0.1 和 0.2 在转换成二进制后会无限循环,由于标准位数的限制后面多余的位数会被截掉,此时就已经出现 了精度的损失,相加后因浮点数小数位的限制而截断的二进制数字在转换为十进制就会变成 0.30000000000000004。
instanceof 左为实例,右为构造函数。即判断左是不是右的实例对象。内部机制是通过原型链来判断的
- 用于检测构造函数的 prototype 属性是否出现在某个实例的原型链上
- 判断对象的具体类型
// 手撸一个 instanceof
// instanceof 原理
function myInstanceof (left, right) {
// 获取类型的原型
let prototype = right.prototype
// 获得对象的原型
left = left.__proto__
// 循环判断类型的原型是否等于对象的原型,直到对象原型为 null,因为原型最终为 null
while(true) {
if(left.__proto__ === null || left.__proto__ === 'undefined') {
return false
}
if(prototype === left) {
return true
}
left = left.__proto__
}
}
let a = function(){}
a instanceof a // false
// a 的原型链是向上查找,不会存在自己的原型
// a 不是 a 的实例对象
- ===
可以判断:undefined / null
let a
console.log(a, typeof a) // undefined "undefined"
console.log(typeof a === 'undefined', a === undefined) // true true
a = 3
console.log(typeof a === 'number') // true
a = 'protein'
console.log(typeof a === 'string') // true
a = true
console.log(typeof a === 'boolean') // true
a = null
console.log(typeof a, a === null) // object true
let b1 = {
b2: [1, '‘protein', console.log],
b3: function() {
console.log('b3')
return function() {
return 'protein'
}
}
}
console.log(b1 instanceof Object, b1 instanceof Array) // true false
console.log(b1.b2 instanceof Array, b1.b2 instanceof Object) // true true
console.log(b1.b3 instanceof Function, b1.b3 instanceof Object) // true true
console.log(typeof b1.b2, typeof b1.b2 === 'object') // object true
console.log(typeof b1.b3 === 'function') // true
console.log(b1.b3()()) // b3 protein
- 判断 NaN
// ES6
isNaN()
// ES5
a != a
// true 是 NaN
// false 不是 NaN
什么是实例
// 实例:实例对象
// 类型:类型对象
function Person(name, age) { // 构造函数 类型对象
this.name = name
this.age = age
}
let p = new Person('protein', 22) // 根据类型创建的实例对象
Person('potato', 23) // 语法没问题 但是不建议这么写
undefined 与 null 的区别
undefined:定义了但未赋值
null:定义并赋值了,只是值为 null
let protein
console.log(protein) // undefined
protein = null
console.log(protein) // null
什么时候给变量赋值为 null 呢
初始赋值,表示将要赋值为对象
结束前,让对象成为垃圾对象(被垃圾回收器回收)
// 起始
let tomato = null // 初始赋值为 null 表示将要赋值为对象
// 确定对象并赋值
tomato = ['red', 10]
// 结束 回收
tomato = null // 让 tomato 指向的对象成为垃圾对象(被垃圾回收器回收)
严格区分变量类型与数据类型
- 数据类型
基本类型
引用类型 - 变量类型(变量内存值的类型)
基本类型:保存就是基本类型的数据
引用类型:保存的是地址值
数据类型转换
- 转 Boolean
除了 undefined,null,false,0,-0,NaN,‘ ’ 空字符串 其他的值都转为 true,包括所有的对象。
原始值 | 转换目标 | 结果 |
---|---|---|
number | Boolean | 除了 0、-0、NaN 都为 true |
string | Boolean | 除了空字符串 ' ' 都为 true |
undefined、null | Boolean | false |
引用类型 | Boolean | true |
number | string | 6 => '6' |
Boolean、函数、Symbol | string | 'true' |
数组 | string | [1, 2] => '1, 2' |
对象 | string | '[ object, Object ]' |
string | number | '6' => 6, 'p' => NaN |
数组 | number | [] => 0, [ '6' ] => 6, 其他都是 NaN |
null | number | 0 |
非数组的引用类型 | number | NaN |
Symbol | number | 抛错 |
四则运算符
- 加法 + 运算符的特点
运算中其中一方为字符串,那么就会把另一方也转化成字符串
如果一方不是字符串或者数字,那么会将他转化成数字或者字符串
console.log(1 + '1'); // 11
console.log(true + true); // 2
console.log(4 + [1, 2, 3]); // 41, 2, 3
console.log('a' + + 'b'); // aNaN 因为 + 'b' 为 NaN
- 非加法运算符来说只要其中一方不是数字就会被转化成数字
console.log(2 * '1'); // 2
console.log(2 * []); // 0
console.log(2 * ['2']); // 4
console.log(2 * [1, 2]); // NaN
== 和 === 的区别
=== 判断左右类型和值是不是都相等
== 如果左右类型相等,则进行大小的比较,如果左右类型不相等会进行类型转换
- 判断是否在对比 null 和 undefined 如果是返回 true
- 判断两者的类型是否为 string 和 number,如果是就会将 string 转为 number
1 == '1' => 1 == 1 // true
- 判断一方是否为 boolean 如果是就会将其转换成 number 在进行判断
'1' == true => '1' == 1 => 1 == 1 // true
- 判断一方是否为 object 另一方是否为 string、number、symbol 是的话就会把 object 转换成原始类型在进行判断
'1'== { name: 'protein' } => '1' == '[ object, object ]' // false
实例:[] == ![]
[] == ![] => [] == false => [] == 0 => 0 == 0 // true
判断数组的几种方式以及它们的区别
- typeof 'object' 无法判断
- Array.isArray
- Object.prototype.toString.call(arr) "[object Array]" 返回一个表示该对象的字符串
- instanceof
- 原型的 constructor 属性