Web 前端面试

作者: Daeeman | 来源:发表于2020-07-15 16:04 被阅读0次

    博客园整理了一下,有好的面试题欢迎大家发在评论区哟
    1. 闭包
    2. 数组去重
    3. 原型和原型链
    4. call,apply,bind三者的区别?
    5. 请介绍常见的 HTTP 状态码(至少五个)
    6. 深浅拷贝
    7. 实现(5).add(3).minus(2)输出6
    8. null和undefined区别
    9. MVC和MVVC?
    10. Vue生命周期
    11. Vue数据双向绑定原理
    12. Vue组件传参
    13. 说说各浏览器存在的兼容问题
    14. router和route
    15. active-class属于Vue哪一个modules,有什么作用
    16. v-if和v-show
    17. computed和watch有什么区别
    18.Vue 组件中 data 为什么必须是函数
    19. vue中子组件调用父组件的方法
    20. vue中 keep-alive 组件的作用
    21. vue中如何编写可复用的组件?
    22. Vue 如何去除url中的 #
    23. Vue 中 key 的作用
    24. Vue 中怎么自定义指令
    25. Vue 中怎么自定义过滤器
    26. NextTick 是做什么的
    27. Vue 组件 data 为什么必须是函数
    28. 计算属性computed 和事件 methods 有什么区别
    29. scoped(死够扑的)
    30. vue如何获取dom?
    31. promise
    32. vue常用指令有哪些
    33.vue-loader是什么?使用和用途?
    34.css样式局部化,如何让css只在当前组件起作用?scss和stytus样式穿透

    1. 闭包

    闭包指有权访问另一个函数中变量的函数,
    MDN: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
    B站视频:https://www.bilibili.com/video/BV1YJ411R7ap?from=search&seid=18157596230752413126

    2. 数组去重

    https://www.jianshu.com/p/9c3547450a52

    3. 原型和原型链

    https://search.bilibili.com/all?keyword=%E5%8E%9F%E5%9E%8B%E9%93%BE%20%E9%BB%91%E9%A9%AC

    4. call,apply,bind三者的区别?

    都是用来改变this指向的

    call和apply都是function原型上的方法,每一个函数作为function的实例都可以调用这两个方法,而这两个方法都是用来改变this指向的

    一般情况下this指向其调用者()

    call

    fun.call(thisArg,arg1,ary2,...)
    主要作用可以实现继承
    调用函数,改变this指向

    var o={
        name:'kangkang'
    };
    function fn(a,b){
        console.log(this);  //不写call则指向window
        console.log(a+b);  //3
    }
    fn.call(o,1,2);
    
    

    继承

    function father(uname,age,sex){
        this.uname = uname;
        this.age = age;
        this.sex = sex;
    }
    function Son(uname,age,sex){
        father.call(this,uname,age,sex);
    }
    var son=new Son('张学友',18,‘男’);
    console.log(son);
    
    apply

    fun.apply(thisArg,[argsArray])

    • thisArg:在fun函数运行时指定的this值
    • argsArray:传递的值,必须包含在数组里面
    • 返回值就是函数的返回值,因为它就是调用函数
    var o={
        name:'kangkang'
    };
    function fn(arr){
        console.log(this);
        console.log(arr);
    }
    fn.apply(o);  //后面参数可省略
    fn.apply(o,['pink']);
    

    作用:调用函数,改变函数内部this指向
    参数必须是数组
    apply主要应用于借助数学对象等

    var arr = [1,66,3,17];
    var max = Math.max.apply(Math,arr);
    var min = Math.min.apply(Math,arr);
    console.log(max,min);
    
    bind

    bind()方法不会调用函数,但可以改变函数内部this指向
    fun.bind(thisArg,arg1,arg2,...)
    thisArg:在fun函数运行时指定的this值
    arg1,arg2:传递的其他参数
    返回由指定的this值和初始化参数改造的原函数拷贝

    var o = {
        name:'andy'
    };
    function fn(a,b){
        console.log(this);
        console.log(a+b);
    };
    var f = fn.bind(o,1,2);
    f();   //产生了一个新函数
    

    call的性能要比apply好一些,尤其当传递参数超过3个,后期开发可多用call

    let arr = [1,2,3];
    obj = {};
    function fn(a,b,c){
        fn.apply(obj,arr);  //a=[1,2,3]  b=c=undefined
        fn.call(obj,...arr);//基于ES6的展开运算符,可以将数组中的每一项依次传递给函数
        fn.call(obj,arr); 
    }
    

    时间测试

    console.time('A')
    ...
    ...
    console.timeEnd('a')
    

    5. 请介绍常见的 HTTP 状态码(至少五个)

    状态码是由 3 位数组成,第一个数字定义了响应的类别,且有五种可能取值:

    1xx:指示信息–表示请求已接收,继续处理。

    • 100 客户必须继续发出请求

    • 101 客户要求服务器根据请求转换HTTP协议版本

    2xx:成功–表示请求已被成功接收、理解、接受。

    • 200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。

    • 201 (已创建) 请求成功并且服务器创建了新的资源。

    • 202 (已接受) 服务器已接受请求,但尚未处理。

    3xx:重定向–要完成请求必须进行更进一步的操作。

    • 300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。

    • 301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。

    • 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

    4xx:客户端错误–请求有语法错误或请求无法实现。

    • 400 (错误请求) 服务器不理解请求的语法。

    • 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。

    • 403 (禁止) 服务器拒绝请求。

    5xx:服务器端错误–服务器未能实现合法的请求。

    • 500 (服务器内部错误) 服务器遇到错误,无法完成请求。

    • 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。

    • 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。

    • 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。

    • 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。

    • 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。

    6. 深浅拷贝

    7. 实现(5).add(3).minus(2)输出6

    ~function(){
        //==>每一个方法执行完,都要返回number这个类的实例,这样才可以继续调取number类原型中的方法(链式写法)
        function check(n){
            n = Number(n);
            return isNaN(n)?0 : n;
        }
        function add(n){
            n=check(n);
            return this+n;
        }
        function minus(n){
            n=check(n);
            return this-n;
        }
        Number.prototype.add=add;
        Number.prototype.minus=minus;
    }
    

    8. null和undefined区别

    阮一峰:http://www.ruanyifeng.com/blog/2014/03/undefined-vs-null.html

    9.MVC和MVVC?

    MVC是后端中的概念

    • M (Model) 是指数据库中的数据
    • V (View)
    • C (Controller)

    MVVC中是前端概念

    • M (Model) 是data里数据(通过ajax等获取的数据)
    • V (View) 是html结构
    • VM (ViewModel)是new vue 中 new出来的对象就是VM,是V-M的调度者,提供了数据的双向绑定

    最终实现V和M数据的同步,因此开发者只需关注业务逻辑,不需要手动操作Dom,mvvm是vue的核心

    image.png

    10. Vue生命周期

    lifecycle.png

    11、 Vue数据双向绑定原理

    12、Vue组件传参

    13、说说各浏览器存在的兼容问题

    14、router和route

    1. router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性。

      举例:history对象

      $router.push({path:'home'});本质是向history栈中添加一个路由,在我们看来是 切换路由,但本质是在添加一个history记录

      方法:
      $router.replace({path:'home'});//替换路由,没有历史记录

    2. route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query等

    这两个不同的结构可以看出两者的区别,他们的一些属性是不同的。

    • $route.path
      字符串,等于当前路由对象的路径,会被解析为绝对路径,如 "/home/news"
    • $route.params
      对象,包含路由中的动态片段和全匹配片段的键值对
    • $route.query
      对象,包含路由中查询参数的键值对。例如,对于 /home/news/detail/01?favorite=yes ,会得到$route.query.favorite == 'yes'
    • $route.router
      路由规则所属的路由器(以及其所属的组件)
    • $route.matched
      数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
    • $route.name
      当前路径的名字,如果没有使用具名路径,则名字为空。

    15. active-class属于Vue哪一个modules,有什么作用

    active-class 属于vue-router的样式方法
    当routerlink标签被点击时将会应用这个样式

    使用有两种方法
    routerLink标签内使用

    <router-link to='/' active-class="active" >首页</router-link>
    在路由js文件,配置active-class
    <script>
        const router = new VueRouter({
            routes,
            linkActiveClass: 'active'
        });
    </script>
    <script>
        const router = new VueRouter({
            routes,
            linkActiveClass: 'active'
        });
    </script>
    

    在使用时会有一个Bug
    首页的active会一直被应用
    解决办法
    为了解决上面的问题,还需加入一个属性exact,类似也有两种方式:
    在router-link中写入exact

    <router-link to='/' active-class="active" exact>首页</router-link>
    

    在路由js文件,配置active-class

    <script>
        const router = new VueRouter({
            routes,
            linkExactActiveClass: 'active'
        });
    </script>
    

    还可以不用exact这种方法去解决,例如

    首页
    路由中加入重定向

    {
    path: ‘/’,
    redirect: ‘/home’
    }
    

    16 . v-if和v-show

    17. computed和watch有什么区别

    computed

    computed是计算属性,也就是计算值,它更多用于计算值的场景
    computed具有缓存性,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时重新调用对应的getter来计算
    computed适用于计算比较消耗性能的计算场景
    watch

    watch更多的是[观察]的作用,类似于某些数据的监听回调,用于观察props $emit或者本组件的值,当数据变化时来执行回调进行后续操作
    无缓存性,页面重新渲染时值不变化也会执行
    小结

    当我们要进行数值计算,而且依赖于其他数据,那么把这个数据设计为computed
    如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化。

    18.Vue 组件中 data 为什么必须是函数

    vue组件中data值不能为对象,因为对象是引用类型,组件可能会被多个实例同时引用。
    如果data值为对象,将导致多个实例共享一个对象,其中一个组件改变data属性值,其它实例也会受到影响。

    19.vue中子组件调用父组件的方法

    第一种方法是直接在子组件中通过this.parent.event来调用父组件的方法 第二种方法是在子组件里用emit向父组件触发一个事件,父组件监听这个事件就行了。
    第三种都可以实现子组件调用父组件的方法,

    <template>
      <div>
        <button @click="childMethod()">点击</button>
      </div>
    </template>
    <script>
      export default {
        props: {
          fatherMethod: {
            type: Function,
            default: null
          }
        },
        methods: {
          childMethod() {
            if (this.fatherMethod) {
              this.fatherMethod();
            }
          }
        }
      };
    </script>
    
    

    20.vue中 keep-alive 组件的作用

    keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

    <keep-alive>
      <component>
        <!-- 该组件将被缓存! -->
      </component>
    </keep-alive>
    如果只想 router-view 里面某个组件被缓存
    
    export default [
      {
        path: '/',
        name: 'home',
        component: Home,
        meta: {
          keepAlive: true // 需要被缓存
        }
      }, {
        path: '/:id',
        name: 'edit',
        component: Edit,
        meta: {
          keepAlive: false // 不需要被缓存
        }
      }
    ]
    <keep-alive>
        <router-view v-if="$route.meta.keepAlive">
            <!-- 这里是会被缓存的视图组件,比如 Home! -->
        </router-view>
    </keep-alive>
    
    <router-view v-if="!$route.meta.keepAlive">
        <!-- 这里是不被缓存的视图组件,比如 Edit! -->
    </router-view>
    
    

    21.vue中如何编写可复用的组件?

    去这里看一下​blog.csdn.net

    ①创建组件页面eg Toast.vue;
    ②用Vue.extend()扩展一个组件构造器,再通过实例化组件构造器,就可创造出可复用的组件
    ③将toast组件挂载到新创建的div上;
    ④把toast组件的dom添加到body里;
    ⑤修改优化达到动态控制页面显示文字跟显示时间;

    import Vue from 'vue'; 
    import Toast from '@/components/Toast';     //引入组件
    let ToastConstructor  = Vue.extend(Toast) // 返回一个“扩展实例构造器”
    
    let myToast = (text,duration)=>{
        let toastDom = new ToastConstructor({
            el:document.createElement('div')    //将toast组件挂载到新创建的div上
        })
        document.body.appendChild( toastDom.$el )   //把toast组件的dom添加到body里
    
        toastDom.text = text;
        toastDom.duration = duration;
    
        // 在指定 duration 之后让 toast消失
        setTimeout(()=>{
            toastDom.isShow = false;  
        }, toastDom.duration);
    }
    export default myToast;
    

    22. Vue 如何去除url中的

    vue-router 默认使用 hash 模式,所以在路由加载的时候,项目中的 url 会自带 #。如果不想使用 #, 可以使用 vue-router 的另一种模式 history

    new Router({
    mode: 'history',
    routes: [ ]
    })

    需要注意的是,当我们启用 history 模式的时候,由于我们的项目是一个单页面应用,所以在路由跳转的时候,就会出现访问不到静态资源而出现 404 的情况,这时候就需要服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面

    23. Vue 中 key 的作用

    key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 keyVue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误

    具体参考 官方API

    24. Vue 中怎么自定义指令

    全局注册

    // 注册一个全局自定义指令 `v-focus`
    Vue.directive('focus', {
      // 当被绑定的元素插入到 DOM 中时……
      inserted: function (el) {
        // 聚焦元素
        el.focus()
      }
    })
    
    

    局部注册

    directives: {
      focus: {
        // 指令的定义
        inserted: function (el) {
          el.focus()
        }
      }
    }
    
    

    参考 官方文档-自定义指令

    25. Vue 中怎么自定义过滤器

    可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数以值为参数,返回转换后的值

    Vue.filter('reverse', function (value) {
      return value.split('').reverse().join('')
    })
    <!-- 'abc' => 'cba' -->
    <span v-text="message | reverse"></span>
    
    

    过滤器也同样接受全局注册和局部注册

    26. NextTick 是做什么的

    $nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM

    具体可参考官方文档 深入响应式原理

    27. Vue 组件 data 为什么必须是函数

    因为js本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有Vue实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了

    28. 计算属性computed 和事件 methods 有什么区别

    我们可以将同一函数定义为一个 method 或者一个计算属性。对于最终的结果,两种方式是相同的

    不同点:

    computed: 计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值对于 method ,只要发生重新渲染,method 调用总会执行该函数

    29. scoped(死背死特)

    <style scoped></style>
    

    让css只在当前组件中起作用

    30.vue如何获取dom?

      答:ref="domName" 用法:this.$refs.domName
    

    31、promise

    相关文章

      网友评论

        本文标题:Web 前端面试

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