bom和dom
bom
概念:浏览器对象模型,将浏览器看做了一个对象
顶级对象: window
包含关系: bom是包含dom的
常见的api: location、navigator、screen、setInterval/setTimeout、locstorage、sessionStorage
浏览器常见缓存的区别
locstorage:
大小:5~20MB
生命周期:永久,手动清除
api使用:方便
sessionStorage
大小:5~20MB
生命周期:窗口关闭
api使用:方便
cookie
大小:4KB
生命周期:时间设置
请求:自动携带
api使用:不方便(js-cookie)
dom
概念: 文档对象模型, 将网页文档看做了一个对象
顶级对象 :document
包含关系: 被bom包含因为document是在window上,所以dom是属于bom的
常见api: getElementById getElementByTagName querySelector querySelectorAll
slice和splice两者的区别
- slice 用于截取, 参数1,开始的位置,参数2结束的位置(不包含)
- splice: 用于删除/新增 参数1: 开始的位置,参数2: 删除的个数, 参数3和参数3之后的所有参数新增的数据
substr和subString
- substr: 用于截取,参数1: 开始的位置,参数2截取的个数
- substring: 用于截取,参数1: 开始的位置,参数2: 结束的位置(不包含)
使用过哪些es6?
聊一聊promise
概念
promise是一个对象/构造函数,es6新增的,更加灵活的处理异步,也可以解决回调地狱问题
promise有三种状态:pending fullfield rejected状态不可逆 pending => (resolve)fullfield,pending =>(rejecte) rejected
实例方法
- then方法:接收promise处理后的结果,
-
- 第一个回调接收成功的结果,第二个回调用于接收失败的结果
- then支持链式调用,在then中可以返回新的promise,并且调用resolve,会将成功的结果传递到下一个then中,所以借助then的链式解决了回调地狱的问题
- 具备穿透性:在then中通过返回的promise调用resolve传递数据,下一个then如果没有通过回调进行接收,则会继续向下传递
- then的返回值是promise,而且then的成功回调如果返回的不是promise,也会被then的promise的resolve进行处理
- 终止then的成功回调的链式:reject、throw Error Promise.reject
- catch方法:专门处理失败的状态
- finnaly方法:都会执行
静态方法
- all:同时处理多个异步,语法参数为数组,数组每一项是Promise实例,只有所有异步处理成功,才会进入then的成功回调,有一个失败,进入all的then的失败回调,结果是数组,值对应的就是参数数组的顺序
- allsettled:语法基本和all一致,不管处理的异步中是否调用reject,最终都会进入allsettled的成功回调,在成功的回调中,数组每一项是对象,对象会有status,状态,成功或失败,还有value就是异步处理的结果
- race:语法基本和all一致,可以获取到异步处理最快的那一个,在then中通过成功回调或失败回调获取结果
- any:语法基本和all一致,可以获取到异步处理成功最快的那一个
async和await
promise的终极解决方案是async await
await 用来修饰promise, 当然await也可以修饰非promise,如果修饰的不是promise则会将 await后面的内容包装为promise,await的返回值会一直是promise的resolve处理,await下面的代码相当于是promise的then成功回调的代码,所以await下面的代码属于异步微任务
async用来修饰await就近的函数,被async修饰的函数,该函数返回值为promise,内部如果return数据,则该数据被promise的resolve进行处理,所以需要通过函数的then的成功回调获取期结果
async和await实际是generator的语法糖
Generator
概念: 也是es6的,可以将函数的控制权交出,也可以利用generator更方便的控制异步,实际async和await就是他的语法糖
区分: 星号
如何交出控制权: 通过yield进行控制权交出,通过next逐步调用
如何处理异步: 可以通过yield配合promise达到类似async和await的效果,通过yiled返回promise,在promise中处理异步,等异步成功调用resolve,这样在外部可以通过next.value获取到promise,通过then等待成功后,执行下一次的next
而且对应的自执行generator函数有co库,可以去自执行generator
区别:
new的过程
创建一个新对象
// 将新对象的__proto__ 指向了 Person.prototype
// 将构造函数内部的this指向新对象
// 执行构造函数给this(实例对象)添加属性或方法
// 默认return this
// 如果写了return 看 数据类型
// 数据类型是简单数据类型: return简单数据类型忽略 最终还是return this
// 如果数据类型是复杂数据类型: 最终得到是该复杂数据类型 return this无效
字符串反转
'hello'.split('').reverse()
forin/forof区别
for in:一般用来遍历对象,并且可以遍历原型对象,不建议循环数组,可以循环
for of:不可以进行遍历普通对象的,可以遍历数字字符串数组和 newSet 对象等等,并且可以进行 break 终止,不可以 return
中断for
- continue:终止该次循环,进入下一次,使用所有循环结构
- break:跳出循环,执行循环后的语句,如果多层循环,只会退出当前层循环
- return:终止循环,结束当前方法
统计数组中出现次数最多的元素
// 统计出出现次数最多的元素 返回次数和元素
const arr = [1, 2, 3, 2, 3, 2, 3, 7, 8, 7, 6, 7, 5, 7, 0, 7, 7, 7, 7, 2, 5, 5, 5, 5, 5, 5]
function repeatCount(arr) {
// key 是元素 value: 次数
const obj = {}
let max = 0
let maxItem = null
for (let i = 0; i < arr.length; i++) {
const item = arr[i]
if (obj[item]) {
obj[item]++
} else {
obj[item] = 1
}
if (obj[item] > max) {
max = obj[item]
maxItem = item
}
}
console.log(maxItem, max)
}
repeatCount(arr)
递归使用场景
export function transListToTree(data, pid) {
const arr = []
data.forEach((item) => {
if (item.pid === pid) {
// 当前: item 就是1级数据 item.id
const children = transListToTree(data, item.id)
if (children.length) {
item.children = children
}
arr.push(item)
}
})
return arr
}
聊一聊异步
为什么有异步?
js是单线程,如果js语言是多线程,在操作dom容易混乱,所以js就是单线程,问就是,如果某一个任务比较耗时,阻塞运行,js把耗时交给浏览器执行,交给浏览器执行的这些耗时任务: 异步任务
js在es5之前无法发起异步,es6的Promise可以发起异步
异步执行流程
- 主线程先判断任务类型
-
- 如果是同步任务,主线程自己执行
- 如果是异步任务,交给宿主环境(浏览器)执行
- 浏览器进行异步任务的执行,每个异步执行完后,会将回调放进任务队列,先执行完成的先放进任务队列,依次放入
- 等主线程任务全部执行完后,发现主线程没有任务可执行了,会取任务队列中的任务,由于任务队列里是依次放入进来的,所以取得时候也会先取先进来的,也就是先进先出原则
- 在任务队列中取出来的任务执行完后,在取下一个,依次重复,这个过程也称为 eventLoop 事件轮训
异步的解决方案
- 回调
- promise
- async await
- generator
es6模块化和commonjs模块化的区别
- es模块化的导入: import import {} import * as
- es6模块化的导出: export export default
- commonJs模块化导入: require
- commonjs模块化导出: module.exports module
箭头函数和普通函数的区别
- 箭头函数this指向上下文,普通函数this看调用方式
- 剪头函数没有arguments对象,普通函数具备arguments对象
- 箭头函数没有prototype, 普通函数具备prototype
- 箭头函数不能用做构造函数,普通函数可以用做构造函数
对闭包是怎么理解的?
- 基本形式:两个嵌套关系的函数,内部函数可以访问外部函数定义的局部变量,那么该变量与内部函数就构造了闭包的形式
- 优点:形成私有空间,避免全局变量的污染
- 缺点:持久化内存,导致内存泄露
- 解决:
-
- 1、尽快避免函数的嵌套,以及变量的引用
- 2、执行完的变量,可以赋值null,触发垃圾回收机制,进行回收释放内存
描述下垃圾回收机制?
首先:垃圾回收机制内部算法:引用计数 和 标记清除
接下来:
- 引用计数:把堆上对象能够访问次数记下来,如果发现某个对象计数为0,算法认为没有变量访问这个对象。该对象所占空间,判定是垃圾,进行回收!但是:如果两个对象相互引用,各自计数永远不会为0,不会判定为是垃圾,不会回收!所以:主流浏览器不再使用该算法!
- 标记清除:核心就是 从 使用对象次数 到 无法到达对象;只要是堆上对象无法访问,哪怕是对象相互引用,但是无法访问,算法对该对象标记为垃圾空间!
什么是原型对象和原型链
答:
原型对象:每个构造函数都有prototype属性,这个属性的值是个对象,称之为原型对象!
原型链:对象都有__proto__属性,这个属性指向它的原型对象,原型对象也是对象,也有__proto__属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链.
原型链有什么意义?
总得来说:给实例化对象上调用方法或使用某个属性,提供查询机制!
具体查询:
先在实例化对象本身上去找该方法!
如果没有,去实例化对象的__proto__(原型对象上去找)
如果当前原型对象上还没有该方法,继续往原型对象上的原型对象上去找
如果还是没有找到,报错 对象.xxx is not function
你能说说怎么理解事件循环机制的?
1、JavaScript 是一门单线程语言. 单线程可能会出现阻塞的情况,所js分了同步任务和异步任务。
2、同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入 任务队列。
3、主线程内的任务执行完毕为空,会去 任务队列 读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。
怎么理解面向对象
答:1、面向对象是一种软件开发的思想和面向过程是相对应的,就是把程序看作一个对象,将属性和方法封装其中,以提高代码的灵活性、复用性、可扩展性。
2、面向对象有三大特性:封装、继承、多态。
封装:把相关的信息(无论数据或方法)存储在对象中的能力
继承:由另一个类(或多个类)得来类的属性和方法的能力
多态:编写能以多种方法运行的函数或方法的能力
3、js中对象是一个无序的数据集合或者也可以说是属性和方法的集合,可以动态的添加属性可方法。
4、js是基于对象,但是也使用了嵌入了面向对象的思想,可以实现继承和封装,这样也可以提供代码的灵活性和复用性。