传送门
- 直通互联网大厂前端面试系列(零)——目录总纲
- 直通互联网大厂前端面试系列(一)——HTML/CSS
- 直通互联网大厂前端面试系列(二)——JS / ES6+
- 直通互联网大厂前端面试系列(三)——网络基础
- 直通互联网大厂前端面试系列(四)——主流框架
- 直通互联网大厂前端面试系列(五)——算法
写在前面
JavaScript
= ECMAScript
+ DOM
(文档对象类型) + BOM
(浏览器对象类型)。我们的重头戏来了,因为JS的内容实在太多了,所以我把算法、框架、网络部分的内容都放到了后面的分类里,这样也有利于我们的聚焦。
ES的变化可谓相当之快,2015年后每年一个版本(BOM和DOM相对变化不大)。多亏了babel,我们可以很愉快的使用ES的最新特性,而不用考虑兼容性的问题,相应的,我们每年都要学习一些新的语法。既然选择了前端,那持续学习是跑不了的了,同学们做好心理准备,心里默念,我们是最pang棒的!
长期如何学习
如果你之前有过编码经验,那么你一定知道我下面说的有多重要
- 深入底层原理,JS也是一门编程语言,只要是编程语言其本质一定是相通的,这一点无论学习任何一种语言都是必然的。虽然是老生常谈,但是真理往往都是经得住岁月考验的。你理解的深度,决定了你以后的高度,出来混迟早要还的,缺的课早晚要补回来的。
- 注意编码规范,建议越早使用eslint越好,推荐最严格的airbnb的标准,它可以非常有效地规范你的代码风格。良好的代码风格能够让你少写bug,快速修复bug,让别人替你修完bug少骂几句娘。就冲这几点!够不够?!够不够?!
- 多看经典的书,看书绝对是提升自己思维高度的最佳途径。私以为经过了一段时间的实战,再去看书,才是最有效果的。因为这时候是带着问题去看书的,每当看到与问题相呼应的地方,一定会有一种茅塞顿开的感觉,记忆尤其深刻。对于新手来说,多加练习反而才是重要的,要在实战中多积累问题,多思考,这也算是一种厚积薄发。不过呢,有些书即使是新手也是必须看的,“前端圣经”系列要是没看过的话,实在是有点说不过去了。另外,针对老鸟,我推荐两本让我记忆深刻的书《鸟哥的linux私房菜》、《码农翻身》。
短期如何突击
短期能突击的,就是几个最容易考的难点,无论你是老鸟还是菜鸟,面试前最好都突击一下,这些必考:
- js数据类型及判断
- 闭包与作用域
- this与执行上下文
- 原型链与继承(原型、构造函数、实例)
- 异步任务
- ES6+常用特性
别看知识点就这么几个,围绕着它们出的题可谓变化无穷,想当年我随便见到它们其中一个,都会腿发抖。那么让我们来看一下它们能变化到什么程度
临阵如何磨枪
JS的题一定是占了面试绝大部分内容的,毕竟平时80%以上的开发时间都是用的它,最后强调一遍,下面的题,一定要保证每个知识点都弄明白了,这些题值得反复地做。不怕做的慢,一定不要自欺欺人。哪怕一天能啃下来一道题,也是可以接受的。
请说出以下代码打印的结果
if (1 == true) {console.log(1);};
if (1 === true ) {console.log(2);};
if ([]) {console.log(3);};
if ([] == []) {console.log(4);};
if ([] === []) {console.log(5);};
if (undefined == null) {console.log(6);};
if ('' == null) {console.log(7);};
if (NaN == NaN) {console.log(8);};
追问:
- JS的数据类型有哪些?哪些是引用类型?它们有什么特点?
- 什么是浅拷贝?什么是深拷贝?请用JS实现一个深拷贝
- 如何判断数组类型?方法越多越好
- typeof 和 instanceof 有什么区别?
- == 和 === 有什么区别?==时发生了什么?
- 函数中的 arguments 是数组吗?若不是,如何将它转化为真正的数组
- 请说下Array的forEach、map、every、some、filter、reduce各有什么功能
- 如何遍历一个对象?方法越多越好
以下代码的结果是什么?请解释你的答案。
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function () {
return this.fullname;
}
}
};
console.log(obj.prop.getFullname());
var test = obj.prop.getFullname;
console.log(test());
实现Function.prototype.bind方法, 使得以下程序最后能输出’success’
function Animal(name, color) {
this.name = name;
this.color = color;
}
Animal.prototype.say = function () {
return `I'm a ${this.color} ${this.name}`;
};
const Cat = Animal.bind(null, 'cat');
const cat = new Cat('white');
if (cat.say() === 'I\'m a white cat' && cat instanceof Cat && cat instanceof Animal) {
console.log('success');
}
追问:
- bind、call和apply有什么区别?
- 什么是闭包?请实现一个“有缓存功能”的加法
- 请用JS实现throttle(函数节流)函数。函数节流解释: 对函数执行增加一个控制层,保证一段时间内(可配置)内只执行一次。此函数的作用是对函数执行进行频率控制,常用于用户频繁触发但可以以更低频率响应的场景
- debounce和throttle的区别?请用JS实现debounce
- es6中的箭头函数与普通函数有什么区别?
请用至少2种方法,实现Cat继承Animal的属性,并比较各方法的优缺点
function Animal() {
this.species = "动物";
}
function Cat(name, color) {
this.name = name;
this.color = color;
}
追问:
- 什么是原型链?什么是原型对象?
- JS的最顶层对象是什么?它的原型对象是什么?
- 什么是构造函数?什么是实例?
- 如何通过一个实例访问它的构造函数及原型对象?
- new一个实例,经历了什么过程?
- es6中的static的作用是什么?用es5如何实现?
以最小的改动解决以下代码的错误(可以使用es6)
const obj = {
name: " jsCoder",
skill: ["es6", "react", "angular"],
say: function () {
for (var i = 0, len = this.skill.length; i < len; i++) {
setTimeout({
console.log('No.' + i + this.name);
console.log(this.skill[i]);
console.log('--------------------------');
}, 0);
console.log(i);
}
}
};
obj.say();
/*
期望得到下面的结果:
1
2
3
No.1 jsCoder
es6
--------------------------
No.2 jsCoder
react
--------------------------
No.3 jsCoder
angular
--------------------------
*/
追问:
- 如果不修改,会打印出什么结果?
- let、const、var有什么区别?
- 什么是函数作用域?还有什么其他作用域?如何工作的?
请说出以下代码打印的结果
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start’);
setTimeout(function() {
console.log('setTimeout');
}, 0);
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
追问:
- JS单线程是怎么运作的?请说下“异步”和“同步”的区别
- 处理异步任务的方法有哪些?
- 如何将一个普通异步函数封装为Promise?
- 请实现一个同步的delay方法