资讯动态

JavaScript面试核心:this指向与对象引用解析

发布时间:2026/8/22 7:42:41 来源:尧图企业网站定制
1. 面试题解析this指向与对象引用这道题考察了JavaScript中this关键字的指向规则和对象引用的概念。题目给出了一个makeStudent函数function makeStudent() { console.log(this, this); return { studentName: xiaoming, ref: this, } }1.1 普通函数调用时的this指向当直接调用makeStudent()时在非严格模式下this指向全局对象浏览器中是window。因此let student makeStudent(); // 输出: this window console.log(student.ref); // 输出: window console.log(student.ref.studentName); // 输出: undefined这里student.ref指向的是window对象而window对象上没有studentName属性所以返回undefined。1.2 构造函数调用时的this指向当使用new操作符调用时this指向新创建的实例对象let student2 new makeStudent() // 输出: this makeStudent{} console.log(student2.ref); // 输出: makeStudent{} console.log(student2.ref.studentName); // 输出: undefined此时student2.ref指向的是新创建的makeStudent实例该实例上也没有studentName属性。1.3 解决方案使用函数返回正确引用要让student.ref.studentName打印xiaoming可以将ref改为一个函数function makeStudent() { return { studentName: xiaoming, ref: function() { return this; } } } let student makeStudent(); console.log(student.ref().studentName); // 输出: xiaoming这种写法利用了方法调用时this指向调用对象的规则。当调用student.ref()时this指向student对象本身。注意在严格模式下普通函数调用的this会是undefined而不是window。这是面试中常被追问的细节。2. 类方法与解构赋值问题这道题考察了ES6类方法和解构赋值的特性class Hello{ constructor(){ this.z[1,2,3,4,5] } sayHello(){ console.log(this.z) } } const objnew Hello() const {sayHello}obj sayHello() // 报错2.1 解构赋值的本质解构赋值相当于const sayHello obj.sayHello;这样获取的是sayHello方法本身但丢失了与obj的绑定关系。2.2 this绑定丢失问题当直接调用解构后的sayHello时this指向取决于调用方式在非严格模式下this指向全局对象在严格模式下this为undefined由于类内部默认使用严格模式所以会报错无法读取undefined的z属性。2.3 正确的解构调用方式要保持this绑定可以使用以下方法// 方法1使用bind const {sayHello} obj; const boundSayHello sayHello.bind(obj); boundSayHello(); // 方法2使用箭头函数 class Hello{ constructor(){ this.z[1,2,3,4,5] } sayHello () { console.log(this.z) } }箭头函数没有自己的this会捕获定义时的this值。3. 时间格式化函数实现题目要求将毫秒数转换为x年x月x天x日x时x分x秒的格式。3.1 时间单位换算关系首先需要明确各时间单位之间的换算关系1秒 1000毫秒1分钟 60秒1小时 60分钟1天 24小时1月 ≈ 30.44天按365.25天/年计算1年 365.25天3.2 实现思路从大到小依次计算各时间单位function formatTime(ms) { const seconds Math.floor(ms / 1000); const minutes Math.floor(seconds / 60); const hours Math.floor(minutes / 60); const days Math.floor(hours / 24); const months Math.floor(days / 30.44); const years Math.floor(months / 12); return ${years}年${months%12}月${days%30}天${hours%24}时${minutes%60}分${seconds%60}秒; }3.3 边界情况处理实际实现中需要考虑0值单位是否显示单复数形式如1年 vs 2年大数处理使用BigInt负值处理4. Fetch API封装实践题目要求封装一个网络请求函数考察对Fetch API的理解和抽象能力。4.1 基础封装实现async function request(url, options {}) { const { method GET, headers {}, body null, timeout 8000, ...rest } options; const controller new AbortController(); const timer setTimeout(() controller.abort(), timeout); try { const response await fetch(url, { method, headers: { Content-Type: application/json, ...headers }, body: body ? JSON.stringify(body) : null, signal: controller.signal, ...rest }); if (!response.ok) { throw new Error(HTTP error! status: ${response.status}); } const data await response.json(); return data; } catch (error) { console.error(Request failed:, error); throw error; } finally { clearTimeout(timer); } }4.2 高级功能扩展一个完善的请求库还应考虑请求/响应拦截器取消请求自动重试缓存策略并发控制类型定义(TypeScript)5. 模块循环引用分析题目给出了三个模块的循环引用关系// a.js console.log(a starting); exports.done false; const b require(./b.js); console.log(in a, b.done %j, b.done); exports.done true; console.log(a done); // b.js console.log(b starting); exports.done false; const a require(./a.js); console.log(in b, a.done %j, a.done); exports.done true; console.log(b done); // main.js console.log(main starting); const a require(./a.js); const b require(./b.js); console.log(in main, a.done %j, b.done %j, a.done, b.done);5.1 CommonJS模块加载机制CommonJS模块系统是同步加载的采用以下规则模块首次加载后会被缓存模块加载是同步的、阻塞式的模块导出的是值的拷贝5.2 执行流程解析main.js开始执行输出main starting加载a.js输出a starting设置exports.done false开始加载b.js加载b.js输出b starting设置exports.done false尝试加载a.js发现a.js已经在加载中返回当前部分导出的对象此时a.done还是false输出in b, a.done false设置exports.done true输出b done回到a.js现在b.done已经是true输出in a, b.done true设置exports.done true输出a done回到main.js现在a和b都已完全加载输出in main, a.done true, b.done true5.3 循环引用的实际影响虽然循环引用在CommonJS中不会导致死循环但可能导致模块状态不一致难以追踪的依赖关系代码理解困难最佳实践是重构代码避免循环引用或使用依赖注入等方式解耦。6. 正则表达式实战题目要求编写正则表达式实现以下功能re.test(htmla)返回truere.test(css)返回truere.test(js)返回false6.1 正则表达式基础常见错误写法let re /[html|css]/; // 错误字符组匹配单个字符正确写法let re /^(html|css)/; // 匹配以html或css开头6.2 提取方法名和参数题目要求从字符串obj.someMethod.sayHi(args)中提取方法名和参数const str obj.someMethod.sayHi(args); let re /\.(\w)\((\w)\)/; const match str.match(re); console.log(match[1]); // sayHi console.log(match[2]); // args6.3 正则表达式优化更健壮的写法应考虑方法链长度不固定参数可能包含各种字符空格等干扰因素改进版本const re /(?:\.(\w))\(([^)]*)\)/; const str obj.foo.bar.sayHi(arg1, arg2); const match str.match(re); console.log(match[1]); // sayHi console.log(match[2]); // arg1, arg27. Flex布局高级技巧题目要求仅使用flex布局实现项目1和2在box中水平垂直居中项目3位于右上角7.1 基础flex布局div classbox div1/div div2/div div3/div /div7.2 实现方案.box { display: flex; justify-content: center; align-items: center; position: relative; height: 300px; /* 假设高度 */ } .box div { width: 100px; height: 100px; margin: 10px; } .box div:last-child { position: absolute; top: 0; right: 0; }但题目要求不能使用定位纯flex解决方案.box { display: flex; flex-wrap: wrap; justify-content: center; align-content: center; height: 300px; } .box div { width: 100px; height: 100px; margin: 10px; } .box div:last-child { align-self: flex-start; margin-left: auto; margin-right: 0; }7.3 flex布局原理关键点justify-content控制主轴对齐align-items控制交叉轴对齐align-self覆盖单个项目的交叉轴对齐margin: auto可以实现特殊定位效果8. React组件设计虽然题目没有给出具体需求但常见的React组件面试题可能涉及8.1 受控组件实现function InputComponent() { const [value, setValue] useState(); return ( input value{value} onChange{(e) setValue(e.target.value)} / ); }8.2 复合组件设计function Tabs({ children }) { const [activeIndex, setActiveIndex] useState(0); return ( div classNametabs div classNametab-list {React.Children.map(children, (child, index) ( button className{tab ${index activeIndex ? active : }} onClick{() setActiveIndex(index)} {child.props.label} /button ))} /div div classNametab-content {children[activeIndex]} /div /div ); } function App() { return ( Tabs div labelTab 1Content 1/div div labelTab 2Content 2/div /Tabs ); }8.3 性能优化技巧使用React.memo避免不必要的渲染使用useCallback/useMemo缓存函数和值虚拟列表优化长列表渲染代码分割按需加载9. 面试准备建议9.1 技术深度准备JavaScript核心概念原型与继承事件循环闭包与作用域ES6新特性React/Vue框架原理虚拟DOM组件生命周期状态管理Hooks原理浏览器工作原理渲染流程性能优化安全防护9.2 项目经验梳理准备2-3个有深度的项目项目背景与目标技术选型原因遇到的挑战与解决方案你的具体贡献可量化的成果9.3 编码练习平台推荐练习平台LeetCode算法题Frontend Mentor前端项目Codewars编程挑战自己实现小型库/工具10. 面试后续跟进10.1 面试复盘要点记录所有面试问题标注回答不理想的问题研究正确答案和更优解法总结面试官反馈10.2 感谢信模板尊敬的[面试官姓名] 感谢您昨天抽出时间面试我[职位名称]的职位。我非常享受我们关于[具体话题]的讨论特别是[具体内容]。 面试后我进一步研究了[某个问题]发现[你的新认识]。这让我对这个领域有了更深的理解。 期待有机会加入[公司名称]团队为[具体业务]贡献我的技能和经验。 此致 敬礼 [你的姓名]10.3 后续跟进策略适当时间询问结果通常5-7个工作日保持专业和耐心无论结果如何都保持积极态度将每次面试视为学习机会

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价