前言
盘点一下自己平时在工作中的面试题
第一部分 HTML5+CSS篇
1、什么是外边距合并?
多个相邻普通流的垂直方向的margin折叠这种情况称为外边距合并。
| 同正 | 同负 | 一正一负 |
|---|---|---|
| 取较大值 | 取绝对值较大 | 取相加值 |
2、如何让一个宽度不确定的div盒子水平垂直居中?
.father{
position:relative;
}
.son{
position:absolute;
margin:auto;
top:0;
left:0;
right:0;
bottom:0;
}
第二部分 JS篇
1、什么是深拷贝和浅拷贝?
深拷贝:在堆中重新分配内存,互不影响
浅拷贝:仅复制了引用,互有影响
2、null和undefined的区别?
null是一个表示"无"的对象,转为数值时为0;
undefined是一个表示"无"的原始值,转为数值时为NaN。
两者在转为布尔值时都是false。
null的典型用法:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
undefined的典型用法:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
3、什么是闭包?
内部函数总是可以访问其所在的外部函数中声明的参数和变量就称为闭包。
闭包的优缺点:
优点:
1:变量长期驻扎在内存中;
2:避免全局变量的污染;
3:私有成员的存在;
缺点: 会增大内存的使用量,使用不当会造成内存泄露。
解决方法:
在退出函数之前,将不使用的局部变量全部删除。
4、js的new操作符做了哪些事情?
new新建了一个空对象,这个对象的原型指向构造函数的protype,执行构造函数后返回这个对象。
代码如下:
var Func=function(){
};
var func=new Func ();
new操作符一共经历了4个阶段:
(1)新建空对象
var obj = new Object();
(2)设置原型链
obj._proto_ = Func.prototype;
(3)让Func的this指向obj,并执行函数体
var res = Func.call(this);
(4)判断返回值res的类型
if(typeof(res)=="object"){//引用类型,就返回这个引用类型的对象
func = res
}else{//值类型 返回obj
func = obj
}
默认情况下函数返回值为undefined,即没有显示定义返回值的话,但构造函数例外,new构造函数在没有return的情况下默认返回新创建的对象。
但是,在有显示返回值的情况下,如果返回值为基本数据类型{string,number,null,undefined,Boolean},返回值仍然是新创建的对象。
只有在显示返回一个非基本数据类型时,函数的返回值才为指定对象。在这种情况下,this所引用的值就会被丢弃了。
5、谈对this的理解
this的指向不是在编写时确定的,而是在执行时确定的,同时,this不同的指向遵循了一定的规则。
1、在执行时确定:
function foo(){
console.log(this.age)
}
obj = {
age:12,
foo:foo
}
obj.foo()//被调用的位置被对象obj拥有,因此结果是12
2、new的this指向新对象
var Function = function(name){
this.name = name
console.log(name)
}
var func = new Function('hi')//hi
3、箭头函数的this
箭头函数的this指向它所在的上下文,也就是父级。
第三部分 Vue篇
1、Vue 组件中 data 为什么必须是函数?
vue组件中data值不能为对象,因为对象是引用类型,组件可能会被多个实例同时引用。 如果data值为对象,将导致多个实例共享一个对象,其中一个组件改变data属性值,其它实例也会受到影响。
2、Vue.nextTick()的理解
(1)Vue.nextTick()是什么?
官方文档解释如下:
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
所以就衍生出了这个获取更新后的DOM的Vue方法。所以放在Vue.nextTick()回调函数中的执行的应该是会对DOM进行操作的 js代码。
(2)使用场景:
在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中
(3)原因说明:
在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载已完成。
总之,在某个动作有可能改变DOM元素结构的时候,对DOM一系列的js操作都要放进Vue.nextTick()的回调函数中。
代码示例
<template>
<div id="msg">hello world</div>
</template>
<script>
export default{
created(){
this.$nextTick(()=>{
console.log(document.getElementById('msg').innerText)
})
}
}
</script>
2、Vue.set()的使用
使用场景 在vue项目中,为data的某一对象添加属性之后,却发现视图并没有更新?
这是为什么呢?
这是因为受javascript的限制,vue.js不能监听到对象属性的添加和删除,因为在vue组件初始化过程中会调用getter和setter方法,所以属性都是必须一开始就存在于对象中,视图层才能响应到该数据的变化。
Vue.set()方法就是用来解决这个问题的
比如我们需要给一个student对象添加hobby属性,可以这样写:
this.$set(student,'hobby','reading')
另一种方法是:
this.student.hobby = 'reading'
this.student = Object.assign({},this.student)
为什么这两种方式可以解决上述问题呢?
因为通过这两种方式为对象添加属性之后,对象的身上多了get和set方法,所以,此时我们再次操作该属性的时候,就会引起视图的更新了。
图示:
图2是仅使用了一行代码this.student.hobby = 'reading',打印出的student,里面只是新增了hobby属性,但是没有get hobby和set hobby的方法。
第四部分:webpack篇
1、webpack是什么?
webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。当 webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle。
2、webpack的作用:
webpack 的作用就是处理依赖,模块化,打包压缩文件,管理插件。
由于webpack只支持js文件,所以需要用loader 转换为webpack支持的模块。
3、webpack的工作流程:
(1)解析配置参数,合并从shell(npm install 类似的命令)和webpack.config.js文件的配置信息,输出最终的配置信息;
(2)注册配置中的插件,让插件监听webpack构建生命周期中的事件节点,做出对应的反应;
(3)解析配置文件中的entry入口文件,并找出每个文件依赖的文件,递归下去;
(4)在递归每个文件的过程中,根据文件类型和配置文件中的loader找出对应的loader对文件进行转换;
(5)递归结束后得到每个文件最终的结果,根据entry 配置生成代码chunk(打包之后的名字);
(6)输出所有chunk 到文件系统。