0%

域名解析问题

这段时间在迁移服务器,发现网页再刷新对时候每次刷新数据都会不一样,检查完以后发现是域名解析的问题.
在阿里云域名进行解析都时候,在解析到新服务器的时候,老服务器域名的解析没有删除.(是否需要加一个弹窗?)
每一次请求都会请求到不同的服务器,导致每次的数据都不一样,emmmm(如果数据库同步了,是不是可以这么做负载均衡,笑..)

结论

自己不仔细,删完老服务器绑定的域名以为可以了.域名解析页面没有注意到还有第二页

介绍下重绘和回流(Repaint & Reflow),以及如何进行优化

个人题解

浏览器渲染主要经过三个阶段

1、dom树与style树合成渲染树
2、计算节点的位置与大小的阶段叫回流
3、渲染计算好的节点叫重绘

如何优化

1、减少dom插入次数,可以用虚拟的节点,计算好以后,一次性插入到dom中
2、动画可以使用绝对布局,脱离文档流
3、使用gpu加速相关的属性,比如transition
4、修改的节点可以先隐藏,修改完毕后再进行显示.

相关链接

你真的了解回流和重绘吗 #4
最高赞作者github

有以下 3 个判断数组的方法,请分别介绍它们之间的区别和优劣Object.prototype.toString.call() 、 instanceof 以及 Array.isArray()

个人题解

1、Object.prototype.toString.call(),是使用原型上的toString()方法,输出为[Object xxxxx],通过xxxxx的内容判断当前的类型.目前大部分判断类型都是基于此方法,比较准确

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
console.log(Object.prototype.toString.call([1, 2, 3])); //[object Array]
console.log(Object.prototype.toString.call(1)); //[object Number]
console.log(Object.prototype.toString.call(NaN)); //[object String]
console.log(Object.prototype.toString.call("1")); //[object Function]
console.log(Object.prototype.toString.call(() => {})); //[object Number]
console.log(Object.prototype.toString.call(undefined)); //[object Undefined]
console.log(Object.prototype.toString.call(null)); //[object Null]
console.log(Object.prototype.toString.call({})); //[object Object]
console.log(Object.prototype.toString.call(/reg/)); //[object RegExp]
console.log(Object.prototype.toString.call(true)); //[object Boolean]
console.log(Object.prototype.toString.call(Symbol)); //[object Function]
console.log(Object.prototype.toString.call(new Set())); //[object Set]
console.log(Object.prototype.toString.call(new Map())); //[object Map]
console.log(Object.prototype.toString.call(new Date())); //[object Date]
console.log(Object.prototype.toString.call(new WeakSet())); //[object WeakSet]
console.log(Object.prototype.toString.call(new WeakMap())); //[object WeakMap]
// ....

2、instanceof是基于原型链的判断方法,一个数组会找到他的原型是不是属于array,如果是返回true

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
let fsimpleStr = "This is a simple string"; 
let fmyString = new String();
let fnewStr = new String("String created with LETructor");
let fmyDate = new Date();
let fmyObj = {};
let fmyNonObj = Object.create(null);
simpleStr instanceof String; // 返回 false, 检查原型链会找到 undefined
myString instanceof String; // 返回 true
newStr instanceof String; // 返回 true
myString instanceof Object; // 返回 true

myObj instanceof Object; // 返回 true, 尽管原型没有定义
({}) instanceof Object; // 返回 true, 同上
myNonObj instanceof Object; // 返回 false, 一种创建非 Object 实例的对象的方法

myString instanceof Date; //返回 false

myDate instanceof Date; // 返回 true
myDate instanceof Object; // 返回 true
myDate instanceof String; // 返回 false

class Parent {}
class Child extends Parent {}
let demo = new Child();
console.log(demo instanceof Child); // true
console.log(demo instanceof Parent); // true
console.log(demo instanceof Object); // true

3、Array.isArray(),Array对象上提供的判断是否是数组的方法,比较准确

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
Array.isArray([1, 2, 3]);  
// true
Array.isArray({foo: 123});
// false
Array.isArray("foobar");
// false
Array.isArray(undefined);
// false

// 下面的函数调用都返回 true
Array.isArray([]);
Array.isArray([1]);
Array.isArray(new Array());
Array.isArray(new Array('a', 'b', 'c', 'd'))
// 鲜为人知的事实:其实 Array.prototype 也是一个数组。
Array.isArray(Array.prototype);

// 下面的函数调用都返回 false
Array.isArray();
Array.isArray({});
Array.isArray(null);
Array.isArray(undefined);
Array.isArray(17);
Array.isArray('Array');
Array.isArray(true);
Array.isArray(false);
Array.isArray(new Uint8Array(32))
Array.isArray({ __proto__: Array.prototype });

相关链接

第 21 题:有以下 3 个判断数组的方法,请分别介绍它们之间的区别和优劣Object.prototype.toString.call() 、 instanceof 以及 Array.isArray()
MDN isArray
MDN instanceof

如何实现a=1a=2a=3

个人题解

1
2
3
4
5
6
7
8
9
10
11
// node
let b = 1;
Object.defineProperty(global, "a", {
get() {
return b++;
},
});

console.log(a===1); // true
console.log(a===2); // true
console.log(a===3); // true

谈谈你对TCP三次握手和四次挥手的理解

个人题解

