深究JS底层原理

一、JS中八种数据类型判断方法

在JavaScript中,数据类型分为两大类:基本(原始)数据类型和引用(对象)数据类型。

基本数据类型(Primitive Data Types)

基本数据类型是表示简单的数据片段,它们是直接存储在变量中的数据。JavaScript中的基本数据类型有以下几种:

  1. String - 表示文本数据,例如 "Hello, World!"
  2. Number - 表示整数和浮点数,例如 42 和 3.14
  3. Boolean - 表示逻辑值 true 或 false
  4. Undefined - 表示未定义的值,即变量已声明但未初始化时的值。
  5. Null - 表示空值或者不存在的对象。在JavaScript中,null 是一个表示“无”的对象,转为数值时为 0
  6. Symbol (ES6新增) - 表示独一无二的值,常用于创建对象的私有成员。
  7. BigInt (ES2020新增) - 表示非常大的整数。

基本数据类型的值是不可变的,也就是说,一旦创建,就不能更改。如果对基本数据类型的变量进行操作,实际上是创建了一个新的变量或值。

引用数据类型(Reference Data Types)

引用数据类型表示的是数据的集合,它们存储的是对数据的引用(内存地址),而不是数据本身。在JavaScript中,最常见的引用数据类型是对象(Object),还包括以下几种:

  1. Object - 表示一组无序的键值对,例如 {name: "Alice", age: 25}
  2. Array - 表示一组有序的数据集合,例如 [1, 2, 3, 4]
  3. Function - 表示函数,JavaScript中的函数是一等公民,可以作为对象使用。
  4. Date - 表示日期和时间。
  5. RegExp - 表示正则表达式。

引用数据类型的值是可变的,这意味着可以改变它们的内容而不改变它们的身份。例如,可以向对象添加属性或修改数组中的元素。

基本数据类型与引用数据类型的区别

以下是一些基本数据类型和引用数据类型之间的关键区别:

  • 存储方式:基本数据类型的值直接存储在变量中,而引用数据类型存储的是内存地址。
  • 赋值:基本数据类型赋值时是传递值,而引用数据类型赋值时是传递引用。
  • 比较:基本数据类型比较的是值,而引用数据类型比较的是引用地址。
  • 参数传递:在函数中,基本数据类型作为参数传递时,传递的是值的副本;引用数据类型传递的是引用地址。

理解这些差异对于编写高效和正确的JavaScript代码非常重要。

八种数据类型判断方式

二、NaN

三、数值千分位的六种方法

1.format with array

(number + '') 是一种常见的类型转换技巧,它将数字 number 转换为字符串。无论 number 是什么数字,加上一个空字符串 '' 后,结果都会是一个字符串形式的 number。

function format_with_array(number) {// 转为字符串,并按照.拆分var arr = (number + '').split('.');// 整数部分再拆分var int = arr[0].split('');// 小数部分var fraction = arr[1] || '';// 返回的变量var r = "";var len = int.length;// 倒叙并遍历int.reverse().forEach(function (v, i) {// 非第一位并且是位值是3的倍数, 添加 ","if (i !== 0 && i % 3 === 0) {r = v + "," + r;} else {// 正常添加字符r = v + r;}})// 整数部分和小数部分拼接return r + (!!fraction ? "." + fraction : '');
}const print = console.log;
print(format_with_array(938765432.02));938765432.02
  1. var arr = (number + '').split('.');

    这行代码首先通过 number + '' 将数字 number 转换为字符串。这是因为 split 方法是字符串的方法,不能直接在数字上使用。
    然后使用 split('.') 方法将字符串按照小数点(.)分割成两部分,结果存储在数组 arr 中。如果 number 是一个整数,那么 arr 将只有一个元素,即整数部分;如果 number 是一个小数,那么 arr将有两个元素,第一个元素是整数部分,第二个元素是小数部分。
  2. var int = arr[0].split('');

    这行代码将 arr 数组中的第一个元素(即整数部分)再次使用 split('') 方法进行分割。由于没有指定分隔符,实际上是将整数部分的每个字符分割成一个单独的字符串,并将结果存储在数组 int 中。例如,如果整数部分是 "123",那么 int 将是 ["1", "2", "3"]
  3. var fraction = arr[1] || '';

    这行代码尝试获取 arr 数组中的第二个元素(即小数部分)。如果 arr 只有一个元素(即 number 是一个整数),那么 arr[1] 将是 undefined
    使用逻辑或运算符 ||,如果 arr[1] 是 undefined(即没有小数部分),则将 fraction 设置为一个空字符串 ''。如果存在小数部分,则 fraction 将是小数部分的字符串。

