Promise
Promise 最大的好处是在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了
1 | new Promise((resolve, reject) => { |
闭包
函数可以访问由函数内部定义的变量。
JS 有多态吗
有
多态:同一个操作作用于不同的对象上,可以产生不同的解释和不同的执行结果。
例子:
1 | var makeSound = function (animal) { |
一个进程能创建多少个线程
Linux 下通过ulimit -u
可以查看系统中的进程上限,通过ulimit -s
查看线程的调用栈大小。假设一个进程的虚拟内存是 4G,在 Linux32 位平台下,内核分走了 1G,留给用户用的只有 3G,于是我们可以想到,创建一个线程占有了 10M 内存,总共有 3G 内存可以使用。于是可想而知,最多可以创建差不多 300 个左右的线程。因此,进程最多可以创建的线程数是根据分配给调用栈的大小,以及操作系统(32 位和 64 位不同)共同决定的。
Windows 下默认情况下,一个线程的栈要预留 1M 的内存空间 ,而一个进程中可用的内存空间只有 2G,所以理论上一个进程中最多可以开2048 个线程。
三栏布局的实现方式,尽可能多写
三列布局又分为两种,两列定宽一列自适应,以及两侧定宽中间自适应
两列定宽一列自适应:
1、使用 float+margin:
给 div 设置 float:left,left 的 div 添加属性 margin-right:left 和 center 的间隔 px,right 的 div 添加属性 margin-left:left 和 center 的宽度之和加上间隔
2、使用 float+overflow:
给 div 设置 float:left,再给 right 的 div 设置 overflow:hidden。这样子两个盒子浮动,另一个盒子触发 bfc 达到自适应
3、使用 position:
父级 div 设置 position:relative,三个子级 div 设置 position:absolute,这个要计算好盒子的宽度和间隔去设置位置,兼容性比较好,
4、使用 table 实现:
父级 div 设置 display:table,设置 border-spacing:10px//设置间距,取值随意,子级 div 设置 display:table-cell,这种方法兼容性好,适用于高度宽度未知的情况,但是 margin 失效,设计间隔比较麻烦,
5、flex 实现:
parent 的 div 设置 display:flex;left 和 center 的 div 设置 margin-right;然后 right 的 div 设置 flex:1;这样子 right 自适应,但是 flex 的兼容性不好
6、grid 实现:
parent 的 div 设置 display:grid,设置 grid-template-columns 属性,固定第一列第二列宽度,第三列 auto,
对于两侧定宽中间自适应的布局,对于这种布局需要把 center 放在前面,可以采用双飞翼布局:圣杯布局,来实现,也可以使用上述方法中的 grid,table,flex,position 实现
类的继承
- 原型链继承
1 | function Cat() {} |
介绍:在这里我们可以看到 new 了一个空对象,这个空对象指向 Animal 并且 Cat.prototype 指向了这个空对象,这种就是基于原型链的继承。
特点:基于原型链,既是父类的实例,也是子类的实例
缺点:无法实现多继承
- 构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
1 | function Cat(name) { |
特点:可以实现多继承
缺点:只能继承父类实例的属性和方法,不能继承原型上的属性和方法。
- 实例继承和拷贝继承
实例继承:为父类实例添加新特性,作为子类实例返回
拷贝继承:拷贝父类元素上的属性和方法
上述两个实用性不强,不一一举例。
- 组合继承:相当于构造继承和原型链继承的组合体。通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
1 | function Cat(name) { |
特点:可以继承实例属性/方法,也可以继承原型属性/方法
缺点:调用了两次父类构造函数,生成了两份实例
- 寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性
1 | function Cat(name) { |
较为推荐
输出程序结果
1 | async function async1() { |
执行过程:
- 输出”script start”(毋庸置疑)
- 将
setTimeout
加入宏任务队列 - 执行
async1()
函数:输出”async1 start”,运行到await
时,async2()
立即执行,输出”async2”,然后将当前任务阻塞并加入到微任务队列中,继续执行其他代码; - 执行
Promise
,输出”promise1”,并将.then()
方法加入到微任务队列; - 输出”script end”,当前微任务结束,依次执行当前宏任务中包含的微任务;
- 输出”async1 end”
- 输出”promise2”,当前宏任务的所有微任务执行结束,执行下一个宏任务;
- 输出”setTimeout”,宏任务队列为空,执行结束。
输出结果:
1 | script start |
setTimeout
就是作为宏任务来存在的,而Promise.then
则是具有代表性的微任务