这里分享一份由字节前端面试官整理的「2021大厂前端面试手册」,内容囊括Html、CSS、Javascript、Vue、HTTP、浏览器面试题、数据结构与算法。全部整理在下方文档中,共计111道
HTML
-
HTML5有哪些新特性?
-
Doctype作⽤? 严格模式与混杂模式如何区分?它们有何意义?
-
如何实现浏览器内多个标签页之间的通信?
-
⾏内元素有哪些?块级元素有哪些? 空(void)元素有那些?⾏内元 素和块级元素有什么区别?
-
简述⼀下src与href的区别?
-
cookies,sessionStorage,localStorage 的区别?
-
HTML5 的离线储存的使用和原理?
-
怎样处理 移动端 1px 被 渲染成 2px 问题?
-
iframe 的优缺点?
-
Canvas 和 SVG 图形的区别是什么?
JavaScript
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
-
问:0.1 + 0.2 === 0.3 嘛?为什么?
-
JS 数据类型
-
写代码:实现函数能够深度克隆基本类型
-
事件流
-
事件是如何实现的?
-
new 一个函数发生了什么
-
什么是作用域?
-
JS 隐式转换,显示转换
-
了解 this 嘛,bind,call,apply 具体指什么
-
手写 bind、apply、call
-
setTimeout(fn, 0)多久才执行,Event Loop
-
手写题:Promise 原理
-
说一下原型链和原型链的继承吧
-
数组能够调用的函数有那些?
-
PWA使用过吗?serviceWorker的使用原理是啥?
-
ES6 之前使用 prototype 实现继承
-
箭头函数和普通函数有啥区别?箭头函数能当构造函数吗?
-
事件循环机制 (Event Loop)
1、声明变量时内存分配不同
原始类型:在栈中,因为占据空间是固定的,可以将他们存在较小的内存中-栈中,这样便于迅速查询变量的值
引用类型:存在堆中,栈中存储的变量,只是用来查找堆中的引用地址。
这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响
2、不同的内存分配带来不同的访问机制
在JavaScript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是传说中的按引用访问。
而原始类型的值则是可以直接访问到的。
3、复制变量时的不同
1)原始值:在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。
2)引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,
也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。(复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量)
4、参数传递的不同(把实参复制给形参的过程)
首先我们应该明确一点:ECMAScript中所有函数的参数都是按值来传递的。
但是为什么涉及到原始类型与引用类型的值时仍然有区别呢?还不就是因为内存分配时的差别。
1)原始值:只是把变量里的值传递给参数,之后参数和这个变量互不影响。
2)引用值:对象变量它里面的值是这个对象在堆内存中的内存地址.
因此它传递的值也就是这个内存地址,这也就是为什么函数内部对这个参数的修改会体现在外部的原因了,因为它们都指向同一个对象。
3. 数据类型判断
- typeof
typeof 基本可以正常判断基本数据类型,没法正确识别 Null,可以区分function,但是对于其他引用数据类型会返回 Object,这是因为 typeof 的原理:
-
所有数据类型在计算机中存储的都是按照“二进制”存储
-
Null -> 000000
-
对象都以 000 开头
-
typeof 检测的时候,是按照计算机存储的二进制来检测的
typeof null // “object”
typeof function(){} // “function”
typeof [] // “object”
typeof /./ // “object”
- instanceof
原理:根据原型对象来判断类型
function instanceof(left, right) {
const rightVal = right.prototype
const leftVal = left.proto
// 若找不到就到一直循环到父类型或祖类型
while(true) {
if (leftVal === null) {
return false
}
if (leftVal === rightVal) {
return true
}
leftVal = leftVal.proto // 获取祖类型的__proto__
}
}
首先需要了解JS的作用域链,内部可以访问外部的变量,但是外部却不可以访问内部的变量,所以当我们有需求访问函数内部的变量时,我们就需要利用闭包去访问。
因此可以明确闭包的四个特性:
-
闭包一定是函数对象
-
闭包和词法作用域,作用域链,垃圾回收机制息息相关
-
当函数一定是在其定义的作用域外进行的访问时,才产生闭包
-
闭包是由该函数和其上层执行上下文共同构成
我们可以通过最简单的闭包例子来分析
function foo() {
let a = 2;
function bar() {
console.log( a );
}
return bar;
}
console.log(a) // Uncaught ReferenceError: a is not defined
let baz = foo();
baz(); // 2
但是滥用闭包同样会造成弊端
- 内存泄漏(Memory Leak)
闭包阻止了垃圾回收机制对变量进行回收,因此变量会永远存在内存中,即使当变量不再被使用时,这样会造成内存泄漏,会严重影响页面的性能。因此当变量对象不再适用时,我们要将其主动释放,尤其是涉及 DOM 的操作时。
function foo() {
let a = 2;
function bar() {
console.log( a );
}
return bar;
}
let baz = foo();
baz(); //baz指向的对象会永远存在堆内存中
baz = null; //如果baz不再使用,将其指向的对象释放
- this指向不明
var object = {
name: ‘object’,
getName: function() {
return function() {
console.log(this.name)
}
}
}
object.getName()() // underfined
事件流分为3个阶段:
1 - 5 为捕获阶段
5 - 6 为目标阶段
6 - 10 为冒泡阶段
优点:
-
节省内存
-
新增对象无需再次绑定
实现方法: 通过给父元素增加监听器获取target,便可拿到子元素的标签名和class,id等属性,从而进行操作
例:
window.onload = function(){
var oUl = document.getElementById(‘ul1’)
oUl.onmouseover = function(ev){
var ev = ev || window.event
var oLi = ev.srcElemnt || ev.target
oLi.style.background = ‘red’
}
}
其中,
刷面试题
刷题的重要性,不用多说。对于应届生或工作年限不长的人来说,刷面试题一方面能够尽可能地快速自己对某个技术点的理解,另一方面在面试时,有一定几率被问到相同或相似题,另外或多或少也能够为自己面试增加一些自信心,可见适当的刷题是很有必要的。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
-
前端字节跳动真题解析
-
【269页】前端大厂面试题宝典
最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。大厂面试远没有我们想的那么困难,摆好心态,做好准备,你也可以的。