网易面试题 技术面 问题解答整理

js中的闭包是什么?
v-if和v-show之间的区别?
v-for中key值的作用?
vue中插槽的作用?
js的执行机制

详解:
1. js中的闭包是什么?
闭包是指有权访问另一个函数作用域中的变量的函数。

2.v-if和v-show之间的区别?
相同点:v-if与v-show都可以动态控制dom元素显示隐藏
实现本质方法区别:
vue-show本质就是标签
display:none;
,控制隐藏vue-if是动态的向DOM树内添加或者删除DOM元素
编译的区别
v-show其实就是在控制css
v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件
编译的条件
v-show都会编译,初始值为false,只是将display设为none,但它也编译了
v-if初始值为false,就不会编译了
性能
v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,故v-show性能更好一点。

3.v-for中key值的作用?
key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
在用v-for更新已渲染的元素列表的时候,会使用就地复用的策略;这就是说列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改了就重新渲染,不然就复用之前的元素。
4.vue中插槽的作用?
插槽就是Vue实现的一套内容分发的API,将<slot></slot>
元素作为承载分发内容的出口,没有插槽的情况下在组件标签内些一些内容是不起任何作用的。
插槽内可以是任意内容。在<child-component>你好</child-component>
内放置一些内容如上,输出内容还是在组件中的内容,直接在父组件的<child-component>
标签中定义的内容不会被渲染。在子组件template中加入<slot>
元素占位,便能渲染父组件<child-component>
标签下的内容。
具名插槽,当需要多个插槽时,可以使用<slot>
的特性:name。这个特性可以用来定义额外的插槽。
<div id="root">
<child>
<header slot="header">header</header>
<footer slot="footer">footer</footer>
</child>
</div>
Vue.component('child',{
template:`<div>
<slot name="header">default header</slot>
<div>content</div>
<slot name="footer">default footer</slot>
</div>`
}
)
var vm=new Vue({
el:'#root'
})
//输出结果是 :
header
content
footer
插槽默认内容 ,插槽可以提供一个默认内容,如果如果父组件没有为这个插槽提供了内容,会显示默认的内容。如果父组件为这个插槽提供了内容,则默认的内容会被替换掉。
作用域插槽,作用域插槽就是父组件在调用子组件的时候给子组件传了一个插槽,这个插槽为作用域插槽,该插槽必须放在template标签里面,同时声明从子组件接收的数据放在一个自定义属性内,并定义该数据的渲染方式。(解决的问题:调用了两次child组件,因为调用的是同一个子组件,所以显示的内容完全一样。如何在每次调用时能有各自的渲染效果?)
<div id="root">
<child>
<template slot-scope="props"><!--该插槽必须放在template标签内-->
<li> {{ props.value }} </li> <!--定义渲染方式-->
</template>
</child>
<child>
<template slot-scope="props">
<h1> {{ props.value }} </h1><!--定义渲染方式-->
</template>
</child>
</div>
Vue.component('child',{
data: function () {
return {
list:[1,2,3,4]
}
},
template: `<div>
<ul>
<slot v-for="value in list" :value=value>//使用slot占位
</slot>
</ul>
</div>`
})
var vm=new Vue({
el: '#root'
})
5.js的执行机制:Event loop

同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
当指定的事情完成时,Event Table会将这个函数移入Event Queue。
主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
上述过程会不断重复,也就是常说的Event Loop(事件循环)。
setTimeout
这个函数,是经过指定时间后,把要执行的任务加入到Event Queue中,又因为是单线程任务要一个一个执行,如果前面的任务需要的时间太久,那么只能等着,导致真正的延迟时间远远大于设置的时间长度。
setInterval
会每隔指定的时间将注册的函数置入Event Queue,如果前面的任务耗时太久,那么同样需要等待。唯一需要注意的一点是,对于setInterval(fn,ms)
来说,我们已经知道不是每过ms
秒会执行一次fn
,而是每过ms
秒,会有fn
进入Event Queue。一旦setInterval的回调函数fn执行时间超过了延迟时间ms,那么就完全看不出来有时间间隔了。
除了广义的同步任务和异步任务,我们对任务有更精细的定义:
macro-task(宏任务):包括整体代码script,setTimeout,setInterval
micro-task(微任务):Promise,process.nextTick
不同类型的任务会进入对应的Event Queue,比如setTimeout
和setInterval
会进入相同的Event Queue。

进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。