logo资料库

高薪之路—前端面试精选集.pdf

第1页 / 共201页
第2页 / 共201页
第3页 / 共201页
第4页 / 共201页
第5页 / 共201页
第6页 / 共201页
第7页 / 共201页
第8页 / 共201页
资料共201页,剩余部分请下载后查看
01 开篇:为什么要学习本专栏 更新时间:2020-03-08 18:49:49 知识犹如人体的血液一样宝贵。 ——高士其 大家好,我是 Nolan,前美团高级前端工程师,长期担任面试官,曾主持过美团的多个重要产品的 开发工作。现在旅居澳大利亚,担任一家支付公司的前端业务负责人。 多年的面试官经历,使我得出一个结论:面试表现和工作能力,并没有大多数人以为的那么相关。 一个技术能力优秀的程序员,很可能因为忘记 Event Loop 的内容而被认为基础知识不扎实;一个 原来在团队中没有存在感每天划水的人,却有可能因为碰巧面试前一天晚上刷到了浏览器缓存机制 的面试题,而被认为是基础扎实的大牛。实际上,如果面试总是能准确地反映出一个人真正的技术 能力,大公司里就不会有这么多划水的人了。 工作能力强,并不代表面试表现就一定好;工作有工作的技巧,面试有面试的技巧,它们有一些联 系,但是它们是两个不同的学科。如果你下个月要参加长跑比赛,从现在开始你会每周练习三次长 跑;但是如果你下个月要参加面试,却不从现在开始花一个月的时间刷一遍面试题,岂不是很奇怪 吗?
市面上有不少介绍前端面试的资料,但是都包含各式各样的问题:有的年代久远题目过时已久;有 的主题不全,某些资料竟然以作者不熟悉 CSS 为由将 CSS 的题目一笔带过,而关于 TypeScript, React Native,层叠上下文,移动端开发的题目更是少之又少;有的浅尝辄止,只是提供一个答案 不做深入研究,让读者一知半解;有的东拼西凑,完全形不成系统。 所以我决定自己来写一个面试专栏,这个专栏花费了我很多精力,但是我相信是值得的。只要你从 头到尾练习一遍,一定可以解答你的很多疑惑,为你的面试助力。 我选择题目的标准是: 1. 实用性。即,题目背后的知识点一定是面试中大概率会被问到的知识点 2. 代表性。即,每道题目可以都准确地代表一类知识点,这样有利于读者举一反三,遇到这一类 的题目都能有思路 3. 全面性。即,覆盖到所有常见的前端面试知识点,这样读者只需要通读本专栏,而不需要四处 搜寻其他的材料作为补充 4. 科学性。即,越是常考的题目,越放在前面。这样可以保证读者熟知最常考到的题目。比如大 多数面试书会遵循 JavaScript 技术书籍的编写原则:把 JavaScript 的变量与变量类型 这个题 目放在第一节。实际上这是不科学的,因为 JavaScript技术书籍要兼顾到 JavaScript 新手, 所以第一节一定要讲最基本的知识;而大部分面试书籍的读者都有一定的前端知识,就不如把 函数调用、执行上下文、异步函数等知识放在第一章。 本专栏共分为 7 章,分别为: 1. 开篇 本章介绍了整个专栏的基本内容以及设计原则 2. JavaScript 本章包含了 JavaScript 相关知识的常见考点,包含 函数定义、调用、闭包、原型与继承、异 步函数等等内容,是整个专栏中的重中之重,同学们务必要掌握每一道题目。 3. CSS 本章包含了 CSS 单位、布局、层叠上下文、自适应等内容,这一章的内容是很多面试书籍会 忽略的内容,因为 CSS 是很多前端程序员的薄弱项,包括这些书籍的作者。这就造成了很多 对 JavaScript 能侃侃而谈却被一道简单的 CSS 题目难倒的尴尬场景。而本章致力于覆盖 CSS 面试中常见的面试题目,希望能为 CSS 基础薄弱的同学助力。
4. 客户端 本章的内容是浏览器相关,包括 HTML、浏览器、性能优化、HTTP 等知识点,这部分内容考 察面试者在代码能力之外的知识能力。 5. 框架与库 本章的内容包含了 React、Vue、TypeScript、React Native 等常考知识点。React 小节包含 了 React Hook 的内容,而 Vue 则包含了 Vue3 的相关知识。网上关于 TypeScript 的面试题 很少,React Native 的题目则更是难得,笔者总结了一些经典题目。 6. 计算机基础知识 很多公司喜欢考察一些前端以外的知识,以证明你有主动学习的热情。本章总结了一些常见的 计算机相关的面试知识。 7. 简历与面试 本章笔者根据自己多年的担当面试者与面试官的经验,聊一聊关于简历和面试的心得。帮助读 者树立对于面试的正确态度。 希望每位同学都能在这本书中有所收获。
02 函数定义与调用 更新时间:2020-02-23 16:02:13 不要问你的国家能够为你做些什么,而要问你可以为国家做些什么。 ——林肯 函数是 JavaScript 中最重要的概念,其定义和调用都包含了很多知识点。特别是其中的函数上下 文,也就是函数中的 this 关键字,是前端面试中的必考知识点。本节的题目会涉及到函数上下文、 箭头函数等内容。 1. 一个页面的脚本如下,请问会打印出什么内容? function printThis() { return this; } console.log(printThis() === window) 答案: 严格模式下,打印 false ;非严格模式下,打印 true 。
因为当函数被当作独立函数调用时,严格模式下 this 指向 undefined ;非严格模式下 this 指向 wi ndow 。 解读: 同样一个函数,其被调用的方式有很多,在不同的情况下函数上下文的指向也不一样。这道题就展 示了当函数被当作独立函数调用时的场景。这道题目的另一个价值是与后面将要提到的函数被当作 构造函数(下一道题)的场景作对比。 注意,要尽量回答出严格模式和非严格模式的区别,这个区别是很经典的。 2. 一个页面的脚本如下,请问会打印出什么内容? function printThis() { return this; } const obj = {printThis} console.log(obj.printThis() === window) 答案: 打印出 false 。 因为当函数被当作一个对象的方法调用时,其中的 this 指向此对象。由于 printThis 函数变成了 o bj 对象的一个方法,所以 printThis 中的 this 指向 obj ,而不是 window 。 解读: 这道题考察了当函数被当作对象的方法调用时 this 的指向问题。当函数被当做对象的方法调用时, this指向此对象,这是在无数面试中被考察过无数遍的内容。 在本题中,虽然函数在被定义时是个独立函数,但是其在被调用时是 obj 对象的一个方法,所以适 用于函数被当作对象方法调用的规则。 3. 一个页面的脚本如下,请问会打印出什么内容? function Dog() { this.name = 'Puppy' }
const dog = Dog() console.log(dog.name) 答案: 会报错: Uncaught TypeError: Cannot read property 'name' of undefined 因为在这段代码中 Dog 函数被当作普通函数调用,而 Dog 函数没有返回值,也就是说返回值是 undef ined ,所以当代码尝试去读取 undefined 的 name 属性时会报错。 解读: 这道题的陷阱就在于, Dog 函数的函数名首字母是大写的。我们都知道在 JavaScript 中默认的规则 是:**构造函数的函数名以大写字母开头,其他函数名以小写字母开头。**本题的函数名首字母虽然 是大写,但是它是被当作独立函数调用的,所以应适用于独立函数的规则。 当 Dog 函数被当作构造函数调用时: function Dog() { this.name = 'Puppy' } const dog = new Dog() console.log(dog.name) 此时就会如预期一样打印出 Puppy 。 顺便一提,大家在写 React 的时候可能注意到过,其中的组件名都是大写字母开头,如 ant.design 中的 Modal , Menu 等组件,这是因为组件相对于组件实例,正是构造函数相对于构造函数实例的关 系。 4. 一个页面的脚本如下,请问会打印出什么内容? const puppet = { rules: false }; function Emperor() { this.rules = true; return puppet; }
const emperor = new Emperor(); console.log(emperor.rules) 答案: false 虽然当函数被当作构造函数调用时, this 关键字指向使用构造函数构建的实例。但是 Emperor 构造 函数最后返回了一个 puppet 对象,如果构造函数有返回值且返回值为一个对象,此构造函数构造的 实例就是这个返回值。 所以构造函数返回的实际上是在第一行声明的 puppet 对象,所以 emperor.rules 的值为 false 解读: 这道题函数的使用场景类似于 字,又有构造函数的实例创建过程。 ,既有具有独立函数特色的 return 关键 5. Function.prototype.apply 方法和 Function.prototype.call 方 法有什么区别? 答案: 参数传入格式不同。 Function.prototype.apply 接受数组字面量(array literal),如 : fun.apply(this, ['eat', 'bananas']) 或数组对象, 如: fun.apply(this, new Array('eat', 'bananas')) 实际上, Function.prototype.apply 可以接受任何形式的类数组对象,如 arguments , NodeList 等,也就是说,只要是有 length 属性和 (0..length-1) 范围的整数属性就可以。如: {'length': 2, '0': 'eat', '1': 'bananas'} 构 造 函 数 与 独 立 函 数 的 结 合
而 Function.prototype.call 是从第二个参数开始,每个参数依次传入,如: callback.call(list[n], n1, n2); 解读: 一个很有用的记忆方法:call 这个单词的意思是拨打电话,打电话的时候数字要一个一个地按,而 不是把数字放在数组里一起按,所以 call 方法的参数是要一个一个传入的。而剩下的 apply 方法就 要传入类数组参数了。 6.在浏览器中运行以下脚本,点击页面后,会打印出 false。请问为什 么会打印出 false? function Button() { this.clicked = false; this.click = function () { this.clicked = true; console.log(button.clicked, 'clicked'); }; } const button = new Button(); document.addEventListener("click", button.click) 答案: 因为 addEventListener 的回调函数的函数上下文为触发事件的元素的引用。所以 click 事件发生 时, button.click 回调函数被调用时里面的 this 指向了 document 元素。 所以 document.clicked 被设置为 true ,而 button.clicked 则没有变化,依然为 false 。 解读: 注意打印时打印的是 button.clicked 而不是 this.clicked ,这已经在明显暗示:button 和 this 并不指向同一个对象。 addEventListener 的回调函数的函数上下文为触发事件的元素的引用,为什么要这么设计呢?想象 这样一个场景:
分享到:
收藏