美文网首页
前端面试常见题(持续更新)

前端面试常见题(持续更新)

作者: 叫兽儿 | 来源:发表于2019-11-22 12:00 被阅读0次

    一、Vue 相关问题

    1、如何理解Vue?

    vue是一套构建用户界面的渐进式框架,核心是数据模型与组件化设计,是一款MVVM框架,基于双向数据绑定,简洁轻量。兼容IE可以添加 babel-polyfill 插件。

    • babel-polyfuu 插件的使用方法:在 build 文件里的 webpack.base.conf.js 文件里配置,然后在 main.js 文件里引入:
    // webpack.base.conf.js:
    module.exports = {
      entry: {
        app: ['babel-polyfill', './src/main.js']
      },
    }
    
    // main.js:
    import 'babel-polyfill'
    
    • promise 问题,axios 不兼容 ie 的使用方法:
    import promise from 'es6-promise';
    promise.polyfill();
    
    • URLSearchParams 未定义的问题,IE9不支持URLSearchParams:
    // 下载 qs
    npm install qs
    
    // 在 main.js 中引入
    import qs from 'qs';
    
    2、什么是MVVM开发模式?

    M是Model代表数据模型,数据和业务逻辑都在Model层;V是View代表UI视图,负责数据的展示;VM是ViewModel负责监听Model中的数据变化并且对View的视图更新,处理交互操作。

    3、简述Vue的响应式原理。

    当一个vue实例被创建时,vue会遍历 data 中的属性,用 Object.defineProperty 将它们转化为 getter/setter 并在内部追踪相关依赖,在属性被访问和修改时被通知。每个组件实例都有 watcher,它会在组件渲染的过程中把属性记录为依赖,当依赖项的 setter 被调用的时候,会通知关联组件更新。

    4、简述Vue的双向数据绑定原理。

    vue通过 Object.defineProperty() 做数据劫持,重写 data 的 getter/setter ,在数据变动时触发 Watcher,改变虚拟dom中的数据更新dom树,完成双向数据绑定。

    5、简述Vue组件之间的数据传递。
    • 父组件向子组件传递数据:
      子组件用 props 接收父组件传来的数据,在父组件中注册子组件并赋值给声明的属性。

    • 子组件向父组件传递数据:
      子组件用 $emit 触发一个自定义函数并传递参数,在父组件中注册子组件并绑定方法接收数据。

    • 兄弟组件之间传递数据:
      在简单的场景下,可以使用一个空的vue实例 Bus作为中央事件总线;在复杂的场景下,使用vuex。

    6、Vue中如何监听某个属性值的变化?

    比如现在需要监听data中,obj.a 的变化:

    • 用 watch 监听
    watch: {
      obj: {
        handler (newValue, oldValue) {
          console.log('obj changed')
        },
        deep: true
      }
    }
    

    deep 属性表示深层遍历,这么写会监听 obj 所有属性变化,并不是我们想要的,所以需要修改一下:

    watch: {
      obj.a: {
        handler (newValue, oldValue) {
          console.log('obj.a changed')
        }
      }
    }
    
    • 用 computed 实现
    computed: {
      a () {
        return this.obj.a
      }
    }
    
    7、Vue中如何给 data 中的对象添加一个新的属性?
    this.$set(this.obj, 'b', 'obj.b')
    
    8、delete 和 Vue.delete 删除数组有什么区别?
    • delete被删除的元素只是变成了 empty 或 undefined 其他元素的键值都不变。
    let a = [1, 2, 3, 4]
    delete a[1]
    console.log(a)
    
    • Vue.delete直接删除了数组,改变了数组原来的键值。
    let b = [1, 2, 3, 4]
    this.$delete(b, 1)
    console.log(b)
    
    9、简述Vue的生命周期。
    • beforeCreate:完成实例初始化,挂载没开始,DOM没有初始化,loading 事件可以放在这里。

    • created:实例创建完成,完成数据初始化,未挂载DOM不能访问 el,若要访问DOM一定要放在 Vue.nextTick() 的回调函数中,$ref 为空数组,可以对 data 数据进行操作但请求不宜过多避免白屏时间太长,loading 结束放在这里。

    • beforeMount:数据初始化完成,找到对应的 template,并编译成 render 函数。

    • mounted:完成挂载DOM和渲染,完成双向绑定,可发起后端请求,对DOM进行操作。

    • beforeUpdate:数据更新前触发,可在更新前访问现有的DOM,如手动移除事件监听器。

    • updated:数据更新完成,不要随意在这里操作数据,会陷入死循环。

    • activated:keep-alive 组件激活时调用(用来缓存组件状态),这个时候 created 钩子就不会被重复调用了,如果子组件需要在每次加载的时候进行某些操作,可以使用 activated 钩子触发。

    • deactivated:keep-alive 组件停用时调用。

    • beforeDestroy:实例销毁之前调用,但实例仍然可用,可以在这里销毁定时器、解绑全局时间、销毁插件对象。

    • destroyed:实例销毁后调用,Vue 实例指示的所有东西都会解除绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

    10、<keep-alive></keep-alive>的作用是什么?

    <keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。
    比如有一个列表和一个详情页,那么用户会经常打开详情=>返回列表=>打开详情…这样列表和详情都是一个频率很高的页面,那么就可以对列表组件使用<keep-alive></keep-alive>进行缓存,用户每次返回列表的时候,都能从缓存中快速渲染,而不是重新渲染,可以减轻服务器压力,提高性能。

    11、Vue有哪些修饰符?

    事件修饰符:stop(阻止冒泡)、prevent(提交事件不再重载页面)、once、left、right
    键盘修饰符:up、down、enter、space
    表单修饰符:number(输入字符串转为有效的数字)、trim(输入首尾空格过滤)、lazy(取代input监听change时间)

    12、Vue中 $mount 与 el 区别?

    两者在使用中没有什么区别,都是将实例化后的vue挂载到指定的DOM元素中,如果指定了 el 则渲染在 el 对应的DOM中,没有指定 el 就用 $mount 手动挂载。

    13、Vue中 key 值和 is 的作用?

    使用 key,vue会基于 key 的变化重新排列元素,并且移出 key 不存在的元素,可以做优化处理;is 可以扩展原生 html 元素,也可以绑定动态组件。

    14、组件中 data 为什么是函数?

    组件是用来复用的,Js 中对象是引用关系,作用域没有隔离,而vue的实例是不会被复用的,因此不存在引用对象的问题。

    15、什么是单向数据流?

    单向数据流出现在组件通信,数据从父级流向子级,数据本身还是父级的,如果操作子级要改变父级的数据,只能通过子级告诉父级要操作哪个数据,然后父级修改数据,再传给子级。

    16、Vue中 $router$route 的区别?
    • router 是 VueRouter 的一个实例,相当于一个全局的路由器对象,包含了所有的路由、路由的关键属性及方法,经常用的跳转链接 $router.push({path:'/login',query:{name:'userName'}})

    • route 是一个跳转的路由对象(局部变量),每一个路由都有一个自己的 route,可以获取本次路由跳转的 name、path、params、query 等参数,用法 let query=this.$route.query

    17、vue-router 中 query 和 params 的区别?

    两者都是在路由中传参,query 用 path 引入,参数在地址栏中显示;params 用 name 传递,参数不会在地址栏中显示。

    18、vue-router有哪几种导航钩子?
    • 第一种:全局导航钩子(全局守卫):router.beforeEach(to,from,next),跳转前进行判断拦截;
    • 第 二种:全局解析守卫:router.beforeResolve,在导航被确认前,所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用;
    • 第三种:单独路由独享的守卫:beforeEnter,在路由配置时定义,与全局守卫的方法是一样的。
    • 第四种:组件内的守卫。直接在路由组件内定义守卫,
    beforeRouteEnter (to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
    },
    beforeRouteUpdate (to, from, next) {
       // 在当前路由改变,但是该组件被复用时调用
       // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
       // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
       // 可以访问组件实例 `this`
    },
    beforeRouteLeave (to, from, next) {
       // 导航离开该组件的对应路由时调用
       // 可以访问组件实例 `this`
    }
    
    19、vue.cli 中怎样使用自定义的组件
    • 在 components 目录新建组件页面
    • 在需要用的页面中导入
    • 注入到vue的子组件的 components 属性上面
    • 在视图中使用
    20、简书Vue中的 slot 插槽。

    插槽是Vue实现内容分发的API,将插槽元素作为分发内容的出口(子组件中给父组件提供一个占位符slot,父组件可以在组件标签中放任何内容)。

    • 匿名插槽:没有插槽时,在组件标签写入内容是不起作用的,当在组件中声明了slot元素后,在组件标签中写入内容起了作用。
    没有使用slot时 使用了slot
    • 具名插槽:就是在父组件中添加一个 slot = '自定义名字' 的属性,在子组件中的 slot 元素里面添加 name = '自定义名字' 即可。

    • 作用域插槽:就是组件上的属性,可以在组件元素内使用。

    例一 例二 例三
    21、如何理解Vue中的 Render 渲染函数?

    Vue一般使用 template 来创建 html,有的时候需要使用javascript 来创建 html,这时候我们需要使用 render 函数,render 函数 return 一个 createElement 组件中的子元素存储在组件实列中,createElement 返回的是包含的信息会告诉Vue页面上需要渲染什么样的节点。我们称这样的节点为虚拟DOM

    22、如何解决在加载页面时出现的闪烁问题?

    使用 v-cloak。
    出现闪烁的原因可能有二:

    • 加载时遇到 {{value.name}} 闪烁
    • 加载时遇到一个空盒子里边什么也没有 <p v-html="value.name"></p>

    解决方法:

    <div class="#app" v-cloak>
        <p>{{value.name}}</p>
    </div>
    
    // css 中要添加
    [v-cloak] {
        display: none;
    }
    

    如果还是闪烁,那可能是 v-cloak 的 display 属性被层级更高的给覆盖掉了;或者 v-cloak 的样式放在 @import 引入的css文件中不起作用,可以放在 link 引入的 css 文件里或者内联样式中。

    23、vuex是什么?

    是一个专为vue应用程序开发的状态管理模式。

    24、vuex有哪几种状态和属性?
    • state:存储数据,在根实例中注册了 store 后,用 this.$store.state 来访问;
    • getter:可以认为是 store 的计算属性,它的返回值会根据它的依赖被缓存起来,而且只有当它的依赖值发生了改变才会被重新计算;
    • mutation:更改 Vuex 的 store 中的状态唯一方法是提交 mutation;
    • action:包含任意异步操作,通过提交 mutation 间接更变状态;
    • module:将 store 分割成模块,每个模块都具有state、mutation、action、getter、甚至是嵌套子模块。

    vuex的流程:
    页面通过 mapAction 异步提交事件到 action;action 通过 commit 把对应参数同步提交到 mutation;mutation 会修改 state 中对于的值。;最后通过 getter 把对应值抛出去,在页面的计算属性中,通过 mapGetter 动态获取 stat e中的值。

    二、javaScript 和 Jquery 相关问题

    1、javascript 的数据类型有哪些?
    • 基本数据类型:number、boolean、string、array、null、undefined
    • 复合型数据类型:object、function、array
    2、什么是window对象?什么是document对象?
    • window 对象是指浏览器打开的窗口;
    • document 对象是 HTML 文档对象的一个只读引用,window 对象的一个属性。
    3、call 和 apply 的区别?

    call 与 apply 的相同点:

    • 方法功能是一样的,都是调用一个对象的一个方法,用另一个对象替换当前对象;
    • 第一个参数的作用是一样的;

    call 与 apply 的不同点:两者传入的列表形式不一样

    • call 可以传入多个参数;
    • apply 只能传入两个参数,所以其第二个参数往往是作为数组形式传入。
    4、document.load 和 document.ready 的区别?

    document.load 是当页面全部内容都加载完再执行;
    document.ready 是当页面的DOM数渲染完就执行;

    5、JS如何阻止事件冒泡和阻止默认事件?
    • 阻止事件冒泡:e.stopPropagation()
    • 阻止默认事件:e.preventDefault()
    6、如何将 arguments 转化为数组?
    // 方法一:
    function toArr1 () {
      var arr = [];
      for (var i = 0; i < arguments.length; i ++){
        arr.push(arguments[i]);
      }
    return arr;
    }
    console.log(toArr1('你好', 100)); //  ["你好", 100]
    
    // 方法二:
    function toArr2 () {
      return [].slice.call(arguments);
    }
    console.log(toArr2('你好', 200));  //  ["你好", 200]
    
    // 方法三:
    function toArr3 () {
      return Array.prototype.slice.apply(arguments);
    }
    console.log(toArr3('你好', 300));  //  ["你好", 300]
    
    // 方法四:es6
    function toArr4 () {
      return Array.from(arguments);
    }
    console.log(toArr4('你好', 400));  //  ["你好", 400]
    
    // 方法五:es6扩展运算符
    function toArr5 () {
      return [...arguments];
    }
    console.log(toArr5('你好', 500));  //  ["你好", 500]
    
    7、列举js跨域的方法,并对其原理加以解释?

    同源策略:就是浏览器为了保证用户的信息安全,防止恶意网站窃取数据,禁止不同域之间的JS进行交互。
    同源策略限制了以下行为:
    ① Cookie、LocalStorage 和 IndexDB 无法读取;
    ② DOM 无法获得;
    ③ AJAX 请求不能发送。

    • jsonp 跨域:插入 script 标签,引入一个js文件,当js文件加载成功后,会执行callback对应的方法,并把我们需要的 jsonp 数据作为参数传入(需要后端配合)。
    // 方法一:在 aja x函数中设置 dataType 为 'jsonp'
    $.ajax({
      dataType: 'jsonp',
      url: 'http://www.a.com/user?id=123',
      success: function (data) {
        // 处理data数据
      }
    });
    
    // 方法二:用 getJSON 来实现,只要在地址中加上 callback=? 参数即可
    $.getJSON('http://www.a.com/user?id=123&callback=?', function (data) {
      // 处理data数据
    });
    
    • 跨域资源共享 CORS:基本思想就是使用自定义的HTTP头让浏览器与服务器进行沟通,从而决定请求或响应是成功还是失败;服务器端对于CORS的支持,主要是通过设置 Access-Control-Allow-Origin 来进行的,如果浏览器检测到相应的设置,就可以允许 Ajax 进行跨域的访问。
    // 指定允许其他域名访问
    Access-Control-Allow-Origin:*
    // 响应类型
    Access-Control-Allow-Methods:GET,POST
    // 响应头设置
    Access-Control-Allow-Headers:x-requested-with,content-type
    
    • window.name:window 对象有个 name 属性,在一个窗口的生命周期内,窗口载入的所有页面无论是否同源都共享一个 window.name 并且都有读写的权限,name 的值只能是字符串的形式。

    • window.postMessage:H5为了解决跨域问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging),这个API为 window 对象新增了一个 window.postMessage 方法,允许跨窗口通信,不论这两个窗口是否同源;有两个参数,第一个参数是要发送的数据,第二个参数是接收消息的域,用 onMessage 接收。

    • document.domain:两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置 document.domain 共享 Cookie 或者处理 iframe。

    ​document.domain = 'example.com';
    // 现在,A网页通过脚本设置一个 Cookie
    document.cookie = "test1=hello";
    // B网页就可以读到这个 Cookie
    var allCookie = document.cookie;
    
    • WebSocket:是一种浏览器 API,在js创建了 websocket 之后,会有一个HTTP请求发送到浏览器以发起连接,在取得服务器响应后,建立的连接会使用HTTP协议交换为websocket协议,只有在支持 websocket 协议的服务器上才能正常工作。
    var socket = new WebSockt('ws://www.baidu.com');//http->ws; https->wss
    socket.send('hello WebSockt');
    socket.onmessage = function(event){
        var data = event.data;
    }
    
    8、排序
    // 方法一:
    function fnSort1 (arr) {
      if (arr.length <= 1) {
        return arr;
      }
      var pivotIndex = Math.floor(arr.length / 2);
      var pivot = arr.splice(pivotIndex, 1)[0];
      var left = [], right = [];
      for (var i = 0; i < arr.length; i++) {
         if (arr[i] <= pivot) {
            left.push(arr[i]); 
         } else {
            right.push(arr[i]);
         }
      }
      return sort(left).concat([pivot], sort(right));
    }
    
    // 方法二:冒泡排序
    function fnSort2 (arr) {
      for (var i = 0; i < arr.length - 1; i++) {
        for (var j = 0; j < arr.length - 1 - i; j++) {
          if (arr[j] > arr[j + 1]) {
            var temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
          }
        }
      }
      return arr;
    }
    
    9、去重
    // 方法一:
    function deRepet1 (arr) {
      arr.sort();
      for (var i = 0; i < arr.length-1; i > 0; i--) {
        if (arr[i] == arr[i - 1]) {
          arr.splice(i, 1);
        }
      }
      return arr;
    }
    
    // 方法二:es6
    function deReprt2 (arr) {
        return Array.from(new Set(arr));
    }
    
    // 方法三:
    function deRepet3 (arr) {
      var newArr = [];
      for (var i = 0; i < arr.length; i++) {
        if (newArr.indexOf(arr[i]) === -1) {
          newArr.push(arr[i]);
        }
      }
      return newArr;
    }
    
    // 方法四:双重遍历
    function deRepet4 (arr) {
      for (var i = 0; i < arr.length; i++) {
        for (var j = i + 1; j < arr.length; j++) {
          if (arr[i] === arr[j]) {
            arr.splice(j, 1);
            j--;
          }
        }
      }
      return arr;
    }
    
    // 方法五:for...of
    function deRepet5 (arr) {
      var result = [],obj = {};
      for (var i of arr) {
        if (!obj[i]) {
          result.push(arr[i]);
          obj[i] = 1;
        }
      }
      return return;
    }
    
    10、Session 和 Cookie 的区别?
    • cookie 数据存放在客户的浏览器上,session 数据放在服务器上。
    • cookie 不是很安全,别人可以分析存放在本地的 cookie 并进行 cookie 欺骗,考虑到安全应当使用 session。
    • session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用 cookie。
    • 单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie。
    • 可以考虑将登陆信息等重要信息存放为 session,其他信息如果需要保留,可以放在 cookie 中。

    相关文章

      网友评论

          本文标题:前端面试常见题(持续更新)

          本文链接:https://www.haomeiwen.com/subject/brcsictx.html