前端面试题
1、闭包 闭包就是能够读取其他函数内部变量的函数 子级函数可以访问父级函数的变量,反之不成立 例如 function f1() { var n = 999; function f2() { console.log(n); } return f2; } var result = f1(); result();//999 使用场景 原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果。 function f1(a) { function f2() { console.log(a); } return f2; } var fun = f1(1); setTimeout(fun,1000);//一秒之后打印出1 2、深浅拷贝 说白了就是 去 赋值 浅:定义对象A、B。当B拷贝了A的数据,且当B的改变会导致A改变时,此时叫B浅拷贝了A 例子: var A{ name:"martion", data:{num:10} } var B={} B=A; B.name="lucy"; console.log(A.name); ///lucy 深:当B拷贝了A的数据,且当B的改变不会导致A的改变,此时叫B深拷贝了A var A={ name:"martin", data:{num:10}, say:function(){ console.log("hello world") } } //开辟了一个新的堆内存地址,假设为placaA var B={}; //又开辟了一个新的堆内存地址,假设为placeB B=JSON.parse(JSON.stringfy(A)); B.name="lucy"; console.log(A.name); //martin 可以使用JSON对象的stringfy()、es6中的Object.assign 3、var let const 的区别 作用域不同 var是函数作用域,不能跨函数访问,可以跨块访问且快内访问。 let是块作用域, 只能在块作用域里访问,不能跨块访问,也不能跨函数访问。 const 使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改(变量), 但是在对象中可以修改里面的变量值,不能修改指定一个新的对象。 块作用域由 { } 包括,if语句和 for语句里面的{ }也属于块作用域 函数作用域 (function a(){ console.log('函数作用域') })() 可参考:https://blog.csdn.net/unionz/article/details/80032048 4、数据类型 基本类型:String 、Number、Undefined、Null、Boolean。占用空间固定,保存在栈中 引用类型:Object、Array、Function、Date。不固定、保存在堆中 堆与栈就是操作系统对进程占用的内存空间的两种管理方式 栈:由编译器自动分配 堆:一般由程序员分配释放 5、v-if 与 v-show 的区别 v-if的原理是根据条件来动态的进行增删DOM元素 v-show是根据判断条件来动态的进行显示与隐藏元素,只是动态的更改样式而不需要增删DOM元素 频繁判断展示与隐藏推荐使用v-show,v-if增删DOM会影响页面加载的性能 6、== 与 === == 比较时,先检查两个操作数据类型,如果相同,则进行===比较, 如果不同,则自动进行一次类型转换,转换成相同类型后再进行比较。 ===比较时,如果类型不同,不会自动转换类型,直接返回false. 7、盒子模型 边距、边框、填充、和实际内容组成
8、垂直居中 第一种: width:100px; height:100px; position:absolute; top:50%; left:50%; margin-left:-50px;//高度的一半 margin-top:-50px;//宽度的一半 第二种: position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
9、javaScript 创建新节点 createDocumentFragment() //创建一个DOM片段 createElement() //创建一个具体的元素 createTextNode() //创建一个文本节点 添加、移除、替换、插入 appendChild() //添加 removeChild() //移除 replaceChild() //替换 insertBefore() //插入
10、浏览器的内核 IE: trident内核 Firefox:gecko内核 Safari:webkit内核 Opera:以前是presto内核,Opera现已改用Google Chrome的Blink内核 Chrome:Blink(基于webkit,Google与Opera Software共同开发)
11、如何消除一个数组里面重复的元素? var arr1 =[1,2,2,2,3,3,3,4,5,6], arr2 = []; for(var i = 0,len = arr1.length; i< len; i++){ if(arr2.indexOf(arr1[i]) < 0){ arr2.push(arr1[i]); } } console.log(arr2)//1、2、3、4、5、6
12、判断数据类型 1) typeof typeof 123 //number typeof 'abc' //string typeof [1,2,3], //"object" typeof {a:1,b:2,c:3}, //"object" typeof function(){console.log('aaa');}, //"function" typeof undefined, //"undefined" 数组、对象等都是返回object,所以部分不是做判断 2) instanceof 123 instanceof Number, //false 'dsfsf' instanceof String, //false false instanceof Boolean, //false [1,2,3] instanceof Array, //true {a:1,b:2,c:3} instanceof Object, //true 数组、对象可使用instanceof 3) constructor
13、vue的生命周期
是指 vue 实例对象从创建到销毁的过程。
作用:有多个钩子函数,更好地控制vue实例过程时的逻辑。
常用八个钩子函数:创建前后,挂载前后,更新前后,销毁前后。
创建前:el和data属性都还没有初始化,所以不能访问;可以加loading加载事件。
创建后:data已经初始化完成,但是el还不能访问;结束loading事件。
挂载前:el和data完成了初始化,但是数据和模板没有完成,页面的内容还是vue的占位符,
这里也是页面渲染前最后一次机会更改数据。
挂载后:已渲染完成,可以操作DOM。
更新前:需要更改的数据和模板还没结合。
更新后:数据已经更改完成,dom也重新渲染完成。
销毁前:vue实例销毁之前调用。监听、定时器的移除等。
销毁后:实例销毁后,数据与视图的关系会断开,其实dom元素还是存在的,只是不再受vue控制。
第一次加载页面会触发:beforeCreate, created, beforeMount, mounted。
挂载后mounted,DOM渲染已经完成了。
父子件的生命周期顺序:先走到父组件的(挂载前),再子组件走到(挂载后),父组件再挂载到dom。
14、MVVM --- 前后端分手大师
一句话总局:vm层(视图模型层)通过ajax接口从后台m层(模型层)请求数据,vm层再和v层(视图层)实现数据的双向绑定。
view视图层:也就是用户看到的页面html、css
viewmodel视图模型层:js业务逻辑层
model模型层:数据访问层
是mvc(模型视图控制层)的加强版、数据分离、视图模型层
15、vue路由
vue-router就是用于组件之间的切换跳转传参,从而使得单页面引用变得更加简单。
路由配置参数:
path : 跳转路径 ?
component : 路径相对于的组件 ?
name:命名路由 ?
children:子路由的配置参数(路由嵌套) ?
props:路由解耦 ?
redirect : 重定向路由
有两种模式:默认是hash模式,会自动带上#号;history模式不会带#号。
16、Set 对象作用
数组去重
var mySet = new Set([1, 2, 3, 4, 4]);
[...mySet]; // [1, 2, 3, 4]
并集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var union = new Set([...a, ...b]); // {1, 2, 3, 4}
交集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}
差集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var difference = new Set([...a].filter(x => !b.has(x))); // {1}
17、vue 父子组件之间的通讯传参方式
1) 父传子 通过props
export default {//子组件
props: {
message: String //定义传值的类型
}
}
2) 子传父 通过$emit
checked(e) {
uni.$emit("handClick", e);
}
父组件 引入子组件
import Child from '@/components/Child.vue';
handC(obj){
console.log(obj); //输出子组件e传过来的值
}
3) 多级嵌套组件 通讯方式
provide:是一个对象,或者是一个返回对象的函数,里面呢就包含要给子孙后代的东西,也就是属性和属性值。
inject:一个字符串数组,或者是一个对象。属性值可以是一个对象,包含from和default默认值。
provide: {
msg: 'hello world!'
}
inject: {
msg: {
from: 'msg',
default: ''
}
}
===================================