HOME 首页
SERVICE 服务产品
XINMEITI 新媒体代运营
CASE 服务案例
NEWS 热点资讯
ABOUT 关于我们
CONTACT 联系我们
创意岭
让品牌有温度、有情感
专注品牌策划15年

    js底层原理(js底层原理常见问题)

    发布时间:2023-03-13 22:59:35     稿源: 创意岭    阅读: 122        问大家

    大家好!今天让创意岭的小编来大家介绍下关于js底层原理的问题,以下是小编对此问题的归纳整理,让我们一起来看看吧。

    ChatGPT国内免费在线使用,一键生成原创文章、方案、文案、工作计划、工作报告、论文、代码、作文、做题和对话答疑等等

    只需要输入关键词,就能返回你想要的内容,越精准,写出的就越详细,有微信小程序端、在线网页版、PC客户端

    官网:https://ai.de1919.com

    本文目录:

    js底层原理(js底层原理常见问题)

    一、typeof & instanceof 原理

    typeof 可判断类型比较有限,它的输出值只有八种,即用 typeof 判断一个变量,得到的结果只会是以下八种类型中的一种

    第一版 JS 的 typeof 实现如下,在 JS 诞生之初就只有六种类型判断。

    typeof 的输出值中没有 array 这一项,所以当需要判断数组类型时,可以使用 instanceof 。 instanceof 会判断右侧表达式是否在左侧表达式的原型链上,所以下面的两个 instanceof 都为 true 。

    答案是 NO ,前面说了, typeof 只有八种类型,其中并没有 null 这一类型,如果用 typeof 判断,会得到 object 的结果。

    因为在 Javascript 底层存储变量的时候,会在变量的机器码低位 1-3 位表示类型信息。而 null 的低位 1-3 解析到的为 000 ,而 000 表示的是 obecjt 类型。

    答案依然是 NO ,因为 null 根本没有 __proto__ 属性,所以用 instanceof 去检测永远都不会返回 true

    拓展: Object.prototype.toString 可以判断所有类型

    下面的表达式分别输出什么呢?如果全部回答正确,你对原型链和 instanceof 的理解应该非常到位了。

    二、JS位运算异常(位运算精度丢失)的原因探究

    《【转+补充】深入研究js中的位运算及用法》

    《【JS时间戳】获取时间戳的最快方式探究》

    日常开发中一直没遇到过位运算导致精度丢失的问题,直到这天,搞10位时间戳取整的时候,终于被我撞上了。具体是个什么场景呢,我们来还原下案发现场:

    可以看到输出的结果为:

    得到的 t 是一个精确到微秒的时间戳。但是请求接口的时候需要的是一个10位(精确到秒)的时间戳,所以这里需要将它转换为10位,自然就是 ➗1000 即可,然后通过位运算来实现类似 Math.trunc 的取证效果,得到了我们要的10位时间戳。至此完美解决!那问题又是如何发生的呢?

    按照上面的运算规律,如果我们要获取13位时间戳,是不是直接对 t>>0 就可以了呢?我们来看一下:

    输出结果如下:

    WTF!!!看到了咩!!!居然输出了一个负数!!!我们想要的结果应该是 1597113682985 才对啊!为什么会出现了负数呢!!!

    由此,怪物出现啦!我们今天就来解读(xiang fu)一下它!

    想到这里,我们一定就会怪是位运算的锅!那这个锅该怎么让位运算背起来呢!我们来研究一下!

    首先我们知道,JS中没有真正的整型,数据都是以double(64bit)的标准格式存储的,这里就不再赘述了,要想搞透其中的原理,请打开 【传送门】

    位运算是在数字底层(即表示数字的 32 个数位)进行运算的。由于位运算是低级的运算操作,所以速度往往也是最快的(相对其它运算如加减乘除来说),并且借助位运算有时我们还能实现更简单的程序逻辑,缺点是很不直观,许多场合不能够使用。

    以下来源于w3shool:

    ECMAScript 整数有两种类型,即有符号整数(允许用正数和负数)和无符号整数(只允许用正数)。 在 ECMAScript 中,所有整数字面量默认都是有符号整数 ,这意味着什么呢?

    有符号整数使用 31 位表示整数的数值,用第 32 位表示整数的符号,0 表示正数,1 表示负数。数值范围从 -2147483648 到 2147483647 。

    可以以两种不同的方式存储二进制形式的有符号整数,一种用于存储正数,一种用于存储负数。 正数是以真二进制形式存储的 ,前 31 位中的每一位都表示 2 的幂,从第 1 位(位 0)开始,表示 20,第 2 位(位 1)表示 21。没用到的位用 0 填充,即忽略不计。例如,下图展示的是数 18 的表示法。

    那在js中二进制和十进制如何转换呢?如下

    负数同样以二进制存储,但使用的格式是二进制补码。计算一个数值的二进制补码,需要经过下列3个步骤:

    例如,要确定-18的二进制表示,首先必须得到18的二进制表示,如下所示:

    0000 0000 0000 0000 0000 0000 0001 0010

    接下来,计算二进制反码,如下所示:

    1111 1111 1111 1111 1111 1111 1110 1101

    最后,在二进制反码上加 1,如下所示:

    1111 1111 1111 1111 1111 1111 1110 1101 +

    0000000000000000000000000000 0001 =

    1111 1111 1111 1111 1111 1111 1110 1110

    因此,-18 的二进制就是 1111 1111 1111 1111 1111 1111 1110 1110

    而其相反数18的二进制为 0000 0000 0000 0000 0000 0000 0001 0010

    ECMAScript会尽力向我们隐藏所有这些信息,在以二进制字符串形式输出一个负数时,我们看到的只是这个负数绝对值的二进制码前面加上了一个负号

    JavaScript 只有一种数字类型 ( Number )

    我们将 1596596596.3742654.toString(2) 转为二进制字符串表示如下:

    1011111001010100010000101110100.0101111111001111110111

    但实际在内存中的存储如下:

    说到这里就不得不简单提一下数字精度丢失的问题。上面也知道,JS中所有的数字都是用double方式进行存储的,所以必然会存在精度丢失问题。

    以下转自文章: JavaScript数字精度丢失问题总结

    此时只能模仿十进制进行四舍五入了,但是二进制只有 0 和 1 两个,于是变为 0 舍 1 入。这即是计算机中部分浮点数运算时出现误差,丢失精度的根本原因。

    大整数的精度丢失和浮点数本质上是一样的,尾数位最大是 52 位,因此 JS 中能精准表示的最大整数是 Math.pow(2, 53) ,十进制即 9007199254740992

    大于 9007199254740992 的可能会丢失精度:

    9007199254740992 >> 10000000000000...000 ``// 共计 53 个 0

    9007199254740992 + 1 >> 10000000000000...001 ``// 中间 52 个 0

    9007199254740992 + 2 >> 10000000000000...010 ``// 中间 51 个 0

    实际上

    9007199254740992 + 1 ``// 丢失

    9007199254740992 + 2 ``// 未丢失

    9007199254740992 + 3 ``// 丢失

    9007199254740992 + 4 ``// 未丢失

    以上,可以知道看似有穷的数字, 在计算机的二进制表示里却是无穷的,由于存储位数限制因此存在“舍去”,精度丢失就发生了。

    想了解更深入的分析可以看这篇论文(你品!你细品!): What Every Computer Scientist Should Know About Floating-Point Arithmetic

    关于精度和范围的内容可查看 【JS的数值精度和数值范围】

    通过前面的知识补充,我们已经知道:

    这也就是为什么对于整数部位为10位的时间戳,通过位运算可以进行取整(因为目前时间戳159xxxxxxx<2147483647),不存在时间戳超过范围的问题。但是对于13位时间戳,如 1596615447123>2147483647 ,此时再通过位运算操作的时候就会导致异常,如:

    这主要是因为在进行位运算之前,JS会先将64bit的浮点数 1596615447015.01 转为32bit的有符号整型后进行运算的,这个转换过程如下:

    为了验证上述过程,我们再举一个例子: 1590015447015.123 >> 0 = 877547495

    将将将将!没错的吧!所以JS的这个坑还真是。。。 让人Orz

    三、JS防水涂料怎么,优缺点各是什么?

    JS防水涂料实际上是一类复合型防水涂料,J就是指聚合物,S是指水泥,JS就是聚合物水泥防水涂料,它是一种以聚丙烯酸酯乳液、乙烯-醋酸乙烯酯共聚乳液等聚合物乳液与各种添加剂组成的有机液料,和水泥、石英砂、轻重质碳酸钙等无机填料及各种添加剂所组成的无机粉料通过合理配比、复合制成的一种双组份、水性建筑防水涂料;相对于其他防水涂料而言,其突出的优点比较多,主要有:1、无毒无害,属环保型防水涂料,经检测符合国家生活饮用水标准;2、可在潮湿基层施工,基层不受含水率限制,可缩短施工工期;3、具有较高的抗拉强度和延伸率,对基层有微小裂缝追随性强,涂层坚韧,具有明显的柔韧性;4、粘结力强,涂膜与基层、饰石层粘结牢固,不论涂刷在垂直面、斜面及各种基层上均有良好的粘结效果。

    四、js中fib()函数是自定义的还是系统自带的?

    你自己都说fib()是自定函数那肯定就是自定义函数啊。

    function fib(n){

    return (n===1||n===2)?1:fib(n-1)+fib(n-2);

    }

    console.log(fib(8));

    如果用ES6来写可以这样:

    let fib=n=>(n===1||n===2)?1:fib(n-1)+fib(n-2);

    console.log(fib(8));

    以上就是关于js底层原理相关问题的回答。希望能帮到你,如有更多相关问题,您也可以联系我们的客服进行咨询,客服也会为您讲解更多精彩的知识和内容。


    推荐阅读:

    贴吧js什么意思(贴吧jsk是什么意思)

    js底层原理(js底层原理常见问题)

    我被js了是什么意思啊(我被js了是什么意思啊英语)

    三只兔子可以合体变身的动漫(三只兔子可以合体变身的动漫有哪些)

    家里越干净的人越容易发财(家里越干净,越有财运)