JavaScript 相关知识点整理
1. null
和 undefined
的区别是什么?
- 答案:
undefined
:表示变量已声明但未赋值。例如:let a; console.log(a)
输出undefined
。null
:表示变量被显式赋值为“空值”。例如:let b = null
。- 关键区别:
undefined
是 JavaScript 引擎自动赋予的,而null
是开发者主动设置的。
2. 什么是变量提升(Hoisting)?
- 答案:
- JavaScript 在代码执行前会将变量和函数的声明提升到作用域顶部。但变量仅声明提升,赋值不会提升。
- 示例:
等价于:console.log(a); // 输出 undefined var a = 10;
var a; console.log(a); // undefined a = 10;
- 注意:
let
和const
存在暂时性死区,不会完全提升。
3. 闭包是什么?它有什么作用?
- 答案:
- 闭包:函数嵌套函数时,内部函数可以访问外部函数的变量,即使外部函数已执行完毕。
- 作用:
- 数据隐藏:封装私有变量(如计数器)。
- 模块化开发:隔离作用域,避免全局污染。
- 示例:
function createCounter() {let count = 0;return { increment: () => ++count,getCount: () => count}; } const counter = createCounter(); counter.increment(); // count = 1
- 缺点:滥用闭包可能导致内存泄漏。
4. 同步代码和异步代码的区别?
- 答案:
- 同步代码:按顺序执行,阻塞后续代码。
console.log("Start"); console.log("End"); // 按顺序输出
- 异步代码:代码放入任务队列,主线程空闲时执行。
console.log("Start"); setTimeout(() => console.log("Middle"), 0); console.log("End"); // 输出顺序:Start → End → Middle
- 常见异步操作:
setTimeout
、fetch
、Promise。
- 同步代码:按顺序执行,阻塞后续代码。
5. let
、const
和 var
的区别?
- 答案:
- 作用域:
var
:函数作用域。let
/const
:块级作用域(如{}
内)。
- 变量提升:
var
会提升并初始化为undefined
。let
/const
提升但未初始化,使用前会报错。
- 重新赋值:
const
声明后不能重新赋值(但对象属性可修改)。
- 作用域:
6. ==
和 ===
的区别?
- 答案:
==
(宽松相等):会进行类型转换后比较值。console.log(1 == "1"); // true(字符串转为数字)
===
(严格相等):值和类型都相同才返回true
。console.log(1 === "1"); // false
- 建议:优先使用
===
避免隐式转换错误。
7. Promise 是什么?它的状态有哪些?
- 答案:
- Promise:表示异步操作的最终结果,解决回调地狱问题。
- 三种状态:
- Pending:初始状态,未完成或拒绝。
- Fulfilled:操作成功完成。
- Rejected:操作失败。
- 示例:
const promise = new Promise((resolve, reject) => {setTimeout(() => resolve("成功"), 1000); }); promise.then(result => console.log(result)); // 1秒后输出“成功”
- 链式调用:
.then()
和.catch()
处理结果和错误。
8. 事件冒泡和事件捕获是什么?
- 答案:
- 事件冒泡:事件从触发元素向父元素逐层传播(默认)。
- 事件捕获:事件从根元素向触发元素逐层传播。
- 示例:
<div id="parent"><div id="child">点击</div> </div>
parent.addEventListener("click", () => console.log("父元素被点击")); child.addEventListener("click", () => console.log("子元素被点击")); // 点击子元素时输出:子元素 → 父元素(冒泡阶段)
- 阻止冒泡:
event.stopPropagation()
。
9. 箭头函数和普通函数的区别?
- 答案:
this
指向:- 普通函数:根据调用方式动态绑定
this
。 - 箭头函数:继承父作用域的
this
,无法通过call
/apply
修改。
- 普通函数:根据调用方式动态绑定
- 示例:
const obj = {name: "Alice",sayName: function() { console.log(this.name) }, // 输出 AlicesayNameArrow: () => console.log(this.name) // 输出 undefined(this指向全局) };
- 其他区别:箭头函数没有
arguments
对象,不能作为构造函数。
10. 什么是原型链?
- 答案:
- 原型链:对象通过
__proto__
属性向上查找属性和方法的链式结构。 - 示例:
function Person(name) { this.name = name; } Person.prototype.sayName = function() { console.log(this.name) }; const alice = new Person("Alice"); alice.sayName(); // 输出 Alice(通过原型链找到方法)
- 继承机制:子类通过
prototype
指向父类实例实现继承。
- 原型链:对象通过
更多高频问题:
- 跨域解决方案:CORS、JSONP、代理服务器。
- 深拷贝实现:
JSON.parse(JSON.stringify(obj))
(局限性:无法处理函数和循环引用)。 - 防抖和节流:优化高频事件(如滚动、输入)的性能。