前端面试题


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


3var 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: ''
}
}
===================================