下面是 2021年面试准备的内容,有的是看大佬文章视频总结,有的是按自己理解.....如有错误内容可以在评论区留言,我看到会及时更正,逐渐抽空补全当中.....
一.CSS3
盒子水平垂直居中5大方案
水平:
1.text-align:center(对行内内容有效,必须将子元素设置为 display: inline; 或者 display: inline-block; )
2.margin: 0 auto;(必须定宽)
3.绝对定位实现(代码较多;脱离文档流;使用margin-left需要知道宽度值;使用transform兼容性不好(ie9+)。记得好像是回引起重绘??)
#parent{
height: 200px;
width: 200px; /*定宽*/
position: relative; /*父相*/
background-color: #f00;
}
#son{
position: absolute; /*子绝*/
left: 50%; /*父元素宽度一半,这里等同于left:100px*/
transform: translateX(-50%); /*自身宽度一半,等同于margin-left: -50px;*/
width: 100px; /*定宽*/
height: 100px;
background-color: #00ff00;
}
4.最爱的flex(pc端兼容不好 移动端ok)
#parent{
display: flex;
justify-content: center;
}
垂直:
1.line-height(只能用于单行行内内容;要知道高度的值)
2.vertical-align: middle; (需要添加font-size: 0; 才可以完全的垂直居中;需要给它的父元素设置display: table; 才生效;table-cell不感知margin,在父元素上设置table-row等属性,也会使其不感知height;设置float或position会对默认布局造成破坏,可以考虑为之增加一个父div定义float等属性;内容溢出时会自动撑开父元素 建议看下vertical-align和line-height的关系)
#parent{
height: 150px;
line-height: 150px;
font-size: 0;
}
img#son{vertical-align: middle;} /*默认是基线对齐,改为middle*/
======================================================
#parent{
display: table-cell;
vertical-align: middle;
}
3.绝对定位(和上面水平差不多)
4.flex(和上面水平差不多)
#parent{
display: flex;
align-items: center;
}
或
#parent{display: flex;}
#son{align-self: center;}
水平垂直:
1.text-align: center; vertical-align: middle;
#parent{
height: 150px;
line-height: 150px; /*行高的值与height相等*/
text-align: center;
font-size: 0; /*消除幽灵空白节点的bug*/
}
#son{
/*display: inline-block;*/ /*如果是块级元素需改为行内或行内块级才生效*/
vertical-align: middle;
}
2.display: table-cell;(缺点同水平)
#parent{
height: 150px;
width: 200px;
display: table-cell;
vertical-align: middle;
/*text-align: center;*/ /*如果是行内元素就添加这个*/
}
#son{
/*margin: 0 auto;*/ /*如果是块级元素就添加这个*/
width: 100px;
height: 50px;
}
4.绝对定位(代码较多;脱离文档流)
#parent{
position: relative;
}
#son{
position: absolute;
margin: auto;
width: 100px;
height: 50px;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
5.flex
#parent{
display: flex;
}
#son{
margin: auto;
}
或
#parent{
display: flex;
justify-content: center;
align-items: center;
}
或
#parent{
display: flex;
justify-content: center;
}
#son{
align-self: center;
}
关于CSS3几道面试题
标准盒模型,ie盒模型;
清除浮动;
BFC
px,em,rem
经典布局(圣杯,双飞翼)
二.HTML5
语义化标签类
音视频处理
canvas/webGL
history API
requestAnimationFrame
地理位置
web scoket
三.永远的Javascript
一堆栈内存及闭包作用域
JS的8种数据类型及区别
基本类型:number string boolean,null,undefined
引用类型:function,object
特殊(es6新加):symbol
JS堆栈内存的运行机制
堆:存储引用类型值的空间 栈:存储基本类型值和指定代码的环境
变量提升(var function)es5
在代码执行之前,在当前作用域当前执行上下文,所有带var function关键字的变量提前声明 声明定义
作用域、作用域链
闭包的两大作用:保护/保存
JS编译机制:VO/AO/GO
JS高级编程技巧:惰性函数/柯里化函数/高级函数
几道面试题
1.
//###example1
let a={},
b='1'
c=1
a[b]='AAAA'
a[c]='BBBB'
console.log(a[b])//BBBB
//=》对象和数组区别
//###example2
let a={},
b=Symbol('1')
c=Symbol('1')
a[b]='AAAA'
a[c]='BBBB'
console.log(a[b])//AAAA
//=》实现symbol
//###example3
let a={},
b={
n:'1'
},
c={
m:'2'
}
a[b]='AAAA'
a[c]='BBBB'
console.log(a[b])//AAAA
//=》Object.prototype.toString()
2.
var test=(function(i){
return function(){
alert(i*=2)
}
})(2);//创建并立即执行
test(5)///'4' *************注意alert输出字符串(细节决定成败)
3.
var a=0,
b=0;
function A(a){
A=function(b){
alert(a+b++);
};
alert(a++)
}
A(1)
A(2)
4.
对象数组深浅克隆
let obj={
a:'AAA',
b:['BBB',1,1,2,3],
c:{c:xx,}
d:/^\d+$/
}
let obj2={}
//浅克隆
obj2={...obj};
for(let i in obj){
if(!obj.hasOwnProperty(i))break;
obj2[i]=obj[i]
}
//深克隆
let obj2=JSON.parse(JSON.stringify(obj))//函数、正则、日期new Date()不能用,=》弊端
function deepClone(obj){
//过滤特殊情况
if(obj===null) return null
if(typeof obj!=='object') return obj
if(obj instanceof RegExp){
return new RegExp(obj);//*********注意不能返回obj,不然地址一样是浅克隆
}
if(obj instanceof Date){
return new Date(obj);//*********注意
}
//不直接创建空的对象,为了克隆结果和之前保持相同的所属类
let newObj=new Object();//new obj.constructor==>有什么好处???
for(let key in obj){
if(obj.hasOwnProperty(key)){
newObj[key]=deepClone(obj[key])
};
}
return newObj
}
5.
function Foo(){
getName=function(){
console.log(1);
}
retune this;
}
Foo.getName=function(){
console.log(2);
}
Foo.prototype.getName=function(){
console.log(3);
}
var getName=function(){
console.log(4);
}
function getName(){
console.log(5);
}
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
二面向对象和this处理
单例设计模式
类和实例
原型/原型链
new运算符的实现机制
函数调用的方法一共有 4 种:
- 作为一个函数调用
- 函数作为方法调用
- 使用构造函数调用函数
- 作为函数方法调用函数(call、apply) new 的过程:
- 创建一个空对象 obj;
- 将新创建的空对象的隐式原型指向其构造函数的显示原型。
- 使用 call 改变 this 的指向
- 如果无返回值或者返回一个非对象值,则将 obj 返回作为新对象;如果返回值是一个新对象的话那么直接直接返回该对象。
var a = new myFunction("Li","Cherry");
new myFunction{
var obj = {};
obj.__proto__ = myFunction.prototype;
var result = myFunction.call(obj,"Li","Cherry");
return typeof result === 'obj'? result : obj;
}
call/apply/bind
改变this指向方法: 改变 this 的指向我总结有以下几种方法:
- 使用 ES6 的箭头函数
- 在函数内部使用 _this = this
- 使用 apply、call、bind
- new 实例化一个对象
在 MDN 中定义 apply 如下;
apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数。 fun.apply(thisArg, [argsArray])
call 的语法为:
fun.call(thisArg[, arg1[, arg2[, ...]]])
其实 apply 和 call 基本类似,他们的区别只是传入的参数不同, call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。
MDN 中定义 bind 如下:
bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
bind 是创建一个新的函数,我们必须要手动去调用
示例:
//example1
var a ={
name : "Cherry",
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.apply(a,[1,2]) // 3
//example2
var a ={
name : "Cherry",
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.call(a,1,2) // 3
//example3
var a ={
name : "Cherry",
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.bind(a,1,2)() // 3
constructor构造函数模式
JS中this五种情况的综合梳理
JS的4种数据类型检测方案
typeof
typeof '5' // string
typeof 5 // number
typeof null // object*************************注意
typeof undefined // undefined
typeof true // boolean
typeof Symbol('5') // symbol
typeof 5n // bigint
typeof new Object(); // object
typeof new Function(); // function
【#】null被认为是一个空对象,因此返回了object,因为任何对象都会被转化为二进制,null转为二进制则表示全为0,如果前三个均为0,js就会把它当作是对象,这是js早期遗留下来的bug。
instanceof
[] instanceof Array; // true
//[].proto 的原型 是指向Array.prototype 的,说明两个对象是属于同一条原型链的,返回true
[] instanceof Object; // true
function Person() {};
const person = new Person();
person instanceof Person; // true
person instanceof Object; // true
//person和Object是属于原型链的关系
let obj1 = {}
console.log(obj1 instanceof Object) // true
let obj2 = Object.create(null)
console.log(obj2 instanceof Object) // false*******************注意
let obj3 = Object.create({})
console.log(obj3 instanceof Object) // true
【#】只能用来判断变量的原型链上是否有构造函数的prototype属性(两个对象是否属于原型链的关系),不一定能获取对象的具体类型,Instanceof 不适用判断原始类型的值,只能用于判断对象是否从属关系。
constructor
//原理:每一个实例对象都可通过constructor来访问它的构造函数,其实也是根据原型链的原理来的。注意---undefined和null是无效的对象,因此是没有constructor属性的,这两个值不能用这种方法判断.
'5'.__proto__.constructor === String // true
[5].__proto__.constructor === Array // true
undefined.__proto__.constructor // Cannot read property '__proto__' of undefined
null.__proto__.constructor // Cannot read property '__proto__' of undefined
toString
//因为实例对象有可能会自定义toString方法,会覆盖Object.prototype.toString,所以在使用时,最好加上call.*********注意
Object.prototype.toString.call('5') // [object String]
Object.prototype.toString.call(5) // [object Number]
Object.prototype.toString.call([5]) // [object Array]
Object.prototype.toString.call(true) // [object Boolean]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(null) // [object Null]
Object.prototype.toString.call(new Function()); // [object Function]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(new RegExp()); // [object RegExp]
Object.prototype.toString.call(new Error()); // [object Error]
【#】Object.prototype.toString方法返回对象的类型字符串,因此可用来判断一个值的类型。所有的数据类型都可以使用此方法进行检测,且非常精准
JS继承方案(深浅拷贝)
1.原型链继承
2.借用构造函数继承
3.组合继承
4.原型式继承
5.寄生式继承
6.寄生组合式继承
7.混入方式继承多个对象
8.ES6类继承extends
几道面试题
三dom/bom及事件处理机制
DOM/BOM的核心操作
事件对象
拖拽及拖拽插件封装
发布订阅设计模式
JQ部分源码理解
事件传播机制和事件代理
DOM2级事件的核心运行机制
移动端Touch、Gesture事件及封装处理
浏览器底层渲染机制和DOM的回流重绘
DIALOG模态框组件的封装
四.框架(我自己用的vue)
组件通信
vue2
双向数据绑定
vue3
双向数据绑定
script setup
mvc和mvvm区别
五.webpack
六.算法
数组、对象去重
排序(冒泡、选择、快排)
数组扁平化N种方法及优缺点
涉及递归的几道题
斐波那契数列
七.es6-9
let const var
注意使用区别和变量提升
箭头函数Arrowfunction
注意箭头函数不能被new。
this的指向问题
解构赋值和拓展运算符
set、map数据结构
promise设计模式
回调函数本身并没有问题,它的问题出现在多个回调函数嵌套。假定读取A文件之后,再读取B文件,代码如下。
fs.readFile(fileA, function (err, data) {
fs.readFile(fileB, function (err, data) {
// ...
});
});
不难想象,如果依次读取多个文件,就会出现多重嵌套。代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。这种情况就称为"回调函数噩梦"(callback hell)。
Promise就是为了解决这个问题而提出的。它不是新的语法功能,而是一种新的写法,允许将回调函数的横向加载,改成纵向加载。采用Promise,连续读取多个文件,写法如下。
var readFile = require('fs-readfile-promise');
readFile(fileA)
.then(function(data){
console.log(data.toString());
})
.then(function(){
return readFile(fileB);
})
.then(function(data){
console.log(data.toString());
})
.catch(function(err) {
console.log(err);
});
上面代码中,使用了 fs-readfile-promise 模块,它的作用就是返回一个 Promise 版本的 readFile 函数。Promise 提供 then 方法加载回调函数,catch方法捕捉执行过程中抛出的错误。
可以看到,Promise 的写法只是回调函数的改进,使用then方法以后,异步任务的两段执行看得更清楚了,除此以外,并无新意。
Promise 的最大问题是代码冗余,原来的任务被Promise 包装了一下,不管什么操作,一眼看去都是一堆 then,原来的语义变得很不清楚。-->>如何优化???
async、await及实现原理
Generator生成器函数
www.ruanyifeng.com/blog/2015/0…
interator迭代器和for..in for..of循环
promise A++规范
js底层运行机制:单线程和同步异步编程
异步编程对 JavaScript 语言太重要。JavaScript 只有一根线程,如果没有异步编程,根本没法用,非卡死不可。
以前,异步编程的方法,大概有下面四种。
- 回调函数
- 事件监听
- 发布/订阅
- Promise 对象
对异步理解:简单说就是一个任务分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。比如,有一个任务是读取文件进行处理,异步的执行过程就是下面这样。
连续的执行,就叫做同步。
js底层运行机制:微任务宏任务和事件循环机制
执行顺序:微任务-》宏任务-》主程序 event queue(micro-task:promise,async,await ,macro-task:定时器,事件绑定)
几道面试题
1.
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(){
console.log('Promise1');
resolve();
}).then(function(){
console.log('Promise2')
});
console.log('script end')
2.
3.
八.AJAX/HTTP前后端数据交互
AJAX核心4步操作
get、post核心机制与区别
get和post虽然本质都是tcp/ip,但两者除了在http层面外,在tcp/ip层面也有区别。get会产生一个tcp数据包,post两个。
具体就是:
get请求时,浏览器会把headers和data一起发送出去,服务器响应200(返回数据), post请求时,浏览器先发送headers,服务器响应100 continue, 浏览器再发送data,服务器响应200(返回数据)。
再说一点,这里的区别是specification(规范)层面,而不是implementation(对规范的实现)
TCP三次握手、4次握手
http的本质就是tcp/ip请求,.需要了解3次握手规则建立连接以及断开连接时的四次挥手,tcp将http长报文划分为短报文,通过三次握手与服务端建立连接,进行可靠传输。 三次握手的步骤:(抽象派)
客户端:hello,你是server么?
服务端:hello,我是server,你是client么
客户端:yes,我是client
建立连接成功后,接下来就正式传输数据,然后,待到断开连接时,需要进行四次挥手(因为是全双工的,所以需要四次挥手)
四次挥手的步骤:(抽象派)
主动方:我已经关闭了向你那边的主动通道了,只能被动接收了
被动方:收到通道关闭的信息
被动方:那我也告诉你,我这边向你的主动通道也关闭了
主动方:最后收到数据,之后双方无法通信
tcp/ip的并发限制:
- 浏览器对同一域名下并发的tcp连接是有限制的(2-10个不等)
- 而且在http1.0中往往一个资源下载就需要对应一个tcp/ip请求
- 所以针对这个瓶颈,又出现了很多的资源优化方案
axios库和源码
fetch基础和应用
前端跨域9种方案(非同源策略请求)
协议、域名、端口号
- 同源策略请求(部署到web服务器) ajax、fetch
- 跨域请求(服务器拆分) 1.JSONP(缺点:只能get-》优化??) 2.CORS 3.postMessage 4.websocket 5.Node中间件代理 6.nginx反向代理 7.window.name+iframe 8.location.hash+iframe 9.document.domain+iframe