1、vue的双向数据绑定(2和3的区别)
2、mvvm是啥,从页面点击到向后台发送请求经历了哪些步骤,分别是mvvm的哪些负责的
3、实现事件发布订阅,一通乱写
var dep = {}
function subscribe(eventName,fn){
if (dep[eventName]){
dep[eventName].push(fn)
return dep[eventName].length - 1
}else{
dep[eventName] = [fn]
return 0
}
}
function notify(eventName){
if (!dep[eventName]) return
dep[eventName].map(fn => {
fn()
})
}
function unsubscribe(eventName,index){
if(dep[eventName]){
var even = dep[eventName]
even[index] = null
// even.splice(index,1)
}
}
4、单线程异步的问题,宏任务微任务
const p1 = new Promise((resolve, reject) => {
console.log(1)
resolve(2)
})
setTimeout(() => console.log(3))
console.log(4)
p1.then(v => console.log(v))
输出顺序
1 4 2 3
5、开发过程中有没有用到过宏任务和微任务
6、说用个nextTick(自己挖坑)底层实现不了解
关于nextTick和视图的异步更新,参考这篇文章https://funteas.com/topic/5a8dc7c8f7f37aa60a177bb7
js线程中每一个宏任务(task)结束后会重新渲染视图,每个循环中的所有微任务会在当前同步任务的后面紧接着执行,然后再执行task。vue视图的异步更新涉及到watcher,每个变量都有一个自己的watcher,总的有一个存放所有watcher对象的watcherqueue,wathcerqueue中flushwatcherqueue(?类似这个名字,执行wather队列里所有的回调函数)是通过nextTick函数执行的。nextTick目前是以微任务的形式执行的(如果有原生的promise就用promise,没有就用mutationObserver,再没有就用setTimeout宏任务执行),由于每个宏任务结束后都会引起视图的刷新重绘,所以选择用微任务的形式执行异步任务,提高性能。
watcher里面的如果有个for函数,累加到1000的,真正生效的只有最后的1000,因为如果某个watcherid已经存在于队列中,就不会增加,只替换掉当前的watcher。
拥有相同id
的Watcher
不会被重复加入到该queue
中去,所以不会执行1000
次Watcher
的run
。最终更新视图只会直接将test
对应的DOM
的0
变成1000
。 保证更新视图操作DOM
的动作是在当前栈执行完以后下一个Tick
(或者是当前Tick
的微任务阶段)的时候调用,大大优化了性能。
7、数组去重,indexOf是怎么实现的,时间复杂度是多少,怎么写个O(n)的,用了个set
function fn(arr){
return arr.filter((item,index) => {
return arr.indexOf(item) === index
})
}
function indexof(arr,target){
for(var i = 0;i < arr.length;i++){
if(target === arr[i]){
return i
}
}
}
Array.prototype.concat.apply([],new Set(arr))// 虾jb写的啥啊.....
//正真的set转成array的方法
Array.from(new Set([1,1,3,2]);
or
[...new Set([1,2,2])]
//搜了一下,O(n)的方法可以用Object.keys()实现,会返回由对象的key组成的数组
function fn(arr){
var obj = {};
arr.map(item=> {
obj[item]='';
});
return Object.keys(obj);
}
8、重排和重绘区别,visibility:hidden
9、闭包实现,写了半天.....挤出来了.......
实现一个函数,fOnce
const f1 = () => console.log(1)
const f2 = () => console.log(2)
const wrappedF = fOnce(f1)
wrappedF() //1
wrappedF() // it has been executed
wrappedF() // it has been executed
const wrappeedF2 = fOnce(f2)
wrappedF() //2
wrappedF() // it has been executed
wrappedF() // it has been executed
function fOnce(fn){
var flg = true
return function(){
if(flg){
fn()
flg = false
}else {
console.log('It has been executed')
}
}
}