• 前端面试题


    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
    可以利用json.parse和json.stringfy的转换
    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


    3var let const 的区别 作用域不同 var是函数作用域,不能跨函数访问,可以跨块访问且快内访问。 let是块作用域, 只能在块作用域里访问,不能跨块访问,也不能跨函数访问。 const 使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改(变量), 但是在对象中可以修改里面的变量值,不能修改指定一个新的对象。
    const a = 1;//定义变量
    a=2;//报错
    const aa = { name : 'wilson' };//定义对象
    aa.name = 'lst';//不报错
    aa = { name : 'lst'};//报错 块作用域由 { } 包括,if语句和 for语句里面的{ }也属于块作用域 函数作用域 (function a(){ console.log(
    '函数作用域') })() 4、数据类型 基本类型:String 、Number、Undefined、Null、Boolean。占用空间固定,保存在栈中 引用类型:Object、Array、Function、Date。不固定、保存在堆中 堆与栈就是操作系统对进程占用的内存空间的两种管理方式 栈:由编译器自动分配 堆:一般由程序员分配释放 5、v-if 与 v-show 的区别 v-if的原理是根据条件来动态的进行增删DOM元素 v-show是根据判断条件来动态的进行显示与隐藏元素,只是动态的更改样式(display:none)而不需要增删DOM元素 频繁判断展示与隐藏推荐使用v-show,v-if增删DOM会影响页面加载的性能 6、== 与 === == 比较时,先检查两个操作数据类型,如果相同,则进行===比较, 如果不同,则自动进行一次类型转换,转换成相同类型后再进行比较。 ===比较时,如果类型不同,不会自动转换类型,直接返回false. 7、盒子模型 外边距margin、边框border、内边距padding、和实际内容content组成
    8、垂直居中 第一种: 100px; height:100px; position:absolute; top:50%; left:50%; margin-left:-50px;//高度的一半 margin-top:-50px;//宽度的一半 第二种: position: fixed; top:50%; left:50%; transform: translate(-50%,-50%) scale(1);
    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。

    el的解释:vue实例挂载的元素节点

    例如:

    new Vue({

      el:'#app',

      data:{

        msg:'hello world'

      }

    })

    14、MVVM --- 前后端分手大师

    一句话总局:vm层(视图模型层)通过ajax接口从后台m层(模型层)请求数据,vm层再和v层(视图层)实现数据的双向绑定。

    view视图层:也就是用户看到的页面html、css

    viewmodel视图模型层:js业务逻辑层

    model模型层:数据访问层

    是mvc(模型视图控制层)的加强版、数据分离、视图模型层

    15、vue路由

    vue-router就是用于组件之间的切换跳转传参。

    路由有两种跳转的方式:声明式导航(router-link:务必要有to属性)

               编程式导航($routrt.push | replace)

    编程式更加推荐,因为更好的编写自己的业务逻辑

    路由传参的参数有两种写法:

    1、params参数:属于路径的一部分,在配置路由的时候需要占位 例如 /detail/18

    2、query参数:不需要占位,类似ajax中的queryString 例如 /detail?id=10&lst=10

    路由传参的方法

    1、纯字符串形式

    this.$router.push("/detail/"+this.id+"?id="+this.id)     PS : params参数时要在路由配置里面写好占位

    2、模板字符串

    this.$router.push(`/detail/${this.id}?id=${this.id}`)

    3、对象写法 (常用的)

    this.$router.push({name:"detailRou",params:{id:this.id},query:{id:this.id}})  PS :需要在路由配置里面写它的名字name

    路由传递参数(对象写法),path不可以结合params参数一起使用。

    如何指定params参数可传可不传?在配置路由的时候,在占位的后面加上问号?

    params参数传的是空串的解决办法,使用undefined解决

    this.$router.push({name:'detailRou',params:{id:''||undefined}})

    路由组件可以传props数据(了解一下即可)

    1、布尔值写法

    props:true

    2、对象写法

    props:{a:1,b:2}

    3、函数写法

    props:($route)=>{

      return {id:$route.params.id,id:$routr.query.id}

    }

    路由配置参数:
    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
    <child :message="parentMsg"></child>//父组件
    export default {//子组件
    props: {
    message: String //定义传值的类型
    }
    }
    2) 子传父 通过$emit
    <div @click.stop="checked(item)"></div>//子组件
    checked(e) {
    uni.$emit("handClick", e);
    }
    父组件 引入子组件
    import Child from '@/components/Child.vue';
    <Child :handClick="handC"></Child>
    handC(obj){
    console.log(obj); //输出子组件e传过来的值
    }
    3) 多级嵌套组件 通讯方式
    provide:是一个对象,或者是一个返回对象的函数,里面呢就包含要给子孙后代的东西,也就是属性和属性值。
    inject:一个字符串数组,或者是一个对象。属性值可以是一个对象,包含from和default默认值。
    provide: {
      msg: 'hello world!'
    }
    inject: {
    msg: {
    from: 'msg',
    default: ''
    }
    }

    4)兄弟之间的传递

    第一种:

    在main.ji里面利用原型prototype声明

    Vue.prototype.$bus=new Vue();

    子组件一:

    this.$bus.$emit('name',this.name);//传

    子组件二:

    this.$bus.$on('name',(res)=>{

      res =》则是子组件一传过来的数据

    })

    第二种方法

    利用父组件做中转站 (组件1传给父组件,父组件再传给组件2)

    组件1:this.$emit('name',this.name)

    父组件:

    <child1 @name="getName"></child1>//接收组件1传来的值

    <child2 :name="name">//父组件把值传给组件2

    getName(data){

      this.name=data;

    }

    组件2:

    prop{

      nmae:String;//接收父组件传来的值

    }

    ===================================
    <script>
    export default {
    // 父组件通过provide将自己的数据以对象形式传出去
    provide(){
    return {
    parentValue:"我是父组件的值啊"
    }
    }
    };
    </script>
    <script>
    export default {
    // inject:["parentValue"], // 使用一个注入的值作为数据入口:
    inject:{
    // 使用一个默认值使其变成可选项
    parentValue: { // 健名
    from: 'parentValue', // 来源
    default: 'parentValue' // 默认值
    }
    }
    }
    </script>

    18、es6 新特性
    1) let、const、var

    2) 箭头函数
    => 代替了 function()
    var perSon= (item,i) => {
    console.log('456')
    };

    this指向不同:箭头函数指向定义时候外层的第一个普通函数的this,如果没,则指向最外层的window;普通函数指向调用它的对象,也就是说谁调用了它就指向谁。

    箭头函数定义时就指定了,不可修改this指向(call、apply、bind)。

    箭头函数不能作为构造函数,不能使用new。

    箭头函数没有原型portotype、没有arguments。

    3) 拼接字符串
    es6之前都是 通过“\”和“+”来构建。
    现在 `${}` 反引号``+${}
    比如:url: `/pages/store/home/index?id=${id}`

    4)for...of 和 for...in
    let letters = ['a', 'b', 'c'];
    letters.size = 3;
    for (let letter of letters) {
    console.log(letter);
    }
    // 结果: a, b, c
    let stus = ["Sam", "22", "男"];
    for (let stu in stus) {
    console.log(stus[stu]);
    }
    // 结果: Sam, 22, 男

    5)对象和数组的解构
    // 对象
    const student = {
    name: 'Sam',
    age: 22,
    sex: '男'
    }
    const { name, age, sex } = student;
    //数组
    const arr=[100,200,300];
    let [x,y,z]=arr;
    console.log('输出:',x,y,z)
    解构不成功就是undefine

    6)二进制和八进制的字面量
    通过在数字前面添加 0o 或者0O 即可将其转换为八进制值
    let oValue = 0o10;
    console.log(oValue); // 8

    let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`
    console.log(bValue); // 2

    19、跨域

    什么事跨域:协议、域名、端口号不同的请求,称为跨域

    解决方法:JSONP、CROS、代理

    常用 代理:webpack提供的devServer,在webpack.config.js也就是vue.config.js

    20、vuex状态管理库

     vuex是官方提高的一个插件,状态管理库,一般用于大项目,数据多,维护费劲

    五大属性:state、mutations、actions、getters、modules

    state:仓库存储数据的地方

    mutations:修改仓库数据state的唯一手段

    actions:编写自己的业务逻辑,也可以处理异步

    getters:可以理解为计算属性,用于简化仓库数据

    modules:vuex可以多模块开发

    组件如何获取到仓库里面的数据:使用vuex中的mapState,在计算属性computed中使用  ...mapState(["obj"])

    如何修改state:先派发actions,this.$store.dispatch('add'),然后在actions属性中进行commit,方法名和派发是要一致add,

    然后在mutations中引用进行修改

    21、cookie、session和localStorage之间的区别

    cookie数据存放在客户的浏览器上(不安全),session数据放在服务器上

    session关闭窗口后,sessionStorage即被销毁

    localStorage保存后数据永远存在不会失效过期,除非用 js手动或定时清除,window.localStorage.clear()

    22、v-model的双向绑定原理

  • 相关阅读:
    hdu7047 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1004 Link with Balls
    hdu7115 Vertex Deletion
    CF1552B B. Running for Gold
    hdu7055 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1012 Yiwen with Sqc
    hdu7050 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1007 Link with Limit
    CF 1560E E. Polycarp and String Transformation(思维)
    CF 1542C C. Strange Function
    STL 算法 std::distance
    STL 算法 std::accumulate
    std::get<C++11多线程库~线程管理>(08):转移线程所有权(2)
  • 原文地址:https://www.cnblogs.com/chenshaoxiong/p/15922207.html
Copyright © 2020-2023  润新知