JavaScript面试题汇总:高频考点与答案解析
在前端开发领域,JavaScript作为核心语言,其面试题覆盖了从基础语法到高级特性的广泛范围。本文ZHANID工具网将系统梳理JavaScript高频面试考点,结合权威资料与典型案例,为开发者提供清晰的解题思路与知识框架。
一、数据类型与类型检测
1. 数据类型分类
JavaScript包含7种原始类型和1种引用类型:
原始类型:
string、number、boolean、null、undefined、symbol(ES6新增,唯一标识符)、bigint(ES2020新增,大整数)。引用类型:
object(包括array、function、date、regexp等)。
示例:
typeof"hello";//"string" typeofnull;//"object"(历史遗留问题) typeofSymbol();//"symbol"
2. 类型检测方法
| 方法 | 特点 | 示例 |
|---|---|---|
typeof |
返回数据类型的字符串表示,但对null和引用类型区分有限 | typeof [] → "object" |
instanceof | 检测对象是否为某构造函数的实例,仅适用于引用类型 | [] instanceof Array → true |
Object.prototype.toString.call() |
精确判断所有类型,返回[object Type]格式字符串 | Object.prototype.toString.call(42) → "[object Number]" |
示例:
//判断数组类型 constisArray=(arr)=>Object.prototype.toString.call(arr)==='[objectArray]'; isArray([]);//true
二、变量提升与作用域
1. 变量提升机制
var:声明提升至作用域顶部,初始值为undefined。let/const:存在暂时性死区(TDZ),未初始化前访问会报错。
示例:
console.log(a);//undefined(var提升) vara=1; console.log(b);//ReferenceError(let未初始化) letb=2;
2. 作用域链
JavaScript通过词法作用域查找变量,从当前作用域逐级向上查找至全局作用域。
示例:
functionouter(){
constouterVar='outer';
functioninner(){
console.log(outerVar);//访问外部作用域变量
}
inner();
}
outer();//"outer"三、闭包与高阶函数
1. 闭包的定义与应用
闭包是函数与其词法环境的组合,常用于数据封装、模块化及回调函数。
示例:
functioncreateCounter(){
letcount=0;
returnfunction(){
count++;
returncount;
};
}
constcounter=createCounter();
counter();//1
counter();//22. 高阶函数
高阶函数是接收函数作为参数或返回函数的函数,典型应用包括柯里化、防抖与节流。
柯里化(Currying)
将多参数函数转换为单参数函数序列。
functioncurryAdd(a){
returnfunction(b){
returna+b;
};
}
constadd5=curryAdd(5);
add5(3);//8防抖(Debounce)
事件触发后延迟执行,避免重复触发。
functiondebounce(fn,delay){
lettimer;
returnfunction(...args){
clearTimeout(timer);
timer=setTimeout(()=>fn.apply(this,args),delay);
};
}节流(Throttle)
限制事件在一定时间内仅触发一次。
functionthrottle(fn,delay){
letlast=0;
returnfunction(...args){
constnow=Date.now();
if(now-last>delay){
fn.apply(this,args);
last=now;
}
};
}四、原型与继承
1. 原型链机制
每个对象都有__proto__属性指向其构造函数的prototype,形成原型链。
示例:
functionPerson(name){
this.name=name;
}
Person.prototype.sayHello=function(){
console.log(`Hello,${this.name}`);
};
constp=newPerson('Alice');
p.sayHello();//"Hello,Alice"2. 继承实现方式
| 方式 | 特点 |
|---|---|
| 原型链继承 | 子类原型指向父类实例,共享父类引用属性 |
| 构造函数继承 |
父类构造函数通过call/apply调用,避免引用共享但无法继承原型方法 |
| 组合继承 | 结合原型链与构造函数继承,解决引用共享问题 |
| ES6类继承 |
使用class与extends语法糖,底层仍为原型链 |
示例(ES6类继承):
classParent{
constructor(name){
this.name=name;
}
sayHello(){
console.log(`Hello,${this.name}`);
}
}
classChildextendsParent{
constructor(name,age){
super(name);
this.age=age;
}
}
constc=newChild('Bob',18);
c.sayHello();//"Hello,Bob"五、异步编程
1. 事件循环(Event Loop)
JavaScript为单线程语言,通过任务队列处理异步任务:
宏任务:
script、setTimeout、setInterval、I/O。微任务:
Promise.then、MutationObserver。
执行顺序:
宏任务 → 微任务 → 渲染 → 宏任务 → ...
示例:
console.log('1');//同步任务
setTimeout(()=>console.log('2'),0);//宏任务
Promise.resolve().then(()=>console.log('3'));//微任务
//输出:1→3→22. Promise与Async/Await
Promise:解决回调地狱,支持链式调用。
Async/Await:基于Promise的语法糖,使异步代码更接近同步风格。
示例:
functionfetchData(){
returnnewPromise((resolve)=>{
setTimeout(()=>resolve('Data'),1000);
});
}
asyncfunctiongetData(){
console.log('Start');
constdata=awaitfetchData();
console.log(data);//"Data"
}
getData();六、数组与对象操作
1. 数组去重
| 方法 | 特点 |
|---|---|
Set |
利用Set数据结构的唯一性 |
filter+indexOf | 遍历数组并过滤重复项 |
reduce | 递归累积唯一值 |
示例:
//Set去重 constarr=[1,2,2,3]; constuniqueArr=[...newSet(arr)];//[1,2,3]
2. 深拷贝与浅拷贝
| 方法 | 特点 |
|---|---|
| 浅拷贝 |
仅复制第一层属性(如Object.assign、展开运算符...) |
| 深拷贝 |
递归复制所有层级(如JSON.parse(JSON.stringify(obj))、structuredClone) |
示例:
//深拷贝(兼容性方案)
functiondeepClone(obj){
if(obj===null||typeofobj!=='object')returnobj;
constclone=Array.isArray(obj)?[]:{};
for(constkeyinobj){
clone[key]=deepClone(obj[key]);
}
returnclone;
}七、性能优化与内存管理
1. 内存泄漏常见原因
意外全局变量:未声明的变量自动挂载至
window。闭包引用:闭包中未释放的外部变量。
未清理的定时器/事件监听:如
setInterval未调用clearInterval。
示例:
//内存泄漏示例
functionleak(){
constdata=newArray(1e6).fill('data');//大数组
returnfunction(){
console.log(data[0]);//闭包引用data
};
}
constleakFunc=leak();
//leakFunc未被释放时,data无法被垃圾回收2. 垃圾回收机制
JavaScript采用标记-清除算法,通过标记不可达对象并回收其内存。开发者需避免手动管理内存,但需注意减少不必要的引用。
八、浏览器兼容性与安全
1. 跨域解决方案
| 方案 | 适用场景 |
|---|---|
| CORS |
服务端设置Access-Control-Allow-Origin响应头 |
| JSONP |
仅支持GET请求,利用标签无跨域限制 |
| Nginx反向代理 | 通过代理服务器转发请求,隐藏真实域名 |
示例(CORS):
//服务端设置响应头
res.setHeader('Access-Control-Allow-Origin','*');
res.setHeader('Access-Control-Allow-Methods','GET,POST');2. XSS攻击防御
输入过滤:对用户输入进行转义或过滤。
CSP策略:通过
Content-Security-Policy限制资源加载来源。
示例:
九、模块化与ES6特性
1. ES Modules
导出:
export、export default。导入:
import、import * as。
示例:
//math.js
exportconstadd=(a,b)=>a+b;
exportdefaultfunctionmultiply(a,b){returna*b;};
//main.js
import{add}from'./math.js';
importmultiplyfrom'./math.js';2. Symbol与BigInt
Symbol:唯一标识符,避免属性名冲突。
BigInt:表示大整数,解决
Number精度限制。
示例:
constid=Symbol('id');
constbigNum=9007199254740991n;//BigInt字面量十、综合案例解析
案例1:实现一个事件委托函数
functioneventDelegate(parent,selector,eventType,handler){
parent.addEventListener(eventType,(e)=>{
lettarget=e.target;
while(target!==parent){
if(target.matches(selector)){
handler.call(target,e);
break;
}
target=target.parentNode;
}
});
}
//使用示例
document.querySelector('ul').addEventListener('click',(e)=>{
if(e.target.tagName==='LI'){
console.log('Clicked:',e.target.textContent);
}
});案例2:实现一个Promise.all
functionpromiseAll(promises){
returnnewPromise((resolve,reject)=>{
constresults=[];
letcompleted=0;
promises.forEach((promise,index)=>{
Promise.resolve(promise)
.then((value)=>{
results[index]=value;
completed++;
if(completed===promises.length)resolve(results);
})
.catch(reject);
});
});
}总结
JavaScript面试题覆盖了语言核心特性、异步编程、浏览器机制及性能优化等多个维度。开发者需深入理解数据类型、作用域、原型链、异步模型等基础概念,同时掌握闭包、高阶函数、模块化等高级特性。通过系统梳理高频考点与典型案例,可显著提升面试通过率与代码质量。
推荐阅读
-
JAVA实现HTML转PDF的五种方法详解
-
MySQL创建和删除索引命令CREATE/DROP INDEX使用方法详解
-
深入理解 JavaScript 原型和构造函数创建对象的机制
-
ZooKeeper和Eureka有什么区别?注册中心如何选择?
-
ZooKeeper是什么?分布式系统开发者必读入门指南
-
JavaScript防抖与节流函数怎么写?高频事件优化技巧详解
-
c++中sprintf函数使用方法及示例代码详解
在C++编程中,格式化输出是常见的需求。虽然cout提供了基本的输出功能,但在需要精确控制输出格式(如指定宽度、精度、进制等)...
-
Swagger 接口注解详解教程:@Api、@ApiOperation、@ApiModelProperty 全解析
-
Python变量命名规则全解析:打造规范、可读性强的代码风格
-
OpenSSL是什么?OpenSSL使用方法详解

