前端面试——JavaScript面经(持续更新)
一、数据类型
1. JavaScript用哪些数据类型、它们有什么区别?
JavaScript共有八种数据类型,分别包括5种基本数据类型和3种非基本数据类型。
- 基本数据类型:
Undefined
、Null
、Boolean
、Number
、String
。 - 非基本数据类型:
Object
、Symbol
、BigInt
。
其中Symbol
和BigInt
是ES6新增的数据类型:
Symbol
代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。BigInt
是一种数字类型的数据,它可以表示任意精度格式的整数,使用BigInt
可以安全地存储和大整数,即使这个数超出了Number的安全整数范围。
区别一:分为原始数据类型和引用数据类型。
- 原始数据类型:
Undefined
、Null
、Boolean
、Number
、String
。 - 引用数据类型:
Object
。另外还有数组Array
和函数Function
。
区别二:存储位置不同。
- 原始数据类型直接存储在**栈(stack)**中,往往占据空间小、大小固定、属于被频繁使用数据,所以放在栈中。
- 引用数据类型存储在**堆(heap)**中,往往占据空间大、大小不固定,如果存在栈中将会影响程序运行的性能。因此,引用数据类型在栈中存储了指针,指针指向堆中该实体的起始地址。当解释器寻找引用值时,会先检索其在栈中的地址,再根据地址从堆中获得实体。
扩展知识:堆与栈
堆和栈的概念存在于数据结构和操作系统内存中。
- 在数据结构中:
- 栈:先进后出
- 堆:先进先出
- 在操作系统中分为堆区和栈区:
- 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。操作方式类似于数据结构中的栈。
- 堆区内存一般由开发者分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
2. 数据类型的检测方式有哪些?详细讲讲
2.1 typeof
// 1.typeof 数组、对象和null都会被视为object 其他类型都判定正确
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof null); // object
console.log(typeof function () {}); // function
console.log(typeof 1); // number
console.log(typeof true); // boolean
console.log(typeof "str"); // string
console.log(typeof undefined); // undefined
console.log(typeof Symbol()); // symbol
console.log(typeof NaN) // number
根据上面的结果可以看到数组、对象和null都会被视为object,其他类型都能判定正确。
2.2 instanceof
它的原理是:判断在其原型链中能否找到该类型的原型
console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log("str" instanceof String); // falseconsole.log([] instanceof Array); // true
console.log(function () {} instanceof Function); // true
console.log({} instanceof Object); // true
console.log(null instanceof Object); // false 这是因为null是原型链的尽头 它没有后续原型链 更不可能找到Object类型的原型
根据上面的结果可以看到 instanceof只能正确判断引用类型,基本数据类型无法判定。
需要注意的是:null instanceof Object结果是false
,因为null是原型链的尽头,它没有后续原型链,更不可能找到Object类型的原型。
2.3 constructor
它的原理是:**除了null之外,任何对象都会在其prototype
/__proto__
上有一个constructor
属性,而constructor属性返回一个引用,这个引用指向创建该对象的构造函数,而Number
、Boolean
、String
、Array
都属于构造函数。**因此通过construct和构造函数就能判断类型是否符合。
console.log((2).constructor); // ƒ Number() { [native code] } Number构造函数
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(("str").constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function () {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
// console.log((null).constructor === Object); // 会报错 原因是null不存在constructor
// console.log((undefined).constructor === Object); // 会报错 原因是undefined不存在constructor
// console.log((null).constructor); // 会报错
// console.log((undefined).constructor); // 会报错
从上面的结果看到,constructor
除了不能判断null
和undefined
外,其它类型都能判断。
需要注意的是,如果创建的对象的原型被改变了,constructor
就不能用来判断数据类型了。
function Fn() {}
console.log(Fn.prototype.constructor); // f Fn() {}
Fn.prototype = new Array()
console.log(Fn.prototype.constructor); // ƒ Array() { [native code] }
let f = new Fn();
console.log(f.constructor); // ƒ Array() { [native code] }
console.log(f.__proto__); // ƒ Array() { [native code] }
console.log(f.constructor === Fn); // false
console.log(f.constructor === Array); // true
扩展知识:constructor
的两个作用:
- 判断数据类型。
- 对象实例通过construct对象访问它的构造函数。
2.4 Object.prototype.toString.call()
它的原理是:对象原型上的toString
方法会获取当前对象的类型然后返回[object Type]
字符串,由于部分内置对象对toString
重写了,因此需要调用.call()
来利用原本的toString
函数,.call(args)
方法实现让调用call
方法的对象的this
指向传的参数args
。
let a = Object.prototype.toString;
console.log(a.call(2)); // [object Number]
console.log(a.call(2) == Number); // false
console.log(a.call(2) == "[object Number]"); // trueconsole.log(a.call(true)); // [object Boolean]
console.log(a.call(true) == Boolean); // false
console.log(a.call(true) == "[object Boolean]"); // trueconsole.log(a.call("str")); // [object String]
console.log(a.call("str") == String); // false
console.log(a.call("str") == "[object String]"); // trueconsole.log(a.call(new Date())); // [object Date]
console.log(a.call(new Date()) == Date); // false
console.log(a.call(new Date()) == "[object Date]"); // trueconsole.log(a.call([])); // [object Array]
console.log(a.call(function () {})); // [object function]
console.log(a.call({})); // [object Object]
console.log(a.call(undefined)); // [object undefined]
console.log(a.call(null)); // [object Null]
通过上面代码可以看到,Object.prototype.toString.call()
可以验证任何类型。
2.5 封装一个类型验证的方法
大型项目中往往会使用Object.prototype.toString.call()
封装一个isType
方法来验证类型,封装代码如下:
function isType(data, type) {const typeObj = {"[object String]": "string","[object Number]": "number","[object Boolean]": "boolean","[object Null]": "null","[object Undefined]": "undefined","[object Object]": "object","[object Array]": "array","[object Function]": "function","[object Date]": "date", // Object.prototype.toString.call(new Date())"[object RegExp]": "regExp","[object Map]": "map","[object Set]": "set","[object HTMLDivElement]": "dom", // document.querySelector('#app')"[object WeakMap]": "weakMap","[object Window]": "window", // Object.prototype.toString.call(window)"[object Error]": "error", // new Error('1')"[object Arguments]": "arguments",};let name = Object.prototype.toString.call(data); // 借用Object.prototype.toString()获取数据类型let typeName = typeObj[name] || "未知类型"; // 匹配数据类型return typeName === type; // 判断该数据类型是否为传入的类型
}
下面我们可以测试一下封装结果:
console.log(isType({}, "object"), // trueisType([], "array"), // trueisType(new Date(), "object"), // falseisType(new Date(), "date") // true
);
2.6 总结
方法名 | 效果 |
---|---|
typeof | 数组、对象和null 都会被视为object ,其他类型都能判定正确 |
instanceof | 只能正确判断引用类型,基本数据类型无法判定 |
constructor | 除了不能判断null 和undefined 外,其它类型都能判断 |
Object.prototype.toString.call() | 可以判断所有类型,但是返回结果是字符串【最推荐,封装isType 】 |
3. 判断数组的方式有哪些?
let arr = []
Object.prototype.toString.call(arr).slice(8,-1) === 'Array'
或者Object.protoType.toString.call(arr) === '[object Array]'
- 通过原型链判断:
arr.__proto__ === Array.prototype
- 通过
Array.isArray(arr)
- 通过
arr instanceof Array
4. null、undefined、Null有什么区别?
- 含义不同:
undefined
代表的含义是未定义,而null
代表的含义是空对象,NaN
表示不是一个数字,用于指出数字类型中的错误情况,通过执行数学运算没有成功时返回NaN
。。 - 初始化场景不同:通常变量声明了但还没有定义的时候使用
undefined
,null
主要用在初始化一些可能会返回对象的变量,NaN
不用于初始化。 - typeof判断结果不同:
typeof undefined
返回undefined
,typeof null
返回object
,typeof NaN
返回number
。
一般变量声明了但还没定义的时候会返回undefined
。
需要注意的是:
-
使用
null == undefined
返回true
,null === undefined
返回false
。 -
NaN
与自身不相等,NaN == NaN
和NaN === NaN
得到的结果都是false
。
5. 为什么0.1+0.2 !== 0.3,怎么才能让它们相等
大白话:
首先:因此js将数据转为二进制后处理数据【要点一】,0.1
转化为二进制为:0.0001 1001 1001 1001无限循环..
,0.2转化为二进制为:0.001 1001 1001 1001(无限循环)
。
又因为js的Number类型遵循IEEE754标准64位存储【要点二】,IEEE754标准64位内只有52位来表示小数,有很多小数转为二进制后存储无限位数,如果第53位为1的话,只保留52为就会进位【要点三】,从而导致精度丢失【第一次精度丢失】。
而后进行二进制相加的时候,也可能会存在进位的问题,进而导致精度丢失【第二次精度丢失】,最后相加得到的二进制结果转化为数字就会与我们平常相加得到的结果有偏差。
解决方法:
-
将两数转换为整数,在相加后转回小数
let x = (0.1 * 10 + 0.2 * 10) / 10 console.log(x === 0.3) // true
-
使用toFixed方法配合parseFloat方法
console.log(parseFloat((0.1 + 0.2).toFixed(1)) === 0.3) // true
-
根据真实结果减去预测结果是否小于
Number.EPSILON
在ES6中,提供了
Number.EPSILON
属性,它的值为2^-52
。console.log((0.1 + 0.2) - 0.3 < Number.EPSILON) // true
下面详细讲讲:
Number类型遵循的IEEE754 64位标准,也就是双精度浮点数(double)存储,它为每个数值分配64位存储空间,以科学计数法的方式存储。64位分配如下:1位符号位,11位指数位,剩余52位为小数位。
这里以0.1为例:
6. == 操作符的强制转换规则是怎么样的?
==
在比对双方类型不一样时,会进行类型转换。
其中包括:
- string转为number
- boolean转为number
- object转为字符串
[object Object]
判断流程如下:
- 先判断两者类型是否相同,同则比较大小
- 不同进行类型转换
- 先判断是否在比对
null
和undefined
,是的话返回true
- 接着按上述三个点的顺序类型转化
相关文章:

前端面试——JavaScript面经(持续更新)
一、数据类型 1. JavaScript用哪些数据类型、它们有什么区别? JavaScript共有八种数据类型,分别包括5种基本数据类型和3种非基本数据类型。 基本数据类型:Undefined、Null、Boolean、Number、String。非基本数据类型:Object、S…...

微前端——无界wujie
B站课程视频 课程视频 课程课件笔记: 1.微前端 2.无界 现有的微前端框架:iframe、qiankun、Micro-app(京东)、EMP(百度)、无届 前置 初始化 新建一个文件夹 1.通过npm i typescript -g安装ts 2.然后可…...

连锁便利店管理系统有什么用
连锁便利店管理系统对于连锁便利店的运营和管理非常有用。以下是一些常见的用途: 1. 库存管理:连锁便利店通常需要管理多个门店的库存,管理系统可以帮助实时掌握各个门店的库存情况,包括商品数量、进货记录、库存调拨等。这样可以…...

Vue 的两种实现:VSCode 中配置 vue 模板快捷方式的过程
1、创建配置文件: 其一、打开 VSCode ,CtrlShiftP, 打开搜索框: 其二、输入:user, 并点击进去 Snippets:Configure User Snippets 其三、输入 vue3js 并回车: 其四、打开项目,发现配置文件 vue3js.code-sn…...
electron 切换至esm
前言 好消息,经过不知道多少年的讨论。 electron28.0.0开始(23.08.31),默认支持esm了。 see https://github.com/electron/electron/issues/21457 使用方法 升级至electron^28.0.0简单地在package.json中添加"type":…...

【新版】软考 - 系统架构设计师(总结笔记)
个人总结学习笔记,仅供参考!!!! →点击 笔者主页,欢迎关注哦(互相学习,共同成长) 笔记目录 📢【系统架构设计系列】系统架构设计专业技能 计算机组成与结构操作系统信…...
Spring MVC 方法中添加参数、HttpServletRequest 和 HttpServletResponse 对象
在这个例子中,我们添加了 HttpServletRequest 和 HttpServletResponse 对象作为控制器方法的参数。这样,你就可以在方法内部同时访问请求参数、请求对象和响应对象,从而进行更灵活的 HTTP 请求和响应处理。 RestController public class MyC…...

单片机的RTC获取网络时间
理解网络同步校准RTC的原理需要考虑NTP、SNTP、RTC这三个关键组件的作用和交互。下面详细解释这个过程: 1. NTP(Network Time Protocol): 协议目的:NTP是用于同步计算机和设备时钟的协议。它通过在网络上与时间服务器通…...
Android 13 内置可卸载的搜狗输入法
环境 系统:Android 13 芯片厂商:展锐 需求 默认只有英文输入法,没有中文,需要中文输入法,且可以卸载的。 实测为搜狗输入法,百度等其它输入法也同样适用。 实现 在SDK目录中创建packages/apps/SogouIM…...

持续集成交付CICD:GitLabCI 封装Python类 并结合 ArgoCD 完成前端项目应用发布
目录 一、实验 1. 环境 2. Python代码实现获取文件 3.Python代码实现创建文件 4.Python代码实现更新文件 5.GitLab更新库文件与运行流水线 6.ArgoCD 完成前端项目应用发布 二、问题 1.Python获取GitLab指定仓库文件报错 2. K8S master节点运行Python代码报错 一、实验…...

第十三章 常用类(Math 类、Arrays 类、System类、Biglnteger 和BigDecimal 类、日期类)
一、Math 类(P481) Math 类包含,用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。 (1)abs:绝对值 (2)pow:求幂 (3)c…...

2023年12月24日学习总结
今日to do list: 做kaggle上面的流量预测项目☠️ 学习时不刷手机🤡 okkkkkkkkkkkkkk 开始👍🍎 0、我在干什么? 我在预测一个名字叫做elborn基站的下行链路流量,用过去29天的数据预测未来10天的数据 1、…...

第26关 K8s日志收集揭秘:利用Log-pilot收集POD内业务日志文件
------> 课程视频同步分享在今日头条和B站 大家好,我是博哥爱运维。 OK,到目前为止,我们的服务顺利容器化并上了K8s,同时也能通过外部网络进行请求访问,相关的服务数据也能进行持久化存储了,那么接下来…...
芯科科技以卓越的企业发展和杰出的产品创新获得多项殊荣
2023年共获颁全球及囯內近20个行业奖项 Silicon Labs(亦称“芯科科技”)日前在全球半导体联盟(Global Semiconductor Alliance,GSA)举行的颁奖典礼上,再次荣获最受尊敬上市半导体企业奖,这是公…...

计算机视觉基础(11)——语义分割和实例分割
前言 在这节课,我们将学习语义分割和实例分割。在语义分割中,我们需要重点掌握语义分割的概念、常用数据集、评价指标(IoU)以及经典的语义分割方法(Deeplab系列);在实例分割中,需要知…...
CNAS中兴新支点——什么是软件压力测试?软件压力测试工具和流程
一、含义:软件压力测试是一种测试应用程序性能的方法,通过模拟大量用户并发访问,测试应用程序在压力情况下的表现和响应能力。软件压力测试的目的是发现系统潜在的问题,如内存泄漏、线程锁、资源泄漏等,以及在高峰期或…...

jQuery: 整理3---操作元素的内容
1.html("内容") ->设置元素的内容,包含html标签(非表单元素) <div id"html1"></div><div id"html2"></div>$("#html1").html("<h2>上海</h2>") …...
22、商城系统(四):项目jar包配置(重要),网关配置,商品服务基础数据设置
目录 0.重要:整个项目的配置 最外层的pom.xml renren-fast renren-generator xpmall-common xpmall-coupon...
循环链表的学习以及问题汇总
[TOC](循环链表常见的问题) # 问题一: **报错**  **报错原因:**因为没有提前对_tag_CircleListNode重命名为CircleListNode,所以,在定义…...
C++期末复习总结继承
继承是软件复用的一种形式,他是在现有类的基础上建立新类,新类继承了现有类的属性和方法,并且还拥有了其特有的属性和方法,继承的过程称为派生,新建的类称为派生类(子类),原有的成为…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...