0%

前端知识强化总结

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
1.什么是CSS继承 .CSS选泽器是什么?
就是父级设置了一些属性,子级继承了父级的该属性 // CSS选择器用来对选定的页面元素进行样式修改。
选择器有哪些?
类型选择器
通配选择器 1
类选择器
id选择器
标签属性选择器
伪类选择器:a:link :fist-child 10
伪元素选择器:placeholder ::before,::after 1
后代选择器
子代选择器
伪元素选择器添加了一个页面中没有的元素(只是从视觉效果上添加了,不是在文档树中添加),伪类是给页面中已经存在的元素添加一个类。
2.面试口诀:一绝三香(相)
px: 绝对单位,网页开发基本长度单位
em: 相对单位,相对当前盒子字体大小进行计算
rem: 相对单位,相对根元素html字体大小进行计算
vw+vh: 相对单位,相对当前网页视口宽度和高度进行计算

px em rem之间的转换关系
默认情况下1rem = 1em = 16px
根元素字体修改情况下1rem = 根元素字体大小
当前盒子字体修改情况下1em = 当前盒子字体大小
em和rem的使用场景
o em:通常用于字体缩进
o rem:配合媒体查询处理移动端适配问题 ***
3.css如何实现左边定宽,右边自适应
1、将盒子外面的容器设为flex布局,右边盒子设置flex属性值为1 这样就会自动撑满
2、将盒子外面的容器设为table布局,将左右盒子的display都设置为table-cell
4.css实现绝对居中
1、盒子容器设置相对定位,盒子设置绝对定位 top和left都设置50% 之后再设置margin-left和margin-top为盒子大小的一半
2、盒子容器设置相对定位,盒子设置绝对定位 四个方向(top、left、bottom、right都设置为0),margin设置为auto即可
3、盒子容器设置相对定位,盒子设置绝对定位 top和left都设置50% 设置transform属性,属性值为translate(-50%,-50%)
4、盒子容器flex布局,设置justify-content属性和align-items属性,属性值都设为center(内部盒子水平,垂直方向居中)
justify-content设置主轴上的子元素排列方式
align-items 设置侧轴上的子元素排列方式(单行)
总结:前两种内部的盒子定宽高,后两种不定宽高
5、清除浮动的方法有哪些,各有什么缺点?
如下图 添加clear属性
原理: 设置清除浮动以后,浏览器会自动为元素添加一个上外边距, 以使其位置不受其他元素的影响。
清除浮动布局场景下的知识深度和广度? 深度:我们不仅可以实现清除浮动,还可以知道他们的优点和缺点,广度就是可以使用多种方式实现
6、如何用CSS画一个三角形?
css实现三角形的核心是用无宽高盒子的border
透明边框第一步四个方向全部透明边框,
箭头方向:第二步选择箭头方向,箭头指向和有色边框方向相反
border: 10px solid transparent;
border-left: 10px solid #f40;使用border去画三角形
场景就是淘宝上方导航栏的标题右上角都有一个小三角
border-bottom 代表箭头向上
border-top 代表箭头向下
border-left 代表箭头向右
border-right 代表箭头向左
第二种方法是创建一个盒子 将其设置为相对定位,盒子前添加一个伪元素设置成绝对定位,将其绕着左下顶点进行顺时针旋转45度,父元素设置overflow:hidden属性将超出盒子外的部分进行裁剪就能形成一个三角形
说出为什么要用css画三角形的原因(出于页面性能考虑,避免发送过多的http请求,节省带宽)
7、css提高页面性能的方法有哪些?
1.属性设置使用简写 (给margin设置四个方向的时候可以简写为 margin:上右下左)
2.用CSS替换图片比如用css画一个三角形来替换图片 (避免发送过多的http请求,节省带宽)
3.删除不必要的零和单位 (0.2写成.2 20.0写成20
4.用CSS精灵图替代单个文件加载(利用背景定位在CSS精灵图拿到自己想要的图标(一个请求) ,项目加载的时候就要发送http请求,)

1.属性简写目的:减小生产包体积
2.图标替换目的:减少http请求/节约带宽
3.删除零和单位目的:减小生产包体积
4.背景图使用雪碧图目的:减少http请求/节约带宽
8、BFC解决了哪些问题(BFC:一块独立渲染区域,内部元素的渲染不会影响边界以外的元素)
1.垂直方向外边距重叠的问题。
2.子元素浮动,父元素高度塌陷问题。
触发BFC:
浮动元素:float 除 none 以外的值 有局限性:高度不塌了但是脱离文档流了,宽度也就丢失了,对应特点的第三条 -不推荐
绝对定位元素:position (absolute、fixed)
display 为 inline-block、table-cells、flex -不推荐 设置弹性布局
overflow 除了 visible 以外的值 (hidden、auto、scroll) -推荐
开启BFC后的特点:
1.开启BFC的元素不会被浮动元素所覆盖
2.开启BFC的元素子元素和父元素外边距不会重叠
3.开启BFC的元素可以包含浮动的子元素

image-20211221161602539

img

image-20211221195541177

image-20211221200057153

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
9、为什么把bind,call,apply放在一起?有什么区别(相同点,不同点)  干什么的?:用来改变this的指向的
var name = 'fff'
function say(){
var name = 'ddd'
log('this.name',this.name)
}
say() //输出的是fff 因为say相当于window.say()
相同点:bind,call,apply都可以改变this指向
不同点:call和apply的传参方式不同(前者挨个传,后者传入一个数组)/bind(返回的是绑定this一个函数)和call,apply的返回值不同
apply、call 则是返回函数调用立即执行
#三、实现
call的应用场景
*判断数据类型
const array = [1,2,3,4];
const type = 0bject.prototype.toString.call(array);
console.log('type', type)//[object,Array]
*类数组转数组
const arrayLike={
0:'name',
1:'age',
2:'gender',
length:3
}//以上就是类数组 看似数组,本身不是数组
const res = Array.prototype.slice.call(arrayLike) //['name','age','gender']

apply 应用场景
对给定数组求最大值/最小值
const array = [1,2,3,4,5]
const max = Math.max.apply(null,array)//null为this的指向 输出结果为5 min为最小值

bind应用场景
通常用在react项目的组件中
利用bind函数将this的指向指向组件的实例

10、如何使用多种方式实现数组去重 分普通数组和对象数组
array = [1,2,3,4,5]
indexOf 查找项的下标 没找到-1
filter 返回值[]
sort 返回值[] 接收两个参数 返回a-b 从小到大排序
reduce 返回值[] const res = array.reduce(function(prev,current){return prev+current})//不断更新prev 输出15
push 返回值length
const array = [1,2,3,4,5,2,3]

过滤解决
function unique(array) {
if( !Array.isArray(array)){
throw new Error( "unique function params is not Array")}
return array.filter((item,index)=>{
return array.index0f(item)===index //当拿到倒数第二个2的时候获取的下标是第二个2的下标,就会将其过滤
})
}
const res = unique(array) //输出的是[1,2,3,4,5] 实现去重

排序解决
function unique(array) {
if(!Array.isArray(array)){
throw new Error( "unique function params is not Array")}
array = array.sort() //先进行排序
let res=[];
for(let i=0;i<array.length;i++){
if(array[i]!==array[i-1]){
res.push(array[i])
}
}
return res
}
const res = unique(array) //输出的是[1,2,3,4,5] 实现去重

解构赋值解决 (先转化为集合 集合里的元素就已经是唯一的了 然后再解构赋值)
function unique(array) {
if(!Array.isArray(array)){
throw new Error( "unique function params is not Array")}
return [...new Set(array)]

}
const res = unique(array) //输出的是[1,2,3,4,5] 实现去重



11.怎么对给定数组求最大值
应用场景:数据处理的时候可以用到给定数组求最大值
Math.max()方法
const array = [1,2,3,4,5]
const res = Math.max(...array) ***
或者借用这个函数 const res = Math.max.apply(null,array)

reduce函数方法
function getMax(array){
return array.reduce((prev,current)=>{
return current>prev?current : prev
或者return Math.max(prev,current)
})
}
const res = getMax(array)


sort()排序方法
function getMax(array){
const result = array.sort()
return result[result.length-1] //数组的最后一项
}
const res = getMax(array)
考察的是对基本的数据处理能力

12.JS中判断数据类型的方式有哪些?
typeof
优点:使用简单 也不精确 比如 typeof [] 会输出Object(数组本身就)
缺点:功能残缺,只能用来判断6种数据类型:string,number,boolean,undefined,symbol,function
type of null symbol 的值是通过 Symbol() 函数生成,每一个 symbol 的值都是唯一的

Object.prototype.toString.call
优点:适用于判断所有数据类型
缺点:使用上相对typeof而言比较繁琐

instanceof(排除):instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上

js中判断数据类型的场景?
根据接口/返回参数类型/做区别处理。
js中的数据类型有些哪些?
基本数据类型:StringNumberBooleanSymbolundefinedNull
引用数据类型:ObjectArrayFunction

13.如何实现函数节流 (项目优化)
函数节流:规定在一个单位时间内,事件响应函数只能被触发一次。如果这个单位时间内触发多次函数,只有一次生效
使用场景:window.onresize事件 该事件是浏览器的视口不断被放大缩小的时候触发的
mousemove事件,鼠标拖动事件
这两个事件不断别触发 导致性能开销过大 因此要使用函数节流
window.onresize():函数节流
单位时间内触发一次
1.返回值是一个函数
2.开启定时器
3.如果定时器存在,直接返回false
4.定时器内部清空定时器,并且把timer置为null 然后执行我们的事件响应函数
function throttle(fn,interval) {
var timer;
return (event)=>{
if (timer){
return false;
}
timer = setTimeout(()=> {
clearTimeout(timer);
timer = null;
fn(event)},
interval);
}
}
window.onresize = throttle(function(event)){
log(event)
}

//上面的fn 指的就是(function(event)){log(event)} 本身没有返回值 所以上面调用的时候要return一个函数 把fn放在函数里执行的话就是输出log

14.如何实现函数防抖
事件防抖:事件被触发n秒后再执行回调,如果在这n秒执行过程中又被触发,则会把之前的事件响应清除掉,事件函数只执行一次。
使用场景:网站商品搜索框
1.返回值是一个函数
2.事件响应函数式在固定间隔试行的
<input type="text" id = "searchElement">
const SearchElement = document.getElementById("searchElement")
function debounce(fn, delay){
let timer = null
return ()=>{.
clearTimeout(timer)
timer = setTimeout(fn,delay)
}
}
SearchElement.oninput = debounce(function(event)){
const value = searchElement.value
log('value',value)
,1000}

15.如何使用多种方式实现数组拍平
概念 :数组拍平也叫数组扁平化、数组拉平、数组降维。**指的是把多维数组变成一维数组**。
使用场景:复杂场景下的数据处理
实现数组拍平的具体实现:
const array = [1,2,3,4,[5,6,[7,8]]] //多维数组
array [1,2,3,4,5,6,7,8]; //实现的结果
1.使用reduce实现
//reduce
function flatten(array) {
return array.reduce(function(prev,current){
return prev.concat(Array.isArray(current)?flatten(current):current) //如果是就递归调用
},[])
}

const result = flatten(array);
console.log(`result`, result);

//使用ES6的flat函数 在vscode执行不了 在Chorme浏览器(默认支持ES6语法)的控制台可以 ,因为vscode没有兼容ES6的语法
function flatten(array) {
return array.flat(Infinity); //Infinity是长度无限展平
}
const result = flatten(array)
console.log(`result`, result);

//while
function flatten(array) {
while (array.some(Array.isArray)){ //只要数组里是个数组就会进while循环
array = [].concat(...array)
}
// 1 array
// 2 已经被拍平
return array;
}



const result = flatten(array);
console.log(`result`, result);

16.什么情况会使判断成立
let value = 0;
Object.defineProperty(window,'a',{ // Object.defineProperty给目标对象挂载属性并且拿值的操作
get(){
return value += 1; //return的值就是a的值 每获取一次a,value都会加1
}
});
if(a===1&&a===2&&a===3){ //每一次判断都会拿一下a的值,a的值是递加的 是定义在window对象的
console.log(`object`)
}
17.实现new操作符
实际使用场景:封装第三方的工具(通过构造函数进行封装)
const TMap = function(options){
this.name = options.name;
this.address = options.address;
return{
name:'map',
address:'SZ'
}
}

const map = new TMap({
name: 'tmap',
address:"BJ"
});

console.log('map :>> ', map); //返回的是SZ
使用new操作符实例化后的对象有两种情况:如果构造函数里没有返回值的话,实例化对象输出的就是构造函数里的实例属性和方法 BJ
如果构造函数里有返回值的话,实例化对象就是那个返回值 SZ
如何实现new操作符 ->难先不看

18.实现一个bind函数
function origin(a,b){
console.log(this.name);
console.log([a,b]);
}
const obj = {
name:"freemen"
}
const func = origin.bind(obj,2); //改变this的指向 不然是指向window且返回的是一个函数
func(1) // 输出Freeman [2,1]
**模拟一个bind函数** 难先不看
bind函数的实现原理
1. bind 函数改变this指向
2. bind 函数是Function.prototype上的方法
3. bind 函数的返回值也是函数
4. bind 函数调用之后返回的函数的参数同样也接收处理

如何实现call和apply函数
apply入参方式是以数组传递的 实现也很难先不看
call
1.改变this指针
2.返回函数调用
3.参数挨个依次传递
apply
1.改变this指针
2.返回函数调用
3.数组方式传参

19.实现instanceof
function Persion(){
this.name = "freemen"
}
const obj = new Persion

console.log(obj instanceof Persion)//输出true
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

function instance_of(Obj, Constructor){
let implicitPrototype = Obj.__proto__; // 获取实例对象的隐式原型
let displayPrototype = Constructor.prototype; // 获取构造函数的prototype 属性
// while 循环 -> 在原型链上不断向上查找
while(true){
// 直到 implicitPrototype = null 都没找到, 返回false
if(implicitPrototype === null){
return false
// 构造函数的 prototype 属性出现在实例对象的原型链上 返回 true
}else if (implicitPrototype === displayPrototype){
return true
}
// 在原型链上不断查找 构造函数的显式原型
implicitPrototype = implicitPrototype.__proto__
}
}

const has = instance_of(obj,Persion)
console.log(`has`, has)

实现原理:
1. 获取实例对象的隐式原型
2.获取构造函数的prototype属性
3. while 循环->在原型链上不断向上查找
4. 在原型链上不断查找构造函数的显式原型
5,直到实例对象的隐式原型 = null都没找到,返回false
6.构造函数的prototype属性出现在实例对象的原型链上返回true (构造函数的显式原型===实例对象的隐式原型)

20.总结:
1、什么是原型和原型链?
1.什么是原型
在javascript中,函数可以有属性。每个函数都有一个特殊的属性叫作原型(prototype)
每个对象都会在其内部初始化一个属性,就是prototype(原型)

2.什么是原型链
原型链就是当我们访问对象的某个属性或方法时,如果在当前对象中找不到定义,会继续在当前对象的原型对象中查找,如果原型对象中依然没有找到,会继续在原型对象的原型中查找(原型也是对象,也有它自己的原型)如此继续,直到找到为止,或者查找到最顶层的原型对象中也没有找到,就结束查找,返回undefined。可以看出,这个查找过程是一个链式的查找,每个对象都有一个到它自身原型对象的链接,这些链接组件的整个链条就是原型链

3·原型和原型链存在的意义是什么?
**使得实例对象可以共享构造函数原型上属性和方法**,节省内存。构造函数原型上的属性和方法越多,节省内存越大.

2如何理解作用域和作用域链?
讲清楚如下三点:
1.什么是作用域?
作用域是在运行时代码中的某些特定部分中**变量,函数和对象的可访问性**,作用域决定了代码区块中变量和其他资源的可见性。

2.作用域存在的意义是什么? **不同作用域下同名变量不会有冲突。**
作用域存在的最大意义就是变量隔离即:

3.什么是作用域链?
当我们在某个函数的内部作用域中查找某个变量时,如果没有找到就会到他的父级作用域中查找,如果父级也没找到就会接着一层一层的向上寻找,直到找到全局作用域还是没找到的话,就宣布放弃。这种一层一层的作用域嵌套关系,就是作用域链

3、你对闭包怎么理解?
讲清楚如下三点:

1.什么是闭包?
**一个函数作用域能够访问另外一个函数作用域中的变量的函数**
**闭包:自由变量的查找,是在函数定义的地方,向上级作用域查找。不是在执行的地方!!!**
bind方法只有在Function.prototype

2.闭包有哪些实际的使用场景?
1.事件函数的封装
2.用闭包模拟私有方法
3.在循环中给页面元素绑定事件响应函数
使用闭包主要为了设计私有的方法和变量
3.闭包存在什么问题?
好处是可以延伸这个变量的使用范围 缺点:闭包本身会造成内部变量常驻内存,会增大内存使用量,使用不当很容易造成内存泄露
原因就是在函数执行结束之后不会将变量进行销毁

ES6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
1.letconstvar的区别  
1 不存在变量提升
2 块级作用域:不会像var一样先变量提升显示undefined,会直接拿去全局的变量
3 暂时性死区:在块级作用域里面,声明变量的时候不能提前给它赋值
4 不可重复声明 let a = '10' let a = '20' 语法错误
5 letconst声明的变量不会挂在在全局window对象下面
// var fullName ='freemen';
// console.log(`window`, window.fullName) undefined
let a = 20
{
let a = 30 这是不会报错的 因为不是在同一个作用域
}
var能够对一个变量进行多次声明
存在变量提升
在函数中使用使用var声明变量时候,该变量是局部的 而如果在函数内不使用var,该变量是全局的
**修改声明的变量**
varlet可以 const声明一个只读的常量。一旦声明,常量的值就不能改变

const声明之后必须马上赋值,否则会报错
const声明的简单类型不可更改,复杂类型内部数据可以更改 例如 const fullName = ['freeman'] fullName[1] = 'mkw' 不会报错
能用const的情况尽量使用const,其他情况下大多数使用let,避免使用var

2.箭头函数和普通函数的区别
1、箭头函数的this指向父级作用域的this
2、call()/.apply()/.bind()无法改变箭头函数中this的指向
3、不可以被当作构造函数
4、不可以使用arguments对象 是一个对应于传递给函数的参数的类数组对象。
关于第四点 普通函数
function sayName(){
const args = arguments;
log('args',args);
}
sayName('a','b') // 输出的是args可以接收传来的参数为a,b
换成箭头函数, 报错arguments没有定义 而箭头函数接收args参数 const sayName = (...args)=>{.....}
1、在函数调用中,this的指向指向调用它的对象
2、在构造函数中,this指向指向实例化对象
3、在事件体中,this指向事件源
4、箭头函数的this指向父级作用域的this
5、其他情况(声明式,赋值式的函数),this指向window

3.ES6哪个方法可以实现数组去重
采用ES6中Array.from配合new Set
const array = [1,2,3,4,5,12,1,2]
const result = new Set(array) //返回的是一个{} //数组去重console.log(`result`, [...new Set(array)])
我们需要array.from
const result = Array.from(new Set(array))//将一个类数组对象转化为数组对象 =>只能对基本类型的值的数组进行去重
如果是一个对象是不能实现去重

4.ES6实例对象新增的方法对象新增的方有哪些?
1 Object.is() =>判断两个值是否相同
const numOne = 1;
const numTwo = '1';
const result = Object.is(numOne,numTwo);//false
const result = Object.is(NaN,NaN);
console.log(`result`, result);//true
特点: 1 不仅可以对值类型进行正常处理而且对象类型的值也可以进行判断
2 对于特殊的值 NaN 也可以进行正常的处理
2.Object.assign()=>两个对象进行合并
const obj = {
name:"freemen"
}
const objTwo = {
age: 18
}
const result = Object.assign(obj,objTwo);
console.log(`result`, result)//{ name:"freemen", age: 18}
3.Object.keys()=>返回一个数组,目标对象的所有可遍历属性的键名
const object = {
name:"freemen",
age:18
}
const result = Object.keys(object);
console.log(`result`, result);//['name','age']
4.Object.values()=>返回一个数组,目标对象的所有可遍历属性的键值 ['freemen','18']
5.Object.entries ()=>返回一个键值对数组(keys和values的结合)//['name','freemen'] ['age','18']

5.classfunction的区别
//相同点:
// 都可以用作构造函数
function Persion(){
this.fullName = "freemen";
}
class Persion{
constructor(){
this.fullName = "freemen";
}
}
const object = new Persion
console.log(`object`, object)
返回的都是Persion{
fullname:'freemen',
[Prototype]:Object
}
// 不同点:
// * class 不可以使用 call apply bind 的方式来改变他的执行上下文   
function sayName(){
console.log(`this.fullName`, this.fullName)
}
class Persion {
constructor(){
this.fullName = "freemen";
}
}

const obj = {
fullName: "freemen"
}
Persion.call(obj)// 普通函数this.fullName freemen class函数不可以类型错误

6.你对promise了解多少 Promise对象中的then方法,可以接收构造函数中处理的状态变化
定义:是一种异步编程的一种解决方案。比传统的解决方案--回调函数和事件--更合理和更强大
基本使用
// 3 个状态 pending正在进行中 fulfilled成功 rejected 失败
new Promise(function(resolve,reject){
let fullName = "freemen";
if(fullName==='Vinko'){
resolve(1)
}else{
reject(2)
}
}).then(function(value){
console.log(`resolve - value`, value)
},function(value){
console.log(`reject - value`, value) //输出这个
})

原型方法
**Promise.prototype.then**
new Promise(function(resolve, reject){
let fullName = "freemen";
if(fullName==="freemen") {
resolve(1);
}else{
reject(2)
}
}).then((value)=>{
console.log(`fulfilled value`, value)
return Promise.reject(2);
}).then((fulfilledValue)=>{
console.log(`fulfilled value`, fulfilledValue)
},(rejectedValue)=>{
console.log(`rejectedValue`, rejectedValue)
})

1 可以支持链式调用
2 then 接受两个参数且都是函数
第一个函数是我们promise 状态变成fullfilled 时候的回调函数 成功的回调
第二个函数是我们promise 状态变成rejected时候的回调函数 失败的回调
3 返回值也是Promise(新的)
**Promise.prototype.catch**
捕获Promise错误
new Promise(function(resolve, reject){
let fullName = "freemen";
if(fullName==="Vinko") {
resolve(1);
}else{
reject('promise error')
}
}).then((value)=>{
console.log(`value`, value)
}).catch((error)=>{
console.log(`error`, error)
})

**Promise.prototype.finally**
用于指定**不管 Promise 对象最后状态如何,都会执行的操作*

实例方法
**Promise.all**
//用于将多个Promise实例包装成一个新的Promise实例
const promiseArray = [1,2,3,4,5].map((item)=>{
return new Promise((resolve)=>{
resolve(item);//包含多个promise实例的数组对象
})
})
Promise.all(promiseArray).then(res=>{
console.log(`res`, res) //res [1,2,3,4,5]
});

**Promise.race**
// Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例
// Promise.race 和 Promise.all 区别
// Promise.race 继发 只要有一个状态发生改变就拿这个结果作为回调函数的值(res)来执行
// Promise.all 并发 每一个promise状态都发生改变的时候才拿这个结果
const promiseArray = [1,2,3,4,5].map(item=>{
return new Promise((resolve)=>{
resolve(item)
})
})
Promise.race(promiseArray).then(res=>{
console.log(`res`, res)//res 1
})

**Promise.resolve**
// Promise.resolve 将现有对象转化成Promise 对象
new Promise(function(resolve, reject){
console.log(`loading start...`)
let fullName = "freemen";
if(fullName==="freemen") {
resolve(1);
}else{
reject('promise error')
}
}).then(res=>{
console.log(`res`, res) //res为1
})
=>等价于
Promise.resolve(1).then(res=>{
console.log(`res`, res)
})

**Promise.reject**
// Promise.reject 返回一个Promise实例 -> 实例的状态rejected
new Promise(function(resolve, reject){
console.log(`loading start...`)
let fullName = "freemen";
if(fullName==="Vinko") {
resolve(1);
}else{
reject('promise error')
}
}).then(res=>{
console.log(`res`, res)
},rejected=>{
console.log(`rejected`, rejected) //rejected promise error
})
=>等价于
Promise.reject('promise error').then(null,rejected=>{ //reject状态的回调函数是我们then函数的第二个参数
console.log(`rejected`, rejected)//rejected promise error
})
7.扩展运算符的实现原理
const baseArray = [1,2,3,4]
const array = [...baseArray]
==>实现原理
var baseArray = [1,2,3,4]
var array = [].concat(baseArray)
8.forEach, for...in, for...of之间的区别?
1、forEach是数组的方法
1.遍历的时候更加简洁,效率和for循环相同,不用关心集合下标的问题,减少了出错的概率。
2.没有返回值
3.不能使用break中断循环,不能使用return返回到外层函数

2for...in用于可枚举数据,如对象、数组、字符串 得到key
3for...of用于可迭代数据、如数组、字符串、MapSet 得到value

React全家桶

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
1.react父子组件如何通信
父组件=>子组件
1.Props
2.Prototype Methods 原型方法
子组件=>父组件 也是通过props传递,只不过前提是要求父组件提前给子组件传递一个函数
1.Callback Functions 回调函数
2.Event Bubbling 事件冒泡=>浏览器的事件传输机制 点击内部元素的时候一层一层的冒泡 会触发子组件的父元素的事件响应函数
const Child()=>{
return (
<button>click<button> //点击按钮触发下面的div的onClick事件 利用浏览器的事件传输机制 点击内部元素的时候一层一层的 冒泡 会触发子组件的父元素的事件响应函数
);}

class Parent extends React.Component {
handleClick=()=>{
console.log( "clicked " )
}
render(
return (
<div onClick={this. handleClick}>
<Child/>
</div>
)
};

2.react中的setState是同步还是异步 在执行层面和本质层面进行剖析
**执行层面**
同步:原生事件onclick、setTimeout
异步:react合成事件、生命周期钩子函数
**本质层面**
本质:本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致他们没法立马拿到更新后的值,形式了所谓的“异步”

export default class SetStateComponent extends Component {
state= {
count : 0
}
// 同步:原生事件和setTimeout
**setTimeout**
componentDidMount() {
setTimeout(()=>{
this.setState({count: this.state.count+1});
console.log(`this.state.count`, this.state.count);
})
**原生事件**
const ele = document.getElementById('element');
ele.onclick = ()=>{
this.setState({count: this.state.count+1});
console.log(`this.state.count`, this.state.count)
}
}
**生命周期钩子函数**
componentDidMount() {
this.setState({count: this.state.count+1});
console.log(`this.state.count`, this.state.count)
}

** react合成事件 *
handleClick = ()=> {
this.setState({count: this.state.count+1}); //点击的时候输出0 异步的没有立马拿到最新的值
console.log(`this.state.count`, this.state.count)
}
render() {
return (
<div>
<button id="element">add<tton>
<button onClick={this.handleClick}>add<tton>
</div>
)
}
}
3.在同一个事件响应函数中setStata两次,render会执行几次?
setState机制:内部会维护一个updaterQueue, 当我们同时更新一个同名属性的时候 会对同名的state属性进行一个覆盖。
执行后面的一个setState
4.什么是render props?可以用来解决什么问题?
术语“render prop”是指―种在React组件之间使用一个值为函数的prop共享代码的简单技术
使用场景:获取鼠标坐标值(鼠标移动跟随的场景)
路由劫持

5.react中如何进行条件渲染 三元运算符
判断是否登陆渲染相应的组件

6.Router-React中如何获取url的参数
import React, { Component } from 'react'
import { withRouter } from 'next/router'
export default withRouter(class RouteComponent extends Component {
handleClick = ()=>{
const query = this.props.router.query;
console.log(`query`, query);
}
render() {
return (
<button onClick={this.handleClick}>点击我吧<tton>
)
}
})
// 面试官主要考察什么?
// react框架本身的熟悉程度

// 面试中遇到该题目我们该如何回答?
// 以next为例,用withRouter 包装基础组件 基础组件的props中拿到我们路由的信息
7.React-Router有哪几种路由模式?
1、BrowserRouter:浏览器的路由方式,也就是在开发中最常使用的路由方式/
2、HashRouter:在路径前加入#号成为一个哈希值,Hash模式的好处是,再也不会因为我们刷新而找不到我们的对应路径
2.hashRouter和BrowserRouter的实现原理?
hashRouter: window 监听 hashChange 事件来实现路由切换的
BrowserRouter: window 监听popstate事件来实现路由切换的
(实现原理:react-router这个库是依赖history这个库的 history这个库给我们提供了路由跳转的方式)

8.什么是jsx?
jsx是由babel进行编译的
//jsx 本质是一个语法糖
// jsx 通过@babel/presets-react预设(编译),将jsx转换为React.createElement这个函数 这个函数会生成虚拟DOM
// 生成虚拟DOM之后会调用
// render方法来对虚拟DOM编译
9.react的生命周期你了解多少?
面试中遇到该题目我们该如何回答?
1.分阶段(挂载,更新,卸载)讲清楚react的生命周期
挂载:挂载阶段,也可以理解为组件的初始化阶段,就是将我们的组件插入到DOM中,只会发生一次
constructor, 组件构造函数,第一个被执行
getDerivedStateFromProps(让组件在 props 变化时更新 state。),
它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
此生命周期是在 16.3 版本新增的,用于替代 componentWillReceiveProps 生命周期
这个函数有两个参数props和state,分别指接收到的新参数和当前的state对象,这个函数会返回一个对象用来 更新当前的state对象,如果不需要更新可以返回null
render,
componentDidMount 组件挂载之后调用
更新:当组件的props改变了,或组件内部调用了setState或者forceUpdate发生,会发生多次
getDerivedStateFromProps, 无论我们接收到新的属性,调用了setState还是调用了forceUpdate,这个方法都会被调用
shouldComponentUpdate,控制更新的阀门 ,控制 render 是否允许被执行。。
render,渲染render函数是纯函数(同样的输入必定有同样的输出)
getSnapshotBeforeUpdate,这个方法在render之后,componentDidUpdate之前调用,有两个参数prevProps和prevState,表示之 前的属性和之前的state,这个函数有一个返回值,会作为第三个参数传给componentDidUpdate(获取的快照),如果你不想要返回值,请 返回null,一定要和componentDidUpdate一起使用 (这个方法代替了之前的componentWillUpdate)
componentDidUpdate 该方法在getSnapshotBeforeUpdate方法之后被调用,有三个参数prevProps(之前的属性),prevState,snapshot,表示之前的props,之前的state,和snapshot。第三个参数是getSnapshotBeforeUpdate返回的

卸载: 我们的组件被卸载或者销毁了
componentWillUnmount:清除一些定时器,取消网络请求。

Webpack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
1、webpack的理解
1.webpack是一个用于现代JavaScript应用程序的**静态模块打包工具**
2.解决模块依赖问题 :例如A模块依赖B模块,B模块依赖C模块,就会把C模块放在最前面
3.解决代码编写问题 :将less转化为css 将ts转化为js
4.解决开发效率问题 :webpack提供了热加载的功能,当我们项目开发过程中,保存文件后会自动更新
5.解决项目优化问题 :项目完成开发上线的时候,webpack会将代码进行压缩优化,提高性能。
2、使用过webpack中的哪些loader
loader 分为js相关、css相关、文件相关、
js相关
babel-loader:处理javascript文件,提供语法转换(编译过程中class转换成function),语法垫片(对ES的新语法提供支持)
source-map-loader:从现有源文件中提取源映射关系(webpack打出来的包都是一个个bundle.js,bundle.js里面包括webpack打包的代码和源文件,如果要在项目中进行debug调试的话,没有source-map-loader的话,就会debug到webpack打出来的包都是一个个bundle.js中,有的话就会定位到源代码中,在源代码进行调试)
css相关
style-loader:把编译后的css以style标签的格式插入DOM中 执行顺序3
css-loader:处理css中比如url()@import等语法的文件引用路径问题 执行顺序2
less-loader:将less编译为css 执行顺序1 先由less转为css
文件相关
file-loader:处理文件引用路径问题
gzip-loader:加载gzip资源
url-loader:允许有条件地将文件转换为内联的base-64 URL,转化玩之后,减少了http请求的个数,提高了应用的性能
**注意**loader以数组的方式进行配置,执行的顺序是从后往前栈结构的顺序执行。

3.使用过webpack中的哪些plugin分别是用来做什么的
DllPlugin 为了极大减少构建时间,进行分离打包
HotModuleReplacementPlugin 启用模块热替换(Enable Hot Module Replacement -HMR)*
HtmlwebpackPlugin 简单创建HTML文件,用于服务器访问
ProvidePlugin 全局的注入模块,不必通过import/require使用模块
这些插件的执行顺序与配置顺序无关 pligun可以在webpack的整个编译周期执行
4.如何实现一个loader -D是开发依赖 -S 生成依赖
**loader本质上是一个函数,这个函数接收source为参数,函数返回值便是我们最终loader处理的结果。**
使用过uglify-loader来进行代码压缩的
1.首先现在webpack.config.js下配置loader和指定loader编写的目录
2.在指定编写的目录写对应的loader的实现操作
3.返回code实现webpack代码的压缩。
5.如何编写一个plugin 日志loader
1.plugin本质上是一个构造函数,通常用class类来表示,constructor中接受入参,
且必须实现apply方法来接收webpack的主体编译对象compiler
2.讲清楚自己实现过哪些自定义的plugin,分别是用来做什么的?
打印日志的LogPlugin
6.plugin和loader的区别:
1.功能:loader能做的事情,plugin也可以做
2.执行顺序:
pligin 可以在webpack编译的过程中执行,类比react的生命周期钩子
loader 只能在固定的阶段执行
3.本质上的区别
loader 本质上是一个翻译官,对客户端识别不了的源码进行翻译
plugin 执行的是一些副操作,比如输出一个日子,图片资源可以实现插件将图片做一些副操作,上传到cdn里面
7.webpack的构建流程
如下图
8.

image-20211225172445261

数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
1、JavaScript的数组方法有哪些?
concat连接2个或更多数组,并返回结果
every对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true
const array = [{name:'freemen',age:18},{name:'vinko',age:18}];
const result = array.every((item)=>{
return item.name==="freemen"
})
console.log(result);//false

filter对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
forEach对数组中的每—项运行给定函数**这个方法没有返回值** 传入的参数可以使item,和一个索引index
const array = [{name:'freemen',age:18},{name:'vinko',age:18}];
array.forEach((item,index)=>{
console.log(item); //{name:'freemen',age:18}{name:'vinko',age:18}
console.log(index);0 1
})

join将所有的数组元素连接成一个字符串
const array = [1,2,3,4,5];
const result = array.join(',');
console.log(result);//1,2,3,4,5

indexOf返回第一个与给定参数相等的数组元素的索引,没有找到则返回-1
lastIndexOf 返回在数组中搜索到的与给定参数相等的元素的索引里最大的值
map对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
const array = [{name:'freemen',age:18},{name:'vinko',age:18}];
const result = array.map(item=>{
if(item.name==='freemen'){
return item;
}
return {};
})

reverse 颠倒数组中元素的顺序,原先第一个元素现在变成最后一个,同样原先的最后一个元素变成了现在的第一个
slice传入索引值,将数组里对应索引范围内的元素作为新数组返回
some对数组中的每一项运行给定函数,如果任一项返回true,则返回true
const array = [1,2,3,4,5];
const result = array.some(item=>{
return item===6;
})
console.log(result);

sort按照字母顺序对数组排序,支持传入指定排序方法的函数作为参数
const result = array.sort((a,b)=>{
return a-b;
})

toString 将数组作为字符串返回
2、栈 peek获取栈顶
isEmpty栈是否为空
3、react-redux有用到队列的数据结构(发布订阅机制) 所有的订阅者都会拿到消息执行,执行的原则是先进先出
4、冒泡排序

设计模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
装饰者模式:不改变对象自身代码的基础上新增功能
策略模式的实现:有效解决if else逻辑复杂不可维护的情况
let strategys = {
s(base){
log('phone')
return base*5
}
a(base){
log('书包')
return base*4
}
b(base){
log('鼠标')
return base*3
}
}
function catulaBonus(base,grade){
return strategys[grade](base)
}
代理模式:转发请求

发布-订阅模式又叫观察者模式、它定义对象间的一种一对多的依赖关系当一个对象的状状态发生改变时所有依赖于它的对象都将得到通知
最基础的例子是事件监听
迭代器模式:对一个目标数组进行遍历
倒叙迭代器
let reverseEach = function(obj,callback){
if(!array.isArray(obj)){
throw Error('params is must an array')
}
for(let i =obj.length-1;i>=0;i--){
callback.call(obj[i],obj[i],i)
}
}
reverseEach(array,(item,index)=>{
log(`item:${item}`)
log(`index:${index}`)
})

网络协议面试题及实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1、http常见状态码及含义:
200请求成功
301永久重定向
302临时重定向
401未授权
403没权限,服务器拒绝了请求
404表示服务器上没有找到该资源
405表示请求的方式不对
500服务器错误
2get和post区别
1.get用来获取数据,post用来提交数据
2.get参数有长度限制(受限于url长度,具体的数值取决于浏览器和服务器的限制,最长2048字节),而post无限制。
3.get参数通过 url 传递,post放在请求体 (request body) 中。 get是明文传输,post的请求参数是放在请求体中
4.get请求只能进行url编码,而post支持多种编码方式。

3、http协议中的header及含义
accept:代表客户端希望接受的数据类型
accept-encoding:浏览器发给服务器,声明浏览器支持的编码类型
accept-language:表示浏览器所支持的语言类型
Cache-Control:缓存开关,no-cache表示禁用缓存
referer: referer的正确英语拼法是referrer。由于早期HTTP规范的拼写错误,主要用于防止盗链和恶意请求

4、网络分层模型 OSI七层模型
应用层
表示层
会话层
传输层
网络层
链路层
物理层

浏览器面试题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
1、浏览器事件传输机制
事件传输机制冒泡和捕获分别由微软和网景公司提出
这两个概念都是为了解决页面中事件流(事件发生顺序)的问题

事件触发的三个阶段:捕获阶段、目标阶段、冒泡阶段
addEventListener(,true)是捕获阶段 从外到内
addEventListener(,false)是冒泡阶段 从内到外

2、localStorage和sessionStorage的区别 本地存储和会话存储的区别
数据生命周期:
localStorage:永久性存储 除非被用户主动清理,否则一直存在
sessionStorage:页面关闭就清理
数据存储大小
localStorage: 5M
sessionStorage:5M
3、浏览器的事件循环机制
你对浏览器的事件循环机制了解多少
宏任务
scripti(整个代码段)
setTimeout
setInterval
setlmmediate
I/O
UI render
微任务
process.next Tick
Promise
Async/Await
MutationObsarver(html5新特性)
4、浏览器的回流和重绘
浏览器的渲染过程是怎样的?
1.解析HTML,生成DOM树,解析css,生成CSSOM树
2.将DOM树和CSSOM树结合,生成渲染树(Render Tree)
3. Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点
的几何信息(位置,大小)
4. Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点
的绝对像素
5.调用GPU触发渲染,将结果展示在页面上

回流:
我们通过构造渲染树,我们将可见DOM节点以及它对应的样式结合起来,可是我们还需要计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流
(重新绘制当前页面,包括整个结构和样式)
重绘:
我们通过构造渲染树,我们知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(位置、大小),那么我们就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘节点
(重新绘制当前页面样式)
比方说我们软件设计中的设计模式源于建筑学
回流:相当于把房子拆了重建
重绘:相当于重新粉刷
结论:回流必然导致重绘,重绘不一定会伴随着回流

何时触发回流和重绘
1.添加或删除可见的DOM元素
2.元素的内容、位置或尺寸发生变化
3.页面一开始渲染的时候
4.浏览器的窗口尺寸变化

避免回流和重绘 图片
使用文档片段fragment避免不停的往页面插入元素

5、跨域
同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
如果两个URL的protocol、port (en-US)(如果有指定的话)和 host都相同的话,则这两个URL是同源。

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
跨域的解决方法:
jsonp:通过动态创建 script 标签,通过 script 标签的 src 请求来通过jsonp跨域
原理:
利用<script>标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的jSON 数据。JSONP请求一定需要对方的服务器做支持才可以
优点: JSON优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题
缺点∶仅支持get方法具有局限性,不安全可能会遭受XSS攻击。
postMessage
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题
1.页面和其打开的新窗口的数据传递
2.多窗口之间消息传递
3.页面与嵌套的iframe消息传递
4.上面三个场景的跨域数据传递
6、浏览器主要组成部分
用户界面
浏览器引擎
渲染引擎
网络模块
用户界面后端
javascript解析器
数据存储模块

用户界面:包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。
浏览器引擎:在用户界面和呈现引擎之间传送指令。
渲染引擎–负责显示请求的内容。如果请求的内容是 HTML,它就负责解析HTML和CSS内容,并将解析后的内容显示在屏幕上
网络模块:用于网络调用,比如HTTP请求。其接口与平台无关,并为所有平台提供底层实现。
用户界面后端:用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
JavaScript解释器:用于解析和执行JavaScript代码。
数据存储模块:这是持久层。浏览器需要在硬盘上保存各种数据,例如Cookie SessionStorage LocalStorage

image-20211229224218562

image-20211229224445796

软素质

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
一、说一下自己的优点和缺点?
1.避开岗位的核心技能
2.把缺点放在场景中描述
3.对缺点进行合理化解释
4.优点随便说,主要方向还是在岗位上
二、是否能接受加班?(建议分情况作答)
假设公司有重要的项目要赶。示范回答:贵公司现在正处于发展上升期,也在官网上有看到公司的重要项目成果,我觉得有时候因为赶项目进度、工作需要等忙起来是非常正常的,面对这种情况,我是非常愿意配合公司和团队的工作,让工作能够更顺利地完成,此外,我也相信自己一定能在公司安排的工作中获得到锻炼,获得更快地成长。
·假设自己作为新人,对业务不熟悉。示范回答:我作为公司刚进去的新人,可能刚开始进入公司接触业务时不太熟练,
会出现需要加班的情况,但我更愿意提高工作效率,并积极向公司的前辈请教学习,在一定的时间内完成工作而不是拖到下班之后。当然,如果有紧急的事情,忙起来需要加班也是可以接受的。
三、对薪酬的要求?
·薪资并不是我求职的唯一标准,我来贵司求职的主要动机是兴趣,这份工作是我喜欢做的,也相信自己可以胜任,更相
信公司会给出一个合理的薪酬。
·我希望薪资可以达到XX,据我了解,贵司这个岗位薪资范围是A-~B,而结合岗位职责及任职要求,我对自己也进行了
相应评估,也愿意接受贵司的下一步考核。
四、为什么你觉得这个岗位适合自己?(为什么要聘用你)
1.描述应聘岗位的胜任条件,强调自己的工作能力跟岗位的匹配度,岗位要求的工作技能是否自己掌握了,掌握的程度是怎样的,最好在面试中说出来。(建议:在面试前最好是要针对应聘岗位,把自己胜任的条件一一列出来,做到知己知彼。)
2.描述自己能为公司做出什么贡献,公司是一个讲究利益的地方,聘用你肯定要你为公司做出贡献。那么你在回答这个问
题时,就需要说出你的加入可以为公司带来什么,这非常重要。(一定要明确你的工作目标和职业规划,表明你的立场和专业程度,让HR信任你。)
3.描述出自身的优势。公司为何要聘用你,而不聘用别人,肯定是你有比别人优秀的地方。那么在回答这个问题时,就一
定要说出自己与众不同的地方,最好是要举一个例子,来支持你的观点。
(提示:这个问题,主要是想进一步了解你的信息,以及为这次面试做了多少功课。在面试前,最好是要尽可能获取有关公司可行业的资料信息。在回答的时候,结合自己所做的功课,建立个人和公司的联系,说明自己在哪一方面能够匹配公司的要求。)
五、对我们公司有多少了解?
·如果不了解,就按实际情况回答就好,知道多少就说多少,(很多时候去面试对这个公司的了解都是从网上查到的,不
会太深入);最好是提前做好一些调研和准备工作。
六、缺乏工作经验,如何胜任这份工作?
·承认工作经验的重要性。
·突显个人优势。用自己的其他优势特长来补足经验上的不足,比如说记忆力好、动手能力强、语言能力强、学习能力强等。
·强调自己会不断提高工作能力。切忌用假大空的话。

简历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1、简历投递
1.朋友内推:更好的了解公司以及团队内部的情况
2.招聘软件:boss直聘 打钩
3.公众号
2、如何准备项目经验
1.准备1-2个实际做过的或者可以讲清楚整个业务流程的项目
2.说清楚其中作用的技术栈
3.讲清楚在项目开发过程中遇到的难点
4.复盘整个过程发掘出可以优化的地方
1、样式布局可以进行优化:以采用css module的方式 以.css/.less文件文件为主,而不是styled-components的方式
虽然采用styled-components的方式可以有效避免组件之间样式的冲突 但是编写代码起来繁琐(包括没有代码提示)
同时jsx 中的原生标签不能一眼看出来,也额外增加了标签变量。

2、前端的页面,还不完整,可以加一个后台管理系统来管理数据。

3、学历是否能反应一个人的真实水平
当然不能 学历是判断潜力的一个相对客观的一个指标
4、简书项目
1.不同的浏览器内核里对html body标签默认的样式是不同的,有可能在某一个浏览器上的body的margin间距值是10 而在另外一个浏览器的间距值就是8 为了让这个代码在所有浏览器的表现形式是一致的,我们要先把这些浏览器默认对这些标签的实现进行一个统一
reset.css就是干这个活 ,当你引入这个之后,标签基本上在所有浏览器的margin,padding值都会一模一样,这样就防止在不同的浏览器打开呈现的效果不同。

image-20220101141245546

高频考点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
React面试题
. React组件通讯的常见方式。JSX本质是什么?
1、父组件通过向子组件传递 props
2、利用回调函数,可以实现子组件向父组件通信
3、跨级组件间通信:使用context对象
4、非嵌套组件间通信:使用事件订阅

. context 是什么,有何用途?
Context 一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信
创建Context容器对象:
渲染子组件时,外面包裹容器对象的Provider属性, 通过value属性给后代组件传递数据
后代组件读取数据:
第一种方式:仅适用于类组件
static contextType = xxxContext // 声明接收context
const theme = this.context // 读取context中的value数据 theme就是value的值
第二种方式: 函数组件与类组件都可以 函数式没有this所以第一种不适合函数式组件
外面包裹容器对象的Consumer属性

. shouldComponentUpdate 的深入理解。
控制组件更新的“阀门” 应不应该更新状态 **
在父组件更新时会触发此函数,在此函数中可以根据props是否变化来setState,并且在此函数中的setState不会再次触发子组件的render

. 描述redux单项数据流。
react要去改变store里的数据,首先要一个派发action,action会通过dispatch方法传递给store,store再把之前的数据和传递过来的action转发给reducers,reducers是一个函数,当reducers接收到state和action之后,做一些处理之后,会返回一个新的state给到store,store用这个新的state替换掉之前的state,store数据发生改变之后,react组件会感知到store里的state发生改变(用的是``store.subcribe()``来监测store里状态的改变)就会从store里面重新取出数据更新组件的内容,页面就发生变化了

. setState是同步还是异步?
**执行层面**
同步:原生事件、setTimeout
异步:react合成事件、生命周期钩子函数
**本质层面**
本质:本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致他们没法立马拿到更新后的值,形式了所谓的“异步”

. 用React设计一个todolist,请设计组件结构,设计state 数据结构。

webpack面试题
. 前端代码为何要进行构建和打包?
. module chunk bundle分别是什么意思,有何区别?

. loader和plugin 的区别。
. webpack如何实现懒加载?
. webpack '常见性能优化方式(开放型题目,自由发挥)。
. babel-runtime和babel-polyfill的区别。


JavaScript面试题
1、var 和 let const的区别
var是ES5语法,let const是ES6语法;var有变量提升
var和let是变量,可修改;const是常量,不可修改﹔
let const有块级作用域,var没有
2、typeof 能判断哪些类型
undefined string number boolean symbol
object(注意,typeof null === 'object')
function
3、列举强制类型转换和隐式类型转换
强制:parseInt parseFloat toString 等
隐式:if、逻辑运算、==、+拼接字符串
4、数组的pop push unshift shift分别是什么
功能是什么?
push()方法是向数组末尾添加一个或者多个元素,并返回新的长度。
pop()方法删除数组的最后一个元素,把数组的长度减1,返回的是删除的元素。
unshift()方法是向数组的开头添加一个或多个元素,并且返回新的长度。
shift()方法是数组的第一个元素从其中删除,并返回第一个元素的值。
返回值是什么?
pop()返回的是删除的元素
push()返回的是数组的长度****
unshift()返回的是数组的长度****
shift()返回的是删除的第一个元素元素
是否会对原数组造成影响?
都产生影响
以下对原数组不产生影响
toString:得到数组中每个值的字符串形式拼接而成的、一个以逗号分隔的字符串。
valueOf:返回数组的原始值
join:使用指定的分隔符,将数组的每个元素连接起来,返回构建的字符串。
concat:传递一个或多个数组,则会将数组的每一项都添加到结果数组中。
slice:返回起始位置到数组末尾的所有项

纯函数:不改变原数组(没有副作用),且返回一个数组 =>等同于对原数组不产生影响
map
filter
slice
concat
非纯函数:forEach reduce some every

5、slice(-2)//截取后面两个 纯函数
splice 非纯函数 splice(1,2,'a','b')//从第一个元素开始截取两个 然后添加ab
6、const res = [10,20,30].map(parseInt)
拆解开是
[10,20,30].map((num,index)=>{
return parseInt(num,index) //parseInt(20,1) parseInt(30,2)不符合parseInt的转换规则
})
结果为[10,NaN,NaN]//map返回的是一个数组
**parseInt如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。**
7、ajax请求get和post的区别
get 一般用于查询操作,post 一般用户提交操作
get参数拼接在url上(明文传输), post放在请求体内(数据体积可更大)
安全性:post易于防止 CSRF
8、闭包应用场景:作为参数被传入,作为返回值被返回
自由变量的查找,要在函数定义的地方(而非执行的地方
影响∶变量会常驻内存,得不到释放。闭包不要乱用
9、如何阻止事件的冒泡和默认行为
event.stopPropagation
event.preventDefault
这两个API
10、查找、添加、删除、替换DOM节点的方法?
查找:
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性
添加appendChild()
删除removeChild()
替换replaceChild()
11、如何减少DOM操作?(耗性能)
缓存DOM查询结果(获取dom的list长度的时候先把list拿出来 避免重复获取)
多次DOM操作,合并到一次插入
12、==会尝试类型转换,===严格相等
13、函数声明和函数表达式的区别
函数声明function fn() {...}
函数表达式const fn = function() {...}
函数声明会在代码执行前预加载,而函数表达式不会
14、new Object()和 Object.create()区别
{}等同于new Object,原型Object.prototype
Object.create(null)没有原型
Object.create({...})可指定原型 =>意思是创建了一个空对象,但是空对象的原型指向了{...}
15、下图关于this的题 第一个是1 第二个是undefined 如果将函数作为一个独立函数来执行的话 this就是undefined
16、\w 命中字母数字下划线 \d匹配数字
17、trim去除空格字符=>保证浏览器的兼容性
18、Math.max
19、如何用JS实现继承
class继承
prototype继承
20、如何捕获JS中的异常 =>手动捕获catch
21、 什么是JSON ?
json是一种数据格式,本质是一段字符串。
json格式和JS对象结构一致,对JS语言更友好
window.JSON是一个全局对象:JSON.stringify JSON.parse
22、获取当前页面的url参数
传统方式,查找location.search
新API,URLSearchParams
23、数组去重的几种方式
Set方式=>无序 不能重复
24、手写一个深拷贝
Object.assign()不是深拷贝,这是追加信息
const obj = {a: 10,b:20,c: 30}
Object.assign(obj, {d: 40}) //obj:{a:10,b: 20,c: 30,d: 40}
const obj1= Object.assign({},obj, {e: 50})
obj1={a:10,b: 20,c: 30,d: 40,e: 50}
第一层级的浅层拷贝
const obj = {a: 10,b:{x:100,y:100}}
const obj1= Object.assign({},obj, {c: 50})
obj.a=100 那么obj变成{a: 100,b:{x:100,y:100}} obj1没有改
obj.b.x=101 obj和obj1都改了 只拷贝了第一层级a:10 c:30 xy就不拷贝了

image-20220101203115228

拍平数组 如果是很多重就递归拍平

image-20220101205927937

万一真有土豪呢!!!