最近我一直在准备系统的梳理一遍前端知识,为之后进大厂做准备。这个面试总结系列是我查看了多篇博客所累积的知识点,也是我之前没有认真去理解过的知识点,希望和小伙伴们一起分享,一起加油努力,希望这个4月能有好消息,加油。
1.对语义化的理解
2.浏览器内核的理解
3.cookies, sessionStorage 和localStorage 的区别
4.闭包的理解
(function(i){
//某某内部使用了i的函数
})(i);
5.作用域链、原型链的理解
原型链:每个函数都有prototype 属性(显式原型属性),除了 Function.prototype.bind()
,该属性指向原型。每个对象都有 __proto__
属性(隐式原型属性),指向了创建该对象的构造函数的原型。
总结
Object 是所有对象的爸爸,所有对象都可以通过 proto 找到它
Function 是所有函数的爸爸,所有函数都可以通过 proto 找到它
Function.prototype 和 Object.prototype 是两个特殊的对象,他们由引擎来创建
除了以上两个特殊对象,其他对象都是通过构造器 new 出来的
函数的 prototype 是一个对象,也就是原型
对象的 proto 指向原型, proto 将对象和原型连接起来组成了原型链
6.如何实现继承
一般我们把属性方法构造函数中,把方法挂在prototype下面,对象的
__proto__指向构造函数的prototype,原型链的终点为Object.prototype,再往上Object.prototype.proto=null
Child.prototype = new Parent("qy")
//为了不破坏原型链,将Child的constructor指向本身
Child.prototype.constructor=Child
子类与父类的关系为指向关系,实例是子类的实例,也是父类的实例 父类新增的原型方法或属性,子类都能访问。
子类不能拥有自己的属性,如果有多个实例时,其中一个实例修改了父类引用类型的值,那么所有的实例都会发生改变。
function Child(name){
Parent.call(this,name)
}
var child=new Child("qy")
解决了原型链继承中的子类共享父类属性的问题
创建的子类实例可以向父类传递参数
实例是子类的实例,不是父类的
只能继承父类的实例属性和方法,不能继承父类原型上的方法
无法实现函数复用,每个子类都有父类函数的属性和方法的副本,当child调用Parent上的方法时,Parent内部的this指向的是child,Parent内部的this上的属性和方法都被复制到了child上面
function Child(name) {
Parent.call(this,name) //构造继承 ,第二次调用父类
}
//原型链继承
Child.prototype=new Parent()
Child.prototype.constructor=Child
var child=new Child("qy") //子类的实例向父类传递参数,第一次调用父类
console.log(child.name)
child.introduce()
child.hobby("sing")
console.log(child instanceof Parent) //true
console.log(child instanceof Child) //true
子类可向父类传参
实例既是子类的实例,也是父类的实例
多个实例之间不存在公用父类的引用属性的问题
实例可以继承父类实例的属性和方法,也可以继承原型上的属性和方法
缺点:这种方式调用了两次父类的构造函数,生成了两份实例,相同的属性既存在于实例中也存在于原型中
function Child(name){
var parent = new Parent(name);
for(var key in parent){
Child.prototype[key] = parent[key];
}
}
支持多继承
效率很低,内存占用高
无法获取父类不可枚举的方法
function Child(name) {
Parent.call(this,name) //构造继承
}
(function(){
//创建一个临时的类
var Temp=function(){}
Temp.prototype=Parent.prototype
//子类的原型指向父类的实例
Child.prototype=new Temp() //原型链继承
})()
class Parent{
constructor(name){
this.name=name
}
introduce(){
console.log("my name is " + this.name)
}
hobby(hobby){
console.log(this.name + " like " + hobby)
}
}
class Child extends Parent{
constructor(name,age){
super(name) //构造继承,可以继承Parent构造函数上的属性
this.age=age
}
}
在这个方法中使用extends 和 super 两个关键字,在子类的constructor方法中调用super方法,用来继承父类的this对象
实现原理:
先将父类实例 的属性方法加到this上(super),然后再用子类的构造函数修改this
7.对this的理解
**new的过程:**
创建一个新对象: 如:var person = {};
链接到原型: 新对象的_proto_属性指向构造函数的原型对象
绑定this: this对象指向新对象
返回新对象
8.web安全
9.跨域问题的解决
10.CommonJS、AMD、ES6模块化的区别
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
11.对象的拷贝
12.防抖与节流
// 防抖函数
function debounce(fn) {
let timeout = null;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.call(this, arguments);
}, 1000);
}
}
/*
* 节流函数生成器
* 传递事件处理函数和延迟时间
* 返回节流函数
*/
function throttleGen(fn, delay) {
let timer = null;
function throller() {
if (timer === null) {
timer = setTimeout(() => {
fn();
timer = null;
}, delay)
}
}
return throller;
}
13.babel编译原理
14.从输入URL到页面展示的过程
15.TCP三次握手
建立连接前,客户端和服务端需要通过握手来确认对方:
16.TCP四次挥手
17.强缓存和协商缓存(浏览器缓存)
var a=[],b=[]
function push(node)
{
a.push(node);
}
function pop()
{
var t=[]
//如果在a栈push到b栈之前,b栈中有元素,先要将b中元素倒出来放到t中,
//把a栈中元素全部倒入空的b栈中后,再把t中的元素倒回b栈中
if(b.length>0){
while(b.length>0){
t.push(b.pop())
}
}
while(a.length>0){
right.push(a.pop());
}
if(t.length>0){
while(t.length>0){
b.push(t.pop())
}
}
return b.pop();
}
20.prefetch和preload
<link rel="preload" href="/path/to/style.css" as="style">
preload 不会阻塞 windows 的 onload 事件
对跨域的文件进行preload时,必须加上 crossorigin 属性
。它的作用是告诉浏览器加载下一页面可能会用到的资源。因此该方法的加载优先级非常低,也就是说该方式的作用是加速下一个页面的加载速度。所以,对于当前页面很有必要的资源使用 preload,对于可能在将来的页面中使用的资源使用 prefetch。