return r + (!!fraction ? "." + fraction : '');

  1. r +:这是字符串拼接的开始,将数字 r 转换为字符串并准备拼接。

  2. !!fraction:这是双重逻辑非操作符,用于将 fraction 转换为布尔值。如果 fraction 是非空字符串、非零数字或任何“真值”对象,则 !!fraction 将为 true;如果 fraction 是空字符串、零、nullundefined 或任何“假值”,则 !!fraction 将为 false

  3. ? "." + fraction : '':这是一个条件(三元)运算符,它根据 !!fraction 的结果来决定返回的值。如果 !!fraction 为 true(即 fraction 有值),则返回 "." + fraction,即小数点加上 fraction 的值;如果 !!fraction 为 false(即 fraction 没有值或为假值),则返回空字符串 ''

整体来看,这段代码的作用是:

如果 fraction 有值,那么返回的字符串将是 r 后面跟着一个小数点和 fraction 的值。如果 fraction 没有值或为假值,那么返回的字符串就只是 r 转换成的字符串。

2.format with substring

function format_with_substring(number) {// 数字转字符串, 并按照 .分割var arr = (number + '').split('.');var int = arr[0] + '';var fraction = arr[1] || '';// 多余的位数var f = int.length % 3;// 获取多余的位数,f可能是0, 即r可能是空字符串var r = int.substring(0, f);// 每三位添加","和对应的字符for (var i = 0; i < Math.floor(int.length / 3); i++) {r += ',' + int.substring(f + i * 3, f + (i + 1) * 3)}//多余的位数,上面if (f === 0) {r = r.substring(1);}// 整数部分和小数部分拼接return r + (!!fraction ? "." + fraction : '');
}const print = console.log;
print(format_with_substring(938765432.02));

3.format with mod

function format_with_mod(number) {var n = number;  // 将传入的参数 number 赋值给变量 n,用于后续计算,保留原始数值不变。var r = "";     // 初始化一个空字符串 r,用于存储格式化后的结果。var temp;       // 声明一个变量 temp,用于暂存计算过程中的中间值。do {mod = n % 1000;  // 计算 n 除以 1000 的余数,即取 n 的最后三位数字(包括小数部分)。n = n / 1000;    // 将 n 除以 1000,即每次循环处理掉 n 的最后三位数字。temp = ~~mod;    // 使用双按位非操作符(~~)来取整,去除 mod 的小数部分,获取整数部分。// 以下代码用于构造格式化字符串:// 如果 n 大于等于 1,说明还有更多的数字需要处理,因此使用 padStart(3, "0") 来确保 temp 是三位数字,不足部分用 "0" 填充。// 如果 r 已经有内容,则在 temp 前面加上 ",",否则直接使用 temp。r = (n >= 1 ? `${temp}`.padStart(3, "0") : temp) + (!!r ? "," + r : "");} while (n >= 1);  // 当 n 大于等于 1 时,继续循环,直到 n 小于 1。var strNumber = number + "";  // 将数字 number 转换为字符串,以便后续查找小数点位置。var index = strNumber.indexOf(".");  // 查找小数点的位置。// 如果存在小数点(index >= 0),则将原始数字的小数部分添加到格式化字符串 r 的末尾。if (index >= 0) {r += strNumber.substring(index);}return r;  // 返回格式化后的字符串。
}const print = console.log;  // 将 console.log 方法赋值给变量 print,便于后续使用。
print(format_with_mod(38765432.02));  // 调用 format_with_mod 函数并打印结果。

4.format with regex

const print = console.log;
print(/hello (?=[a-z]+)/.test("hello a"));
print(/hello (?=[a-z]+)/.test("hello 1"));  
function format_with_regex(number) {var reg = /\d{1,3}(?=(\d{3})+$)/g;return (number + '').replace(reg, '$&,');
}// 987, 654, 321// const print = console.log;
// print(format_with_regex(987654321));function format_with_regex(number) {var reg = /\d{1,3}(?=(\d{3})+$)/g;return (number + '').replace(reg, function(match, ...args){    console.log(match, ...args);return match + ','});
}
format_with_regex(987654321)// function format_with_regex(number) {
//     var reg = /(\d)(?=(?:\d{3})+$)/g
//     return (number + '').replace(reg, '$1,');
// }

