你忽略的js底层原理

107 阅读2分钟

1) typeof 检测数据类型 原理

先来几个大家都会的例子,想一想为什么结果是这样的呢?

console.log(typeof 1);     //number
console.log(typeof 'a');   //string
console.log(typeof false); //boolean
console.log(typeof []);    //object
console.log(typeof /a/);   //object
console.log(typeof {});    //object
console.log(typeof null);  //object  
console.log(typeof undefined);//undefined

检测数据类型的底层原理:

 + 所有的数据类型值,在计算机底层都是按照 “64位” 的二进制值进行存储的!
   + typeof是按照二进制值进行检测类型的
     + 二进制的前三位是0,认为是对象,然后再去看有么有实现call方法,
       如果实现了,返回 'function',没有实现,则返回 'object'
       按照计算机底层存储的二进制进行检测「效率高」
        -   000 对象
        -   1 整数
        -   010 浮点数
        -   100 字符串
        -   110 布尔
        -   000000…. null
        -   -2^30 undefined
        -   ……
     + null64个零  typeof null -> 'object' 「局限性」
     + ...
   + 检测未被声明的变量,值是'undefined'

2)对象类型转化number类型的过程

基本数据类型的相关操作开发者对其往往只是使用,知其然不知其所以然。
比如:Array是如何转化成Number类型的呢
==>第一步 直接转化

let arry =[10];
console.log(Number(arry)); //10  输出10没什么问题

==>第二步 我们稍微修改下看看arry的 toString 方法再看看效果呢

arry.toString = function(){return '12'};
console.log(Number(arry));//12 这已经变成12了哦

==>第三步 修改valueOf 方法再看看效果呢

arry.valueOf = function(){return '14'};
console.log(Number(arry));//14 又变成14了哦

==>第四步 修改**[Symbol.toPrimitive]** 方法再看看效果呢

arry[Symbol.toPrimitive] = function(){return '16'};
console.log(Number(arry)); //16 咋又变了呢?

按照上面步骤执行下来我们来分析下完整程序
我们再来打印arry所有方法的值都还是多少呢?

arry =[10];
//输出获取这三个方法
console.log(arry[Symbol.toPrimitive]); //undefined
console.log(arry.valueOf()); //[10]
console.log(arry.toString()); //10

console.log(Number(arry)); //10 
//重写
arry.toString = function(){return '12'};
arry.valueOf = function(){return '14'};
arry[Symbol.toPrimitive] = function(){return '16'};
//再次输出获取这三个方法
console.log(arry.toString()); //12
console.log(arry.valueOf()); //14
console.log(arry[Symbol.toPrimitive]()); //16

结果分析

在arry转化为Number类型时转换过程如下
首先 arr[Symbol.toPrimitive] -> undefined
其次 arr.valueOf() 获取原始值 -> [10] 不是原始值
再此 arr.toString() 转换为字符串 -> '10'
最后 再把字符串‘10’转化为数字 -> 10
[Symbol.toPrimitive]并不会覆盖valueOf和toString,
同样valueOf也不会影响toString
2.1. 拓展面试题

实现 a==1&a==2&&a==3 是true
利用对象转换Number特性来做

a = {n:0,toString:function(){return ++this.n}} 
console.log(a==1&&a==2&&a==3);//true