在前端开发领域,JavaScript作为核心语言,其面试题覆盖了从基础语法到高级特性的广泛范围。本文ZHANID工具网将系统梳理JavaScript高频面试考点,结合权威资料与典型案例,为开发者提供清晰的解题思路与知识框架。
一、数据类型与类型检测
1. 数据类型分类
JavaScript包含7种原始类型和1种引用类型:
原始类型:
string、number、boolean、null、undefined、symbol(ES6新增,唯一标识符)、bigint(ES2020新增,大整数)。引用类型:
object(包括array、function、date、regexp等)。
示例:
typeof "hello"; // "string" typeof null; // "object"(历史遗留问题) typeof Symbol(); // "symbol"
2. 类型检测方法
| 方法 | 特点 | 示例 |
|---|---|---|
typeof |
返回数据类型的字符串表示,但对null和引用类型区分有限 | typeof [] → "object" |
instanceof | 检测对象是否为某构造函数的实例,仅适用于引用类型 | [] instanceof Array → true |
Object.prototype.toString.call() |
精确判断所有类型,返回[object Type]格式字符串 | Object.prototype.toString.call(42) → "[object Number]" |
示例:
// 判断数组类型 const isArray = (arr) => Object.prototype.toString.call(arr) === '[object Array]'; isArray([]); // true
二、变量提升与作用域
1. 变量提升机制
var:声明提升至作用域顶部,初始值为undefined。let/const:存在暂时性死区(TDZ),未初始化前访问会报错。
示例:
console.log(a); // undefined(var提升) var a = 1; console.log(b); // ReferenceError(let未初始化) let b = 2;
2. 作用域链
JavaScript通过词法作用域查找变量,从当前作用域逐级向上查找至全局作用域。
示例:
function outer() {
const outerVar = 'outer';
function inner() {
console.log(outerVar); // 访问外部作用域变量
}
inner();
}
outer(); // "outer"三、闭包与高阶函数
1. 闭包的定义与应用
闭包是函数与其词法环境的组合,常用于数据封装、模块化及回调函数。
示例:
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
counter(); // 1
counter(); // 22. 高阶函数
高阶函数是接收函数作为参数或返回函数的函数,典型应用包括柯里化、防抖与节流。
柯里化(Currying)
将多参数函数转换为单参数函数序列。
function curryAdd(a) {
return function(b) {
return a + b;
};
}
const add5 = curryAdd(5);
add5(3); // 8防抖(Debounce)
事件触发后延迟执行,避免重复触发。
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}节流(Throttle)
限制事件在一定时间内仅触发一次。
function throttle(fn, delay) {
let last = 0;
return function(...args) {
const now = Date.now();
if (now - last > delay) {
fn.apply(this, args);
last = now;
}
};
}四、原型与继承
1. 原型链机制
每个对象都有__proto__属性指向其构造函数的prototype,形成原型链。
示例:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, ${this.name}`);
};
const p = new Person('Alice');
p.sayHello(); // "Hello, Alice"2. 继承实现方式
| 方式 | 特点 |
|---|---|
| 原型链继承 | 子类原型指向父类实例,共享父类引用属性 |
| 构造函数继承 |
父类构造函数通过call/apply调用,避免引用共享但无法继承原型方法 |
| 组合继承 | 结合原型链与构造函数继承,解决引用共享问题 |
| ES6类继承 |
使用class与extends语法糖,底层仍为原型链 |
示例(ES6类继承):
class Parent {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, ${this.name}`);
}
}
class Child extends Parent {
constructor(name, age) {
super(name);
this.age = age;
}
}
const c = new Child('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的语法糖,使异步代码更接近同步风格。
示例:
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => resolve('Data'), 1000);
});
}
async function getData() {
console.log('Start');
const data = await fetchData();
console.log(data); // "Data"
}
getData();六、数组与对象操作
1. 数组去重
| 方法 | 特点 |
|---|---|
Set |
利用Set数据结构的唯一性 |
filter+indexOf | 遍历数组并过滤重复项 |
reduce | 递归累积唯一值 |
示例:
// Set去重 const arr = [1, 2, 2, 3]; const uniqueArr = [...new Set(arr)]; // [1, 2, 3]
2. 深拷贝与浅拷贝
| 方法 | 特点 |
|---|---|
| 浅拷贝 |
仅复制第一层属性(如Object.assign、展开运算符...) |
| 深拷贝 |
递归复制所有层级(如JSON.parse(JSON.stringify(obj))、structuredClone) |
示例:
// 深拷贝(兼容性方案)
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
const clone = Array.isArray(obj) ? [] : {};
for (const key in obj) {
clone[key] = deepClone(obj[key]);
}
return clone;
}七、性能优化与内存管理
1. 内存泄漏常见原因
意外全局变量:未声明的变量自动挂载至
window。闭包引用:闭包中未释放的外部变量。
未清理的定时器/事件监听:如
setInterval未调用clearInterval。
示例:
// 内存泄漏示例
function leak() {
const data = new Array(1e6).fill('data'); // 大数组
return function() {
console.log(data[0]); // 闭包引用data
};
}
const leakFunc = leak();
// leakFunc未被释放时,data无法被垃圾回收2. 垃圾回收机制
JavaScript采用标记-清除算法,通过标记不可达对象并回收其内存。开发者需避免手动管理内存,但需注意减少不必要的引用。
八、浏览器兼容性与安全
1. 跨域解决方案
| 方案 | 适用场景 |
|---|---|
| CORS |
服务端设置Access-Control-Allow-Origin响应头 |
| JSONP |
仅支持GET请求,利用<script>标签无跨域限制 |
| Nginx反向代理 | 通过代理服务器转发请求,隐藏真实域名 |
示例(CORS):
// 服务端设置响应头
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST');2. XSS攻击防御
输入过滤:对用户输入进行转义或过滤。
CSP策略:通过
Content-Security-Policy限制资源加载来源。
示例:
<!-- 启用CSP --> <meta http-equiv="Content-Security-Policy" content="default-src 'self'">
九、模块化与ES6特性
1. ES Modules
导出:
export、export default。导入:
import、import * as。
示例:
// math.js
export const add = (a, b) => a + b;
export default function multiply(a, b) { return a * b; };
// main.js
import { add } from './math.js';
import multiply from './math.js';2. Symbol与BigInt
Symbol:唯一标识符,避免属性名冲突。
BigInt:表示大整数,解决
Number精度限制。
示例:
const id = Symbol('id');
const bigNum = 9007199254740991n; // BigInt字面量十、综合案例解析
案例1:实现一个事件委托函数
function eventDelegate(parent, selector, eventType, handler) {
parent.addEventListener(eventType, (e) => {
let target = 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
function promiseAll(promises) {
return new Promise((resolve, reject) => {
const results = [];
let completed = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then((value) => {
results[index] = value;
completed++;
if (completed === promises.length) resolve(results);
})
.catch(reject);
});
});
}总结
JavaScript面试题覆盖了语言核心特性、异步编程、浏览器机制及性能优化等多个维度。开发者需深入理解数据类型、作用域、原型链、异步模型等基础概念,同时掌握闭包、高阶函数、模块化等高级特性。通过系统梳理高频考点与典型案例,可显著提升面试通过率与代码质量。
本文由@战地网 原创发布。
该文章观点仅代表作者本人,不代表本站立场。本站不承担相关法律责任。
如若转载,请注明出处:https://www.zhanid.com/biancheng/5633.html




















