0%

百度前端实习面试复盘

axios和fetch区别

二者都用来发送ajax请求,实现局部更新,axios是基于xhr的,fetch是原生支持的。

axios的拦截器是什么?有什么用?

interceptors.request可以做身份验证

interceptors.response可以做error日志处理,统一返回格式(res.data和res.data.data统一为res.data)

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
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 1000,
headers: {
'Content-Type': 'application/json'
}
})


// 类似express中的app.use,可以做身份验证
instance.interceptors.request.use(
function(config){
const token=localStorage.getItem('token')
if(token){
config.headers.Authorization=`Bearer ${token}`
}
return config
}
function(error){
return Promise.reject(error)
}
)

// 可以用来统一处理error日志,而不是在每个catch中处理
axios.interceptors.response.use(
response => {
// 处理成功的响应
console.log('Response received:', response);
// 例如统一处理数据格式
if (response.data && response.data.data) {
return response.data.data;
}
return response;
},
error => {
// 处理错误的响应
console.error('Error response:', error);
// 例如统一处理错误信息
if (error.response) {
switch (error.response.status) {
case 401:
// 处理未授权错误
console.error('Unauthorized');
break;
case 500:
// 处理服务器错误
console.error('Server error');
break;
default:
console.error('Error status:', error.response.status);
break;
}
}
return Promise.reject(error);
}
);

axios还有哪些方法?

axios.get, axios.post, axios.options(预检), axios.patch修改

axios.all(类似promise.all)

组合模式与继承

为什么组合大于继承?

这是在功能不够确定时,组合大于继承。

例如人类在建立鸟的分类系统时,如果使用单继承,就类似文件夹分类。

1
2
3
4
5
abstract class Bird {
fly() {
console.log('fly')
}
}

鸟分为麻雀、天鹅、鹈鹕等,但有些鸟会飞,有些不会。如果鸡继承鸟的话,就会有会飞这个方法,但鸡不会飞,为了避免误用,就需要抛出异常:

1
2
3
4
5
class chicken extends Bird {
fly() {
throw new Error("cannot fly")
}
}

或者分为两个类,

1
2
3
4
5
6
7
8
9
abstract class Bird {}

class FlyableBird {
fly() {
console.log('fly')
}
}

class UnFlyableBird {}

但后来随着种类增多,可能会有生殖方式、寿命、迁徙、地域、嘴巴形状、眼睛形状等等区分,这个继承层级或者说文件夹的深度会变得越来越深。

这种情况可以选择组合模式,类似标签。

1
2
3
4
5
6
7
interface Flyable {
fly(): void;
}

interface EggLayable {
layEgg(): void;
}

但这样我们就会每次都需要实现fly方法,为了减少重复代码,可以使用委托:

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
interface Flyable {
fly(): void;
}

interface Tweetable {
tweet(): void;
}

interface EggLayable {
layEgg(): void;
}

class FlyAbility implements Flyable {
fly() {
console.log("I can fly!");
}
}

class TweetAbility implements Tweetable {
tweet() {
console.log("I can tweet!");
}
}

class EggLayAbility implements EggLayable {
layEgg() {
console.log("I can lay an egg!");
}
}

class Ostrich implements Tweetable, EggLayable {
private tweetAbility: TweetAbility;
private eggLayAbility: EggLayAbility;

constructor() {
this.tweetAbility = new TweetAbility();
this.eggLayAbility = new EggLayAbility();
}

tweet() {
this.tweetAbility.tweet();
}

layEgg() {
this.eggLayAbility.layEgg();
}
}

class Sparrow implements Flyable, Tweetable, EggLayable {
private flyAbility: FlyAbility;
private tweetAbility: TweetAbility;
private eggLayAbility: EggLayAbility;

constructor() {
this.flyAbility = new FlyAbility();
this.tweetAbility = new TweetAbility();
this.eggLayAbility = new EggLayAbility();
}

fly() {
this.flyAbility.fly();
}

layEgg() {
this.eggLayAbility.layEgg();
}
}

柯里化

什么是柯里化?柯里化有什么用?

real world haskell中的“Partial Function Application and Currying”章节有讲到:“In Haskell, all functions take only one argument.”

1
2
3
4
5
ghci> :type dropWhile
dropWhile :: (a -> Bool) -> [a] -> [a]

ghci> :type dropWhile isSpace
dropWhile isSpace :: [Char] -> [Char]

dropWhile isSpace is a function that strips leading whitespace from a string.

How is this useful? As one example, we can use it as an argument to a higher order function:

1
2
ghci> map (dropWhile isSpace) [" a","f","   e"]
["a","f","e"]”

bind和curry同样是partial application,有什么不同?

bind需要绑定context,curry不需要。

  • 在解决这个问题之前,我们可以看一下bind的实现:

==和===有什么不同?

1
2
3
4
5
6
7
5=='5' // '5'会被转换为number 5
0 == false // false会被转换为0
null == undefined // true,因为它们在不进行类型转换的情况下是相等的

null === undefined // false,因为类型不同,null是object类型,undefined是undefined
console.log(typeof a); // 输出:object
console.log(typeof b); // 输出:undefined

Array API

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
let L=console.log.bind(console)
let arr=[1,2,3,4]

L(arr.some(curr=> curr==2 || curr==3)) // true
L(arr.every(curr=> curr >0)) // true
L(arr.every(curr=> curr >1)) // false

let total=0
arr.forEach((v,i)=>{
total+=v
})
L(total) // 10

L(arr.indexOf(4))
L(arr.find((curr=>curr>2))) // the first element that is bigger than 2 is 3

arr.unshift(9)
L(arr) // [9,1,2,3,4]
L(arr.toString()) // '9,1,2,3,4'
L(arr.join())

let arr1=arr.splice(1,4)
L(arr) // [9]
L(arr1) // [1,2,3,4] the element deleted

arr1.reverse()
L(arr1) // [4,3,2,1]

arr1.splice(2,0,10)
L(arr1) // [4,3,10,2,1]

arr1.sort((a,b)=>{
return a-b
})
L(arr1) // [1,2,3,4,10]

L(arr1.at(-1)) // 10