课程名称: 破解JavaScript高级玩法,成为精通 JS 的原生专家
课程章节: 2-1 数据类型的陷阱,从表象看本质!
课程讲师: Cloud
课程内容:
判断是不是Object
function isObject(obj) {
if(typeof obj === 'object') {
return true;
}
return true
}
-
第一个问题: 上面的方法有什么问题?
typeof null 也是 ‘object’
-
第二个问题:为什么 typeof null 返回的值是 “object” ?
追溯 javascript 第一个版本,这个版本中单个值在栈中占用32个位的存储单元,又分为两个部分,一个标记位,一个表示其它的数据,这个时候它有只有5中数据类型:
// 类型标记位 // 000: object // 001: integer // 010: double // 100: string // 110: boolean
而 null 在机器码中的指针从0~31 位全都是0,自然标记为也是 0,而标记为是0,typeof 返回的也是0了。
当然现在的v8引擎不是这样判断数据的,它是一个历史包袱
-
第三个问题: 为什么不修复这个问题?
因为兼容性的问题,如果一改很多程序就运行不起来了,所以不得不做妥协
一元运算符+转为数字
function toNumber(val) {
return +val;
}
上面的代码在 es5中是完全没有问题的,但在 es6 引入的新的数据类型中是会出错,如下:
const print = console.log;
function toNumber(val) {
const result = +val;
print(result);
return result;
}
// 传统数据类型
toNumber(null); // 0
toNumber(undefined); // NaN
toNumber(1); // 1
toNumber("123aa"); // NaN
toNumber({}); // NaN
toNumber(true); // 1
// ES6的 bigInt和Symbol
// toNumber(10n) // 错误
// toNumber(Symbol.for("a")) // 错误
所以我们代码要考虑向后兼容
位移转为数字
// 有符号位移
function toNumber(val) {
return val >> 0
}
// 无符号位移
function toNumber2(val) {
return val >>> 0
}
代码有什么问题?
上面代码问题为 数值较大是 会出现莫名的数字
本质是 32位的有符号位移和无符号位移
解析:
const print = console.log;
function toNumber(val) {
const result = val >> 0;
print(result);
return result;
}
function toNumber2(val) {
const result = val >>> 0;
print(result);
return result;
}
// toNumber(null); // 0
// toNumber({}); // 0
// toNumber("10x"); // 0
// toNumber("10"); // 10
// 超大的数
toNumber(Number.MAX_SAFE_INTEGER); // -1
toNumber2(Number.MAX_SAFE_INTEGER); // 4294967295
// toNumber2(Number.MAX_SAFE_INTEGER) => 4294967295
var val = Number.MAX_SAFE_INTEGER.toString(2);
// 11111111111111111111111111111111111111111111111111111
var val1 = val.substring(0, 32);
// 11111111111111111111111111111111
var num = parseInt(val1, 2);
// 4294967295
// console.log(num)
// toNumber(Number.MAX_SAFE_INTEGER) => -1
// 有符号数字,最高位为符号位。
// 十进制变二进制:原码 => 反码 加一(补码)
// 二进制变十进制:减一 =>反码 = 原码。
var val = Number.MAX_SAFE_INTEGER.toString(2);
// 11111111111111111111111111111111111111111111111111111
var val1 =
val.substring(0, 32) -
// 11111111111111111111111111111111
// 减1
// 11111111111111111111111111111110
// 取反,
// 00000000000000000000000000000001 = 1
// 因为其最高位1是负数
1;
字符串批量转换为整数
const arr = ["1","2","3"]
arr.map(parseInt)
-
问题1:结果是多少?
结果为 [ 1, NaN, NaN ]
上面代码翻译如下:
["1", "2", "3"].map((val, index) => parseInt(val, index)); // parseInt("1",0) // 这个0是没有生效的所以默认为 10进制 // parseInt("2",1) // 这个是1进制,但结果是为 2,1进制是不能出现2的,所以返回 NaN // parseInt("3",2) // 这个是2进制,但结果是为 3,2进制是不能出现3的,所以返回 NaN
-
问题2:parseInt第二个参数的取值范围
范围为 2~36 的整数
if条件判断
const result = {}
//name存在
if(result.name) {
result.name = obj.name
}
return result;
-
上面的代码是否能进入if
不能 因为对象上没有name,返回 undefined,undefined在if条件中会转为boolean值,undefined转boolean为false
这里推荐使用 Object.hasOwnProperty() 进行判断对象上是否存在某个属性
-
问题:那些值转为布尔值为false
null、undefined、’’、false、(±)0、NaN
宽松比较
null == 0 // false
'0' == false // true
本质:隐式转换
隐式转换七大法则(规律)
-
NaN
它和任何人都不能包括,包括它自己
-
bigInt,Symbol
首先比较是不是同类型,如果不是就不相等
-
null、undefined
null只会和null或undefined相等,undefined也是一样
-
布尔类型(boolean)和其它类型的相等比较
布尔类型(boolean)会转为数字
-
数字类型(Number)和 字符串类型(String)的相等比较
字符串(String)会转为数字
-
对象类型({})和 原始类型 的相等比较
对象会转为原始数据类型
-
对象和对象相等比较
比两个对象的引用是否同一个地址
其它
-
typeof 性能比 instanceof 性能高20倍?
千万级别的时候性能相差 1~2倍
// instanceOf 性能 var count = 10000000; var func = function () {}; var startTime = new Date(); console.log(typeof func === "function"); for (var j = 0; j < count; j++) { typeof func === "function"; } console.log( '[typeof func === "function"] ' + (new Date().getTime() - startTime.getTime()) ); /* ---------- */ startTime = new Date(); console.log(func instanceof Function); for (var k = 0; k < count; k++) { func instanceof Function; } console.log( "[func instanceof Function] " + (new Date().getTime() - startTime.getTime()) );
-
null 和 undefined实现机制完全不一样
null 是属于关键字
undefined 是属于一个词,变量
代码测试:
// null和undefined var print = console.log; print("null=》", Object.getOwnPropertyDescriptor(global, "null")); print("undefined=》", Object.getOwnPropertyDescriptor(global, "undefined"));
上面代码运行后可以看见,null 是没有值的,undefined有描述信息。
由此可见 null 是关键字,undefined是一个值
-
判断是不是数字,NaN
课程收获:
对js数据类型有了深刻的理解
共同学习,写下你的评论
评论加载中...
作者其他优质文章