导图社区 前端面试 JavaScript篇
这是一篇关于前端面试 JavaScript篇的思维导图,主要内容包括:一、数据类型,ES6,三、JavaScript基础,原型与原型链,this/call/apply/bind,Promise,arguments参数。
编辑于2025-05-10 13:10:07前端面试 JavaScript篇
一、数据类型
JavaScript有哪些数据类型,它们的区别
八种数据类型
Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt
Symbol
代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题
BigInt
是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围
原始数据类型和引用数据类型
原始数据类型
在栈上
Undefined、Null、Boolean、Number、String
引用数据类型
在堆上
对象、数组和函数
数据类型检测的方式有哪些
typeof
数组、对象、null都会被判断为object
instanceof
instanceof可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型
因为2没有原型链,所以是false
判断数组的方式有哪些
通过Object.prototype.toString.call()做判断
通过原型链做判断
obj.__proto__ === Array.prototype
通过ES6的Array.isArray()做判断
Array.isArrray(obj)
通过instanceof做判断
obj instanceof Array
null和undefined区别
Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null
使用 undefined 来作为一个变量名
这样的做法是非常危险的,它会影响对 undefined 值的判断。我们可以通过一些方法获得安全的 undefined 值,比如说 void 0
使用typeof
Null 类型化会返回 “object”,这是一个历史遗留的问题
当使用双等号对两种类型的值进行比较时会返回 true,使用三个等号时会返回 false
typeof null 的结果是什么,为什么
typeof null 的结果是Object
intanceof 操作符的实现原理及实现
instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置
typeof NaN 的结果是什么
NAN含义
NaN 指“不是一个数字”(not a number),NaN 是一个“警戒值”(sentinel value,有特殊用途的常规值),用于指出数字类型中的错误情况,即“执行数学运算没有成功,这是失败后返回的结果”
typeof NaN; // "number"
isNaN 和 Number.isNaN 函数的区别
函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断
函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确
== 操作符的强制类型转换规则
对于 == 来说,如果对比双方的类型不一样,就会进行类型转换
假如对比 x 和 y 是否相同,就会进行如下判断流程
首先会判断两者类型是否相同,相同的话就比较两者的大小
类型不相同的话,就会进行类型转换
会先判断是否在对比 null 和 undefined,是的话就会返回 true
判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number
判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断
看来是优先转化为数字
重要:判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断
'1' == { name: 'js' } ↓ '1' == '[object Object]'
自定义toString
注意必须是原型链上的toString才行
==操作符比较对象/数组
两边都是对象
判断引用地址是否相同
例1
例2
两边都是数组
和两边都是对象一样
注意和===关系
对于数组和对象,使用===是一样的,都是比较引用
其他值到字符串的转换规则
Null 和 Undefined 类型 ,null 转换为 "null",undefined 转换为 "undefined"
Boolean 类型,true 转换为 "true",false 转换为 "false"
Number 类型的值直接转换,不过那些极小和极大的数字会使用指数形式
Symbol 类型的值直接转换,但是只允许显式强制类型转换,使用隐式强制类型转换会产生错误
对普通对象来说,除非自行定义 toString() 方法,否则会调用 toString()(Object.prototype.toString())来返回内部属性 [[Class]] 的值
如"[object Object]"。如果对象有自己的 toString() 方法,字符串化时就会调用该方法并使用其返回值
function调用tostring返回自己内容
其他值到数字值的转换规则
Undefined 类型的值转换为 NaN
Null 类型的值转换为 0
Boolean 类型的值,true 转换为 1,false 转换为 0
String 类型的值转换如同使用 Number() 函数进行转换,如果包含非数字值则转换为 NaN,空字符串为 0
Symbol 类型的值不能转换为数字,会报错
对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字
其他值到布尔类型的值的转换规则
假值的布尔强制类型转换结果为 false。从逻辑上说,假值列表以外的都应该是真值
假值类型
undefined null false +0、-0 和 NaN ""
Object.is() 与比较操作符 “===”、“==” 的区别
使用双等号(==)进行相等判断时,如果两边的类型不一致,则会进行强制类型转化后再进行比较
使用三等号(===)进行相等判断时,如果两边的类型不一致时,不会做强制类型准换,直接返回 false
使用 Object.is 来进行相等判断时,一般情况下和三等号的判断相同
它处理了一些特殊的情况,比如 -0 和 +0 不再相等,两个 NaN 是相等的
什么是 JavaScript 中的包装类型
概念
在 JavaScript 中,基本类型是没有属性和方法的,但是为了便于操作基本类型的值,在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象
例子
原理
在访问 'abc'.length时,JavaScript 将 'abc'在后台转换成 String('abc'),然后再访问其 length属性
object.assign和扩展运算法是深拷贝还是浅拷贝,两者区别
assign
ES6
let、const、var的区别
块级作用域
let和const具有块级作用域
var不存在块级作用域
块级作用域概念
放if里面以后外面不能访问到
例子
反例
块级作用域解决了ES5中的两个问题
内层变量可能覆盖外层变量
用来计数的循环变量泄露为全局变量
变量提升
var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错
变量提升例子
变量提升与函数声明的对比
foo 是一个函数声明,它的声明和定义都会被提升到作用域的顶部,因此可以在声明之前调用
给全局添加属性
浏览器的全局对象
window
Node的全局对象
global
var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会
重复声明
var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量
const对象的属性可以修改吗
const保证的并不是变量的值不能改动,而是变量指向的那个内存地址不能改动
const为基本数据类型
其值就保存在变量指向的那个内存地址,因此等同于常量
const为引用类型的数据
变量指向数据的内存地址,保存的只是一个指针,const只能保证这个指针是固定不变的,至于它指向的数据结构是不是可变的,就完全不能控制了
如果new一个箭头函数的会怎么样
箭头函数是ES6中的提出来的,它没有prototype,也没有自己的this指向,更不可以使用arguments参数,所以不能New一个箭头函数
new操作符的实现步骤
创建一个对象
将构造函数的作用域赋给新对象(也就是将对象的__proto__属性指向构造函数的prototype属性)
指向构造函数中的代码,构造函数中的this指向该对象(也就是为这个对象添加属性和方法)
返回新的对象
箭头函数的this指向哪⾥
箭头函数并没有属于⾃⼰的this,它所谓的this是捕获其所在上下⽂的 this 值,作为⾃⼰的 this 值
扩展运算符的作用及使用场景
基本作用
对象的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
例子
等价写法
将字符串转为真正的数组
Proxy 可以实现什么功能
例子
参数作用
target 代表需要添加代理的对象
handler 用来自定义对象中的操作,比如可以用来自定义 set 或者 get 函数
如何提取高度嵌套的对象里的指定属性
例子
提取方法
三、JavaScript基础
Map用法
和Object区别
普通的Object中的键值对中的键只能是字符串。而ES6提供的Map数据结构类似于对象,但是它的键不限制范围,可以是任意类型,是一种更加完善的Hash结构
新建方法
基本api
size: map.size 返回Map结构的成员总数
set(key,value):设置键名key对应的键值value
返回值
然后返回整个Map结构
get(key):该方法读取key对应的键值,如果找不到key,返回undefined
has(key):该方法返回一个布尔值,表示某个键是否在当前Map对象中
delete(key):该方法删除某个键,返回true,如果删除失败,返回false
clear():map.clear()清除所有成员,没有返回值
常用方法
什么是 DOM 和 BOM
DOM 指的是文档对象模型,它指的是把文档当做一个对象,这个对象主要定义了处理网页内容的方法和接口
BOM
BOM 指的是浏览器对象模型,它指的是把浏览器当做一个对象来对待,这个对象主要定义了与浏览器进行交互的法和接口
BOM的核心是 window,而 window 对象具有双重角色,它既是通过 js 访问浏览器窗口的一个接口,又是一个 Global(全局)对象。
DOM 的最根本的对象 document 对象也是 BOM 的 window 对象的子对象
ES6模块与CommonJS模块有什么异同
区别
CommonJS是对模块的浅拷⻉,ES6 Module是对模块的引⽤,即ES6 Module只存只读,不能改变其值,也就是指针指向不能变,类似const
import的接⼝是read-only(只读状态),不能修改其变量值。 即不能修改其变量的指针指向,但可以改变变量内部指针指向
可以对commonJS对重新赋值(改变指针指向),但是对ES6 Module赋值会编译报错
例子
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用
共同点
CommonJS和ES6 Module都可以对引⼊的对象进⾏赋值,即对对象内部属性的值进⾏改变
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
例子理解
运行时加载
就是说require的时候资源才被加载进来
CommonJs 是单个值导出,ES6 Module可以导出多个
CommonJs 是动态语法可以写在判断里,ES6 Module 静态语法只能写在顶层
CommonJs 的 this 是当前模块,ES6 Module的 this 是 undefined
Commonjs特点
对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值
对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此对该模块的值做修改时会影响另一个模块
当使用require命令加载某个模块时,就会运行整个模块的代码
当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。
也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存
子主题
ES6模块特点
ES6模块中的值属于【动态只读引用】
对于只读来说,即不允许修改引入变量的值,import的变量是只读的,不论是基本数据类型还是复杂数据类型
for...in和for...of的区别
for…of 遍历获取的是对象的键值,for…in 获取的是对象的键名
for… in 会遍历对象的整个原型链,性能非常差不推荐使用,而 for … of 只遍历当前对象不会遍历原型链
对于数组的遍历,for…in 会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for…of 只返回数组的下标对应的属性值
原型与原型链
如何获得对象非原型链上的属性
hasOwnProperty
示例
this/call/apply/bind
对this对象的理解
this 是执行上下文中的一个属性,它指向最后一次调用这个方法的对象
this 的指向可以通过四种调用模式来判断
函数调用模式
当一个函数不是一个对象的属性时,直接作为函数来调用时,this 指向全局对象
例子
方法调用模式
如果一个函数作为一个对象的方法来调用时,this 指向这个对象
构造器调用模式
如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象
apply 、 call 和 bind 调用模式
这三个方法都可以显示的指定调用函数的 this 指向
四种调用优先级
使用构造器调用模式的优先级最高,然后是 apply、call 和 bind 调用模式,然后是方法调用模式,然后是函数调用模式
Promise
Promise的基本用法
创建Promise对象
简单方式
Promise.resolve
Promise方法
then
then里面可以自动接收正确或者错误
示例
then的返回值
return "xxx"等效于放入resolve
arguments参数
转化为数组