5.format with toLocaleString

function format_with_toLocaleString(number, minimumFractionDigits, maximumFractionDigits) {minimumFractionDigits = minimumFractionDigits || 2;maximumFractionDigits = (maximumFractionDigits || 2);maximumFractionDigits = Math.max(minimumFractionDigits, maximumFractionDigits);return number.toLocaleString("en-us", {maximumFractionDigits: maximumFractionDigits || 2,minimumFractionDigits: minimumFractionDigits || 2})
}function format_with_toLocaleString(number) {return number.toLocaleString("en-us")
}const print = console.log;
print(format_with_toLocaleString(938765432.02));

6.Intl.NumberFormat

function format_with_Intl(number, minimumFractionDigits, maximumFractionDigits) {minimumFractionDigits = minimumFractionDigits || 2;maximumFractionDigits = (maximumFractionDigits || 2);maximumFractionDigits = Math.max(minimumFractionDigits, maximumFractionDigits);return new Intl.NumberFormat('en-us', {maximumFractionDigits: maximumFractionDigits || 2,minimumFractionDigits: minimumFractionDigits || 2}).format(number)
}// 使用默认配置选项
// function format_with_Intl(number) {
//     return new Intl.NumberFormat('en-us').format(number)
// }const print = console.log;
print(format_with_Intl(938765432.02));

7.效果对比

