数据类型
Object.prototype.toString
.call()
.match(/\[object (.*?)\]/)[1]
.toLowerCase();
# js 原始数据类型?引用数据类型?
# 原始值
- undefined
- null
- string
- number
- boolean
- symbol
- bigInt
# 引用数据类型
对象 Object
- 普通对象 Object
- 正则对象 RegExp
- 函数对象 function
- 数组对象 Array
- 日起对象 Date
- 数学函数 Math
# null 是对象么
不是对象
虽然 typeof null 会输出 object,但是这只是 JS 存在的一个悠久 Bug。在 JS 的最初版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象然而 null 表示为全零,所以将它错误的判断为 object 。
# 0.1+0.2 为什么不等于 0.3
0.1 和 0.2 在转换成二进制后会无限循环,由于标准位数的限制后面多余的位数会被截掉,此时就已经出现了精度的损失,相加后因浮点数小数位的限制而截断的二进制数字在转换为十进制就会变成 0.30000000000000004
# typeof
对于原始类型来说,除了 null 都可以调用 typeof 显示正确的类型
但对于引用数据类型,除了函数之外,都会显示"object"。
因此采用 typeof 判断对象数据类型是不合适的,采用 instanceof 会更好,instanceof 的原理是基于原型链的查询,只要处于原型链中,判断永远为 true
# instanceof 能否判断基本数据类型
能,但是要改写
其实就是自定义 instanceof 行为的一种方式,这里将原有的 instanceof 方法重定义,换成了 typeof,因此能够判断基本数据类型
class PrimitiveNumber {
static [Symbol.hasInstance](x) {
return typeof x === "number";
}
}
console.log(111 instanceof PrimitiveNumber); // true
# 实现 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);
}
}
# Object.is 和 ===
Object 在严格等于的基础上修复了一些特殊情况下的失误,具体来说就是+0 和-0,NaN 和 NaN
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;
}
}
# [] !== []
== 中,左右两边都需要转换为数字然后进行比较。
[]转换为数字为 0。
![] 首先是转换为布尔值,由于[]作为一个引用类型转换为布尔值为 true, 因此![]为 false,进而在转换成数字,变为 0。
0 == 0 , 结果为 true
# js 类型转换哪几种?
- 转换成数字
- 转换成布尔值
- 转换成字符串
# == 和 ===
===叫做严格相等,是指:左右两边不仅值要相等,类型也要相等
==不像===那样严格,对于一般情况,只要值相等,就返回 true,但==还涉及一些类型转换
转换规则:
- 两边的类型是否相同,相同的话就比较值的大小
- 判断是否是 null 和 undefined,是的话就返回 true
- 判断是否是 String 和 Number,是的话,把 String 类型转换成 Number,再进行比较
- 判断其中一方是否是 Boolean,是的话就把 Boolean 转换成 Number,再进行比较
- 如果其中一方为 Object,且另一方为 String、Number 或者 Symbol,会将 Object 转换成字符串,再进行比较
console.log({ a: 1 } == true); //false
console.log({ a: 1 } == "[object Object]"); //true
# 对象转原始类型流程
对象转原始类型,会调用内置的[ToPrimitive]函数,对于该函数而言,其逻辑如下
- 如果 Symbol.toPrimitive()方法,优先调用再返回
- 调用 valueOf(),如果转换为原始类型,则返回
- 调用 toString(),如果转换为原始类型,则返回
- 如果都没有返回原始类型,会报错
并非所有对象的隐式转换都会按照 Symbol.toPrimitive()->valueOf()->toString()这个顺序尝试,Date 对象会优先尝试 toString()方法来实现转换,非 Date 对象按照上述顺序
var obj = {
value: 3,
valueOf() {
return 4;
},
toString() {
return "5";
},
[Symbol.toPrimitive]() {
return 6;
},
};
console.log(obj + 1); // 输出7
# 如何让 if( a === 1 && a === 2)成立
var a = {
value: 0,
valueOf: function() {
this.value++;
return this.value;
},
};
console.log(a == 1 && a == 2); //true
还有一个 sao 断腿的解法:
var a = [1, 2];
a.join = a.shift;
console.log(a == 1 && a == 2);
# iframe 特殊处理
instanceof 不能检测出基本类型,而且不能跨 iframe
其实就是两套隔离的进程,无法通信