作为从业八年的前端老司机,我深知那些高频面试题背后隐藏的知识体系才是真正决定开发者水平的关键。今天要聊的这五个主题——Ajax、原型链、事件循环、Vue和浏览器渲染,就像前端领域的"五绝",掌握它们就相当于拿到了高级开发的通行证。记得刚入行时,每次被问到"从输入URL到页面展示发生了什么"就头皮发麻,后来才发现只要吃透这几个核心概念,90%的面试场景都能从容应对。
2005年诞生的XMLHttpRequest彻底改变了Web的交互方式,让我们看看经典GET请求的完整实现:
javascript复制const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/data', true); // 异步模式
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
};
xhr.send();
而现代的Fetch API则更加简洁:
javascript复制fetch('/api/data')
.then(response => {
if(!response.ok) throw new Error('Network error');
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error(error));
关键点:注意Fetch不会自动携带cookie且默认不处理HTTP错误状态码,这点与XHR不同
javascript复制const controller = new AbortController();
fetch(url, { signal: controller.signal });
// 需要时调用 controller.abort()
当我们创建一个构造函数时:
javascript复制function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, ${this.name}!`);
};
实例访问方法时的查找路径:
code复制实例对象 → 构造函数prototype → Object.prototype → null
class写法只是原型继承的语法糖:
javascript复制class Person {
constructor(name) { this.name = name; }
sayHello() { console.log(`Hello, ${this.name}!`); }
}
// 等同于
function Person(name) { /*...*/ }
Person.prototype.sayHello = function() { /*...*/ };
常见误区:直接修改内置原型(如Array.prototype)是危险操作,会导致不可预期的行为
典型的事件循环流程:
看这段代码的输出顺序:
javascript复制console.log('script start');
setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => {
console.log('promise1');
}).then(() => console.log('promise2'));
console.log('script end');
正确输出顺序:
code复制script start
script end
promise1
promise2
timeout
性能提示:长时间运行的同步代码会阻塞渲染,Web Worker是解决方案之一
Vue2使用Object.defineProperty:
javascript复制function defineReactive(obj, key) {
let value = obj[key];
Object.defineProperty(obj, key, {
get() {
console.log(`读取${key}`);
return value;
},
set(newVal) {
console.log(`设置${key}`);
value = newVal;
}
});
}
Vue3改用Proxy实现更强大的拦截能力。
结合所有知识点,完整流程如下:
在这个过程中,事件循环持续运行处理用户交互,Vue等框架的响应式系统监听数据变化,最终通过虚拟DOM diff算法高效更新视图。
因为setTimeout回调属于宏任务,必须等待当前调用栈清空且微任务队列处理完毕后才会执行。
避免多个组件实例共享同一数据对象,每个实例需要独立的数据副本。
相比Options API,Composition API:
原生组件化方案的优势:
在实际项目中,我通常会根据团队技术栈和项目规模选择合适的技术组合。对于中小型项目,Vue的单文件组件开发体验非常高效;而对于需要长期维护的大型应用,考虑使用TypeScript+Composition API的组合能获得更好的可维护性。