对比一下这六种方法的性能

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>数字千分位</title>
</head><body><div style="text-align:center"><p><input type="number" value="5000" id="textCount" /></p><p><input type="button" onclick="executeTest()" value="测试" /><input type="button" onclick="javascript:document.getElementById('messageEl').innerHTML=''" value="清除" /></p></div><div id="messageEl" style="width: 300px;margin: auto;"></div><script>function format_with_array(number) {var arr = (number + '').split('.');var int = arr[0].split('');var fraction = arr[1] || '';var r = "";var len = int.length;int.reverse().forEach(function(v, i) {if (i !== 0 && i % 3 === 0) {r = v + "," + r;} else {r = v + r;}})return r + (!!fraction ? "." + fraction : '');}</script><script>function format_with_substring(number) {var arr = (number + '').split('.');var int = arr[0] + '';var fraction = arr[1] || '';var f = int.length % 3;var r = int.substring(0, f);for (var i = 0; i < Math.floor(int.length / 3); i++) {r += ',' + int.substring(f + i * 3, f + (i + 1) * 3)}if (f === 0) {r = r.substring(1);}return r + (!!fraction ? "." + fraction : '');}</script><script>function format_with_mod(number) {var n = number;var r = "";var temp;var mod;do {mod = n % 1000;n = n / 1000;temp = ~~mod;r = (n > 1 ? `${temp}`.padStart(3, "0") : temp) + (!!r ? "," + r : "")} while (n > 1)var strNumber = number + "";var index = strNumber.indexOf(".");if (index > 0) {r += strNumber.substring(index);}return r;}</script><script>function format_with_regex(number) {var reg = /(\d{1,3})(?=(\d{3})+(?:$|\.))/g;// var reg = /(\d)(?=(?:\d{3})+$)/g//var reg = /\d{1,3}(?=(\d{3})+$)/g;return (number + '').replace(reg, '$1,');}</script><script>// function format_with_toLocaleString(number, minimumFractionDigits, maximumFractionDigits) {//     minimumFractionDigits = minimumFractionDigits || 2;//     maximumFractionDigits = (maximumFractionDigits || 2);//     maximumFractionDigits = Math.max(minimumFractionDigits, maximumFractionDigits);//     return number.toLocaleString("en-us", {//         maximumFractionDigits: maximumFractionDigits || 2,//         minimumFractionDigits: minimumFractionDigits || 2//     })// }function format_with_toLocaleString(number) {return number.toLocaleString("en-us")}</script><script>// function format_with_Intl(number, minimumFractionDigits, maximumFractionDigits) {//     minimumFractionDigits = minimumFractionDigits || 2;//     maximumFractionDigits = (maximumFractionDigits || 2);//     maximumFractionDigits = Math.max(minimumFractionDigits, maximumFractionDigits);//     return new Intl.NumberFormat('en-us', {//         maximumFractionDigits: maximumFractionDigits || 2,//         minimumFractionDigits: minimumFractionDigits || 2//     }).format(number)// }const format = new Intl.NumberFormat('en-us');function format_with_Intl(number) {return format.format(number)}</script><script>function getData(count) {var data = new Array(count).fill(0).map(function(i) {var rd = Math.random();var r = rd * Math.pow(10, Math.trunc(Math.random() * 12));if (rd > 0.5) {r = ~~r;}return r})return data;}function test(data, fn, label) {var start = performance.now();for (var i = 0; i < data.length; i++) {fn(data[i]);}var time = performance.now() - start;message((fn.name || label) + ":" + time.toFixed(2) + "ms");}function executeTest() {var data = getData(+textCount.value);test(data, format_with_array);test(data, format_with_mod);test(data, format_with_substring);test(data, format_with_regex);test(data, format_with_toLocaleString);test(data, format_with_Intl);message("-------------------")}function message(msg) {var el = document.createElement("p");el.innerHTML = msg;messageEl.appendChild(el);}</script></body></html>

三、[]+[],{}+{},[]+{},{}+[]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/467846.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++虚继承演示

在继承中如果出现&#xff1a; 这种情况&#xff0c;B和C都继承了A&#xff0c;D继承了B、C 在D中访问A的成员会出现&#xff1a; 这样的警告 是因为在继承时A出现两条分支&#xff1a;ABD、ACD 编译器不知道访问的A中的元素是经过B继承还是C继承 所以B、C在继承A时要用到…

【1】虚拟机安装

1.安装VMware WorkStation Pro VMware下载地址&#xff1a; 密钥&#xff1a;YF390-0HF8P-M81RQ-2DXQE-M2UT6 2.新建虚拟机 centos7下载地址&#xff1a;centos-7.9.2009-isos-x86_64安装包下载_开源镜像站-阿里云

【机器学习】均方误差根(RMSE:Root Mean Squared Error)

均方误差根&#xff08;Root Mean Squared Error&#xff0c;RMSE&#xff09;是机器学习和统计学中常用的误差度量指标&#xff0c;用于评估预测值与真实值之间的差异。它通常用于回归模型的评价&#xff0c;以衡量模型的预测精度。 RMSE的定义与公式 给定预测值 和实际值 …

python可视化进阶

引用&#xff1a; 首先需要安装 plotnine from plotnine import* import joypy数据可视化进阶操作 3.1 类别数据可视化 【例3-1】——绘制简单条形图 【代码框3-1】——绘制简单条形图 # 图3-1的绘制代码 import pandas as pd import matplotlib.pyplot as plt from cvxpy …

玩的花,云产品也能拼团了!!!

说起拼单大家都不陌生&#xff0c;电商一贯的营销手段&#xff0c;不过确实可以给消费者省下一笔钱。双11到了&#xff0c;腾讯云产品也玩起了拼团&#xff0c;这明显是对开发人员和各企业的福利。 对于有云产品需求的个人或企业&#xff0c;这次绝对是难得的一次薅羊毛机会。…

设计模式-七个基本原则之一-开闭原则 + SpringBoot案例

开闭原则:(SRP) 面向对象七个基本原则之一 对扩展开放&#xff1a;软件实体&#xff08;类、模块、函数等&#xff09;应该能够通过增加新功能来进行扩展。对修改关闭&#xff1a;一旦软件实体被开发完成&#xff0c;就不应该修改它的源代码。 要看实际场景&#xff0c;比如组内…

Flutter 插件 sliding_up_panel 实现从底部滑出的面板

前言 sliding_up_panel 是一个 Flutter 插件&#xff0c;用于实现从底部滑出的面板。它在设计上非常灵活&#xff0c;能够适应多种 UI 场景&#xff0c;比如从底部滑出的菜单、可拖动的弹出面板等。以下是 sliding_up_panel 的详细用法&#xff0c;包括常用的参数说明和示例代…

出海企业如何借助云计算平台实现多区域部署?

云计算de小白 如需进一步了解&#xff0c;请单击链接了解有关 Akamai 云计算的更多信息 在本文中我们将告诉大家如何在Linode云计算平台上借助VLAN快速实现多地域部署。 首先我们需要明确一些基本概念和思想&#xff1a; 部署多区域 VLAN 为了在多区域部署中在不同的 VLAN …

Linux(CentOS)安装 JDK

CentOS版本&#xff1a;CentOS 7 JDK版本&#xff1a;JDK17 1、下载 JDK 官网&#xff1a;https://www.oracle.com/ 2、上传 JDK 文件到 CentOS 使用FinalShell远程登录工具&#xff0c;并且使用 root 用户连接登录&#xff08;注意这里说的root用户连接登录是指这样的&…

多边形电子围栏算法

在日常生活工作中&#xff0c;我们经常接触到电子围栏&#xff0c;大部分的电子围栏基本上都是圆形的&#xff0c;想要知道某一个点是否在圆形区域内&#xff0c;算法很简单&#xff0c;只需要知道这个圆形区域的圆心坐标和被测点的坐标的距离是否小于半径即可。两点的距离小于…

柯桥学日语J.TEST考试是什么?J.TEST考试报名

J.TEST考试是什么&#xff1f; J.TEST全称为实用日本语鉴定考试&#xff0c;在2007年获得了国家劳动和社会保障部的认可&#xff0c;作为面对母语为非日本语的人员进行的日本语能力测试&#xff0c;J.TEST被越来越多的日本企业所认可&#xff0c;由于其对日语的实际运用能力具有…

谈谈ssh-keygen进行多host配置及使用

背景 传统的Telnet、FTP协议都是使用明文传输数据&#xff0c;存在一定的安全风险&#xff0c;如果传输数据被截取&#xff0c;可能造成数据泄露风险&#xff0c;尤其对于敏感数据&#xff0c;泄露造成的损失无法估计。最近公司、github等平台都不再支持http方式进行代码下载工…

谷粒商城-高级篇-认证服务

1、环境搭建 1、创建gulimall-auth-server模块 2、导入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schem…

独显装完ubuntu后启动黑屏显示/dev/sda:clean files blocks的解决方案

解决方案如下&#xff1a; 选中Ubuntu按E键 在编辑界面倒数第2行的linux那行&#xff08;后面有quiet splash选项&#xff09;的最后添加nomodeset 然后按F10保存重启 然后管理员权限打开/etc/modprobe.d/blacklist.conf&#xff0c;在文件末尾添加&#xff1a; blacklist…

ArcGIS 地理信息系统 任意文件读取漏洞复现

0x01 产品简介 ArcGIS是由美国Esri公司研发的地理信息系统(GIS)软件,它整合了数据库、软件工程、人工智能、网络技术、云计算等主流的IT技术,旨在为用户提供一套完整的、开放的企业级GIS解决方案,它包含了一套带有用户界面组件的Windows桌面应用。可以实现从简单到复杂的…

Linux 系统结构

Linux系统一般有4个主要部分&#xff1a;内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构&#xff0c;它们使得用户可以运行程序、管理文件并使用系统。 1. linux内核 内核是操作系统的核心&#xff0c;具有很多最基本功能&#xff0c;它…

SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”

SLF4J常见问题 1、SLF4J简介2、SLF4J实现原理3、SLF4J常见问题 1、SLF4J简介 SLF4J&#xff08;Simple Logging Facade for Java&#xff09;是一个为Java程序提供日志输出的统一接口&#xff0c;并不具备具体的日志实现方案&#xff0c;类似JDBC&#xff0c;SLF4J只做两件事&a…

使用ThorUi

摘要&#xff1a; 官网 今天遇到一个老项目&#xff0c;使用的是ThorUi组件库&#xff01;之前没有用过这组件库&#xff0c;所以记录一下不同框架是使用情况&#xff01; ThorUI 是一个基于 Thorium 的 UI 框架&#xff0c;用于构建跨平台的桌面应用程序。如果你打算使用 Thor…

OceanBase中,如何解读 obdiag 收集的火焰图 【DBA早下班系列】

1. 前言 在之前的文章 遇到性能问题&#xff0c;如何给OceanBase“拍CT“&#xff08;火焰图与扁鹊图&#xff09;中&#xff0c;分享了obdiag 快速收集火焰图的方法&#xff0c;那么&#xff0c;紧接着的问题便是&#xff1a;收集到火焰图和扁鹊图之后&#xff0c;该如何解读…

Day41 | 动态规划 :完全背包应用 完全平方数单词拆分(类比爬楼梯)

Day41 | 动态规划 &#xff1a;完全背包应用 完全平方数&&单词拆分&#xff08;类比爬楼梯&#xff09; 动态规划应该如何学习&#xff1f;-CSDN博客 01背包模板 | 学习总结-CSDN博客 完全背包模板总结-CSDN博客 难点&#xff1a; 代码都不难写&#xff0c;如何想…