tcp 三次握手

1、客户端:发送报文到服务器,表示我要发送请求了
2、服务端:确认客户端请求,返回确认报文,表示可以接收数据
3、客户端:确认报文,建立tcp链接

tcp 三次挥手

1、客户端:发送断开链接报文,表示我要断开链接了
2、服务端:收到断开链接报文,确认信息包是否发送完毕
3、服务端:信息发送完毕,返回确认报文
4、客户端:收到服务端到确认消息,断开链接.服务端会等待一定时间,确认没有新的消息,然后断开链接.

高赞题解

20200907103418

相关链接

第 16 题:谈谈你对 TCP 三次握手和四次挥手的理解 #15
最高赞作者github

简单讲解一下http2的多路复用

个人理解

不会

最高赞题解

在 HTTP/1 中,每次请求都会建立一次HTTP连接,也就是我们常说的3次握手4次挥手,这个过程在一次请求过程中占用了相当长的时间,即使开启了 Keep-Alive ,解决了多次连接的问题,但是依然有两个效率上的问题:

第一个:串行的文件传输。当请求a文件时,b文件只能等待,等待a连接到服务器、服务器处理文件、服务器返回文件,这三个步骤。我们假设这三步用时都是1秒,那么a文件用时为3秒,b文件传输完成用时为6秒,依此类推。(注:此项计算有一个前提条件,就是浏览器和服务器是单通道传输)
第二个:连接数过多。我们假设Apache设置了最大并发数为300,因为浏览器限制,浏览器发起的最大请求数为6,也就是服务器能承载的最高并发为50,当第51个人访问时,就需要等待前面某个请求处理完成。
HTTP/2的多路复用就是为了解决上述的两个性能问题。
在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。
帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。
多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。

结论

不会

参考

第 15 题:简单讲解一下 http2 的多路复用 #14
http1.1 与 http2 对比
HTTP/2 相比 1.0 有哪些重大改进?
HTTP/2 资料汇总

如何实现一个new

个人题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Demo(a, b) {
this.a = a;
this.b = b;
}
Demo.prototype.test = function () {
console.log(this.a);
};

function newConstructor(cons) {
return function () {
let result = {};
cons.apply(result, arguments);
result.__proto__ = cons.prototype;
return result;
};
}

let newDemo = newConstructor(Demo);
let a = newDemo(1, 2);
a.test();
  • 试了好一会试出来的
  • 一直用prototype方法不行,挠头….
  • proto 这个方法记得不是标准写法
  • 标准写法是contructor prototype?看答案吧

最高赞题解

1
2
3
4
5
function _new(fn, ...arg) {
const obj = Object.create(fn.prototype);
const ret = fn.apply(obj, arg);
return ret instanceof Object ? ret : obj;
}

先理清楚 new 关键字调用函数都的具体过程,那么写出来就很清楚了

  • 首先创建一个空的对象,空对象的proto属性指向构造函数的原型对象
  • 把上面创建的空对象赋值构造函数内部的this,用构造函数内部的方法修改空对象
  • 如果构造函数返回一个非基本类型的值,则返回这个值,否则上面创建的对象

结论

  • proto 不是标准对象,使用Object.create(fn.prototye)创建原型对象
  • 需要判断传入的对象是不是null或者undefined来判断是否返回实例对象
  • 不需要使用必包的方式进行返回(单例模式或许可以)

相关链接

如何实现一个new
最高赞作者github

斐波那契额数列第n位 算法题

个人题解

递归的方式

1
2
3
4
5
6
7
function fibonacci(n) {
if (n === 0 || n === 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
fibonacci(40)

结论:

  • 运行时间为1360ms左右,性能比较差
  • 到45位的时候计算时间已经是15s

递归的方式,加一层缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function fibonacci(n, cache) {
if (n === 0 || n === 1) {
return n;
}
if (!cache) {
cache = {};
}
if (cache[n]) {
return cache[n];
}
cache[n] = fibonacci(n - 1, cache) + fibonacci(n - 2, cache);
return cache[n];
}
fibonacci(40)

结论:

  • 第5000位的时候是9ms,此时数值已经是超过js最大数值,为Infinity
  • 9000位左右递归栈会爆掉

循环的方式

1
2
3
4
5
6
7
8
function fibonacci(n) {
let arr = [0, 1];
for (let i = 0; i < n; i++) {
arr.push(arr[arr.length - 1] + arr[arr.length - 2]);
}
return arr[n - 1];
}
fibonacci(50)

结论:

  • 性能最佳,5000位约7毫秒

总结

  • 递归一般情况下性能比普通循环要低
  • 递归可能会爆栈
  • 除非必须要递归的方式、其他方案成本过高、能确定递归次数较少,不然不建议用递归
  • 某些文档提到尾递归可以提高性能,但是这个斐波那契额数列,没有找到使用尾递归的方式,单独开一篇尾递归的内容

Promise 构造函数是同步执行还是异步执行,那么 then 方法呢?

个人题解

构造函数是同步执行,then的时候是异步

1
2
3
4
5
6
7
8
9
10
11
12
13
const demo = function () {
return new Promise((reslove, reject) => {
console.log(1);
reslove(2);
console.log(3);
});
};

demo().then((res) => {
console.log(res);
});

//1 3 2

相关链接

一开始底牌尽处的人,注定是输家.