刷《一年半经验,百度、有赞、阿里面试总结》·手记

在掘金上看到了一位大佬发了一篇很详细的面试记录文章-《一年半经验,百度、有赞、阿里面试总结》,为了查漏补缺,抽空就详细做了下。(估计只有我这么无聊了哈哈哈)

有给出的或者有些不完善的答案,也尽力给出/完善了(可能有错,大家自行辨别)。有些很困难的题目(例如实现Promise),附带相关链接(懒癌患者福利)。

总的来说,将这些题目分成了“Javascript”、“CSS”、“浏览器/协议”、“算法”和“Web工程化”5个部分进行回答和代码实现。

最后,欢迎来我的博客和我扯犊子:godbmw.com。直接戳本篇原文的地址:刷《一年半经验,百度、有赞、阿里面试总结》·手记

1. Javascript相关 1.1 回文字符串

题目:实现一个函数,判断是不是回文字符串

原文的思路是将字符串转化成数组=>反转数组=>拼接成字符串。这种做法充分利用了js的BIF,但性能有所损耗

function run(input) { if (typeof input !== 'string') return false; return input.split('').reverse().join('') === input; }

其实正常思路也很简单就能实现,性能更高,但是没有利用js的特性

// 回文字符串 const palindrome = (str) => { // 类型判断 if(typeof str !== 'string') { return false; } let len = str.length; for(let i = 0; i < len / 2; ++i){ if(str[i] !== str[len - i - 1]){ return false; } } return true; } 1.2 实现Storage

题目:实现Storage,使得该对象为单例,并对localStorage进行封装设置值setItem(key,value)和getItem(key)

题目重点是单例模式,需要注意的是借助localStorage,不是让自己手动实现!

const Storage = () => {} Storage.prototype.getInstance = (() => { let instance = null return () => { if(!instance){ instance = new Storage() } return instance } })() Storage.prototype.setItem = (key, value) => { return localStorage.setItem(key, value) } Storage.prototype.getItem = (key) => { return localStorage.getItem(key) } 1.3 JS事件流

题目:说说事件流吧

事件流分为冒泡和捕获。

事件冒泡:子元素的触发事件会一直向父节点传递,一直到根结点停止。此过程中,可以在每个节点捕捉到相关事件。可以通过stopPropagation方法终止冒泡。

事件捕获:和“事件冒泡”相反,从根节点开始执行,一直向子节点传递,直到目标节点。印象中只有少数浏览器的老旧版本才是这种事件流,可以忽略。

1.4 实现函数继承

题目:现在有一个函数A和函数B,请你实现B继承A。并且说明他们优缺点。

方法一:绑定构造函数

优点:可以实现多继承

缺点:不能继承父类原型方法/属性

function Animal(){ this.species = "动物"; } function Cat(){ Animal.apply(this, arguments); // 父对象的构造函数绑定到子节点上 } var cat = new Cat() console.log(cat.species) // 输出:动物

方法二:原型链继承

优点:能够继承父类原型和实例方法/属性,并且可以捕获父类的原型链改动

缺点:无法实现多继承,会浪费一些内存(Cat.prototype.constructor = Cat)。除此之外,需要注意应该将Cat.prototype.constructor重新指向本身。

js中交换原型链,均需要修复prototype.constructor指向问题。

function Animal(){ this.species = "动物"; } Animal.prototype.func = function(){ console.log("heel") } function Cat(){} Cat.prototype = new Animal() Cat.prototype.constructor = Cat var cat = new Cat() console.log(cat.func, cat.species)

方法3:结合上面2种方法

function Animal(){ this.species = "动物"; } Animal.prototype.func = function(){ console.log("heel") } function Cat(){ Animal.apply(this, arguments) } Cat.prototype = new Animal() Cat.prototype.constructor = Cat; var cat = new Cat() console.log(cat.func, cat.species) 1.5 ES5对象 vs ES6对象

题目:es6 class 的new实例和es5的new实例有什么区别?

在ES6中(和ES5相比),class的new实例有以下特点:

class的构造参数必须是new来调用,不可以将其作为普通函数执行

es6 的class不存在变量提升

最重要的是:es6内部方法不可以枚举。es5的prototype上的方法可以枚举。

为此我做了以下测试代码进行验证:

console.log(ES5Class()) // es5:可以直接作为函数运行 // console.log(new ES6Class()) // 会报错:不存在变量提升 function ES5Class(){ console.log("hello") } ES5Class.prototype.func = function(){ console.log("Hello world") } class ES6Class{ constructor(){} func(){ console.log("Hello world") } } let es5 = new ES5Class() let es6 = new ES6Class() console.log("ES5 :") for(let _ in es5){ console.log(_) } // es6:不可枚举 console.log("ES6 :") for(let _ in es6){ console.log(_) }

这篇《JavaScript创建对象—从es5到es6》对这个问题的深入解释很好,推荐观看!

1.6 实现MVVM

题目:请简单实现双向数据绑定mvvm

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdyys.html