中级前端工程师面试题
一、选择题(10题,每题3分)*!
1. 以下代码的输出结果是什么?(B)
console.log(typeof null);
A. “null’
B. “object”
C. “undefined”
D. “number”
答案:B(原题拼写 obiect 是 object 笔误)
解析:JS 历史 bug,typeof null === 'object'。
2.关于原型链,以下说法正确的是:(D)
A. 所有对象最终都指向 Object.prototvpe’
B.’Object.create(null),创建的对象有原型
C.’Array.prototype’的原型是‘Object’
D.修改原型对象的属性会影响所有实例
答案:D
A:Object.create(null) 无原型,不指向 Object.prototype;
B:Object.create(null) 创建的对象 __proto__ 为 null,没有原型;
C:Array.prototype.__proto__ 是 Object.prototype,不是 Object 构造函数;
D:原型是共享对象,修改原型属性,所有实例读取都会变化,正确。
3.vue 中,以下哪个生命周期钩子函数在组件首次渲染时被调用?(A)
A. ‘mounted”
B. ‘created’
C. ‘beforeMount
D. ‘updated’
答案:A mounted
解析:
created:实例创建完毕,DOM 未生成;
beforeMount:挂载前,DOM 未插入页面;
mounted:DOM 挂载到页面,首次渲染完成;
updated:数据更新后重新渲染触发,不是首次渲染。
4. 在React 函数组件中,用于处理副作用的 Hook 是:(B)
A. ‘useState’
B. ‘useEffect’
C. ‘useContext’
D. ‘useReducer’
答案:B useEffect
useState:状态;useContext:上下文;useReducer:复杂状态。
5.以下 Es6 语法中,错误的是:(D)
A. ‘const { a, b} = obj;’
B. ‘let x = (a, b) => a + b;’
C. ‘class MyClass extends ParentClass 1’
D. ‘import * as utils from ‘ /utils.js’;’
答案:D
笔误修正:路径不能写 /utils.is,文件名后缀一般是 .js;且导入路径格式错误。
A 解构、B 箭头函数、C 类继承语法全部合法。
6. 关于事件循环,以下代码的输出顺序是:(B)
“javascript
setTimeout(() => console. log(1), 0);
Promise.resolve (). then (() => console. log(2));
console.log(3);
A. 3, 1, 2
B. 3, 2, 1
C. 1, 3, 2
A. 2, 3, 1
执行顺序:同步代码 → 微任务 Promise.then → 宏任务 setTimeout
输出:3,2,1,答案B。
7.vuve3 的Compostition Ap1 中,用手南应式引用的是:(A)
A. ref
B. ‘reactive
C. computed
D. watch
答案:A ref
ref:基本类型 / 单个对象响应式;
reactive 仅对象 / 数组;
题干 “引用式” 指向 ref。
8.以下哪个方法可以强制触发 React 组件的亚新渲染?(C)
A. this.forceUpdate()°
B. this.setstate(®)°
C.两者都可以
D.两者都不可以
答案:C 两者都可以
this.forceUpdate():无视 state/props 强制刷新;
this.setState({}) 空更新也会触发 render 重渲染。
9.关于闭包,以下代码的输出结果是什么?(A)
“javascript
function createFunc() {
let a = 1;
return function() ( console.log(a++); );
const func = createFunc();
}
func();
func();
A. 1, 2
B. 1. 1
C. 2, 3
D. 1, undefined
闭包保留外层a引用,第一次输出 1,自增为 2;第二次输出 2。
答案:A 1,2
10.ES6 中,以下关于 vet和 var的说法错误的是:
A. let存在暂时性死区
B. var声明的变量会挂教到全局对象上
C. let允许重复声明
D. var存在变量提升
答案:C
解析:let 同一作用域禁止重复声明;
A:let 有暂时性死区 TDZ;
B:var 全局变量挂载 window;
D:var 存在变量提升。
(20题,每题2分)*
1.javascript中0.1+0.2===0.3〝 的结果是true’。
2.Vue中 v-if和 v-show的作用完全相同。
3.React中setState•是同步操作。
4.0bject.keys()可以获取对象原型上的属性。
6.’Promise.all 会在所有 Promise 都成功时返回结果数组。
7.vue 组件间的通信只能迎过 props’ 和 semit: 实現。
§.ES6 的模板字符串可以联套使用。
9.null instanceof Object 的结果是 true’。
10.React 函数组件中可以使用生命周期方法。
11.const 声明的交量不可重新赋值,但对象属性可以修改。
12.’Array.prototype.map’会改变原数组。
13.vue的v-moder’ 可以用于自定义组件。
14.’typeof[] 的结果是 “array”’。
15. React Hooks 只能在函数组件中使用。
16.0bject.assign’是浅持贝。
17.Javascript 中所有函数都是 Function的实例。
18.vue3 支持 Options API 和 Composition API 混合使用。
19, useState:的初始值可以是一个函数。
20. for..in 储环可以遊历数组的素引和对象的可枚举属性。
0.1+0.2===0.3 → × 浮点数精度丢失,结果 false
Vue v-if 和 v-show 完全相同 → ×
v-if 销毁重建 DOM;v-show CSS 隐藏 DOM,开销不同。
React setState 同步操作 → ×
合成事件 / 生命周期内批量异步;原生事件、定时器内同步。
Object.keys() 获取原型属性 → ×
仅获取自身可枚举属性,不遍历原型链。
Promise.all 全部成功才返回数组 → √
任意一个 reject 直接触发失败。
Vue 组件通信只有 props/
还有parent/$children 等。
ES6 模板字符串可嵌套 → √
null instanceof Object → × 返回 false
React 函数组件不能使用 class 生命周期钩子 → ×
const 对象变量不能重赋值,但属性可修改 → √
Array.map 修改原数组 → × map 返回新数组,不改动原数组
Vue v-model 可用于自定义组件 → √ 自定义 v-model 语法糖
typeof [] → "array" → × 返回"object",不是 "array",这是 JS 历史遗留 bug,不能用 typeof 判断数组Array.isArray([])
React Hooks 只能在函数组件调用 → √(自定义 Hook 本质也是函数组件规则)
Object.assign 浅拷贝 → √
JS 所有函数都是Function实例 → √
Vue3 可混合 Options API + Composition API → √
useState初始值支持函数 → √ 惰性初始化
for...in 遍历数组索引、对象可枚举属性 → √
三、简答题 (2题,每题 15分).
1.请简述 JavaScript 原型链的实现机制,并举例说明原型继派的优缺点。
(1)实现机制
每个构造函数拥有 prototype 原型对象;
构造函数 new 出的实例拥有 __proto__,指向构造函数的prototype;
原型对象自身也有__proto__,层层向上查找,直到顶端Object.prototype.__proto__ === null;
访问对象属性 / 方法时:先在自身查找,找不到顺着__proto__向上遍历整条原型链,直到找到或到链尾停止。
示例:
js
运行
function Person(){}
Person.prototype.say = function(){}
const p = new Person();
// p.__proto__ === Person.prototype
// Person.prototype.__proto__ === Object.prototype
(2)原型继承优点
节省内存:方法挂载原型,所有实例共享同一份函数,不用每个实例单独复制;
天然实现继承,扩展原型即可批量给所有实例新增方法;
JS 原生内置,数组、内置对象都基于原型链实现扩展。
(3)缺点
原型引用类型属性会被所有实例共享,一个实例修改数组 / 对象,全部实例同步改动;
无法向父构造函数单独传参,实例初始化灵活性差;
多层原型链嵌套过深,属性查找遍历层级多,存在性能损耗。
2.对比Vue和React在数据绑定,组件通信和状态管理上的异同。
一、数据绑定
相同点
都是单向数据流为核心理念;
视图依赖状态,状态驱动视图更新,摒弃 DOM 手动操作;
数据变更自动触发视图重新渲染。
不同点
Vue:
双向绑定:v-model语法糖,底层绑定 value + 监听 input 事件;
响应式原理:Vue2 Object.defineProperty、Vue3 Proxy,自动依赖收集,精准更新组件;
模板语法:HTML 模板,指令驱动。
React:
严格单向绑定,无原生双向绑定;双向需要手动封装value+onChange;
无响应式监听,靠setState/setXxx触发重渲染;
JSX 语法,JS 和 HTML 混写。
二、组件通信
相同点
父子组件:父传子属性,子触发回调给父传值;
跨层级都支持透传、全局事件、全局状态库;
兄弟组件借助共同父组件中转通信。
不同点
Vue
父子:props / $emit;
跨层级:provide/inject;
全局:EventBus、Pinia/Vuex;
访问实例:$parent/$children/$refs。
React
父子:props 传参 + 回调函数;
跨层级:useContext上下文;
无原生事件总线,依赖第三方库;
函数组件无实例,不能直接拿组件 DOM 实例。
三、状态管理
相同点
组件内私有状态:组件自身维护,不全局共享;
全局状态库:集中管理公共状态,组件共享、统一修改;
支持模块化拆分全局状态,避免单一状态臃肿。
不同点
Vue
Vue2:Vuex;Vue3:Pinia(无 mutations、模块化更简洁);
状态自带响应式,修改 state 直接赋值即可更新;
React
原生:useState/useReducer局部状态;
全局主流:Redux、Zustand、Jotai;
不可变数据原则:不能直接修改 state,必须返回全新对象触发更新。
四、关键代码验证(复制可直接运行)
运行
// 1. 自定义构造函数
function Person() {}
const p = new Person();
console.log(p.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
// 2. 数组
const arr = [];
console.log(arr.__proto__ === Array.prototype); // true
console.log(Array.prototype.__proto__ === Object.prototype); // true
// 3. 构造函数都是 Function 实例
console.log(Person.__proto__ === Function.prototype); // true
console.log(Array.__proto__ === Function.prototype); // true
console.log(Function.prototype.__proto__ === Object.prototype); // true
五、原型链查找规则(必背)
- 读取
p.xxx时,先在实例自身属性查找; - 找不到就顺着
__proto__去Person.prototype找; - 还找不到继续上溯到
Object.prototype; - 追到
null仍无该属性,返回undefined。
六、高频易错点
prototype只属于构造函数,实例只有__proto__;typeof Person.prototype→object,所有原型对象都是普通对象;- 修改原型上的属性,所有共享该原型的实例都会受影响;
Object.create(null)创建的对象无__proto__,不在标准原型链上。




