• 技术文章 >web前端 >前端问答

    总结一些前端常见面试题(附答案),带你巩固知识点!

    青灯夜游青灯夜游2022-07-29 09:49:53转载184

    发布文章主要也是巩固自己的知识更加熟练,全凭自己的理解和网上查资料总结出来的,如有不对的地方还望多多指点。下面是我总结的一下常见面试题,为了督促自己还可以会继续更新

    js部分

    1、谈一谈你对原型链的理解

    在js语言中,每个实例对象都有一个__proto__属性,改属性指向他的原型对象,且这个实例对象的构造函数都有一个原型属性prototype,与实例对象的__proto__属性指向同一个对象,当这个对象在查找一个属性的值时,自身没有就会根据__proto__向他的原型上寻找,如果不存在,则会到生成这个实例对象的构造函数的原型对象上寻找,如果还是不存在,就继续道Object的原型对象上找,在往上找就为null了,这个链式寻找的过程,就被称为原型链

    2、原型、构造函数、实例对象三者的关系

    首先从构造函数说起,构造函数通过prototype指向他的原型对象,原型对象通过他的constructor属性指回这个构造函数,表明原型对象是由哪个构造函数生成的。原型对象通过new关键字生成的实例对象,这个实例对象可以通过__proto__属性指向生成这个实例对象的构造函数的原型对象,实现一个三角关系。

    1.png

    3、实现继承的方式

    继承的方式有很多种,网上的答案都有很多,我自己总结且大致说的明白的有这五种

    1)原型链继承

    借助原型可以基于已有的对象创建对象,同时还不必因此创建自定义类型。 在 object()函数内部,先创建一个临时的构造函数,然后将传入的对象作为这个构造 函数的原型,最后返回了这个临时类型的一个新实例。关键代码:Star.proyotype = new Person(), Star.proyotype.constructor = Star缺点:只能继承父类的方法

    2)借用构造函数继承

    在子类构造函数的内部调用超类型构造函数。可以通过使用 apply()call()方 法在新创建的对象上执行构造函数。关键代码:Person.call(this,age,name)缺点:无法复用,只能继承父类的属性

    3)组合继承

    也叫伪经典继承。指的是将原型链和借用构造函数的技术组合到一 起,从而发挥二者之长。使用原型链实现对原型属性属性和方法的继承,通过借用构造函数来实现实例 属性的继承。 既通过在原型上定义方法实现了函数复用,又能保证每一个实例都有它自己的属性。但是会有一个小bug,里面的age,name,有两份,有一份的值为undefined,因为里面的apply()call()方法会自动多调用一次。

    4)寄生组合继承

    通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。 本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。是公认继承比较全面的一种方法,要写全的话还是非常多的,我只会一个简单的?,关键代码:Star.prototype = Object.create(Person.prototype)

    5)ES6的Class类继承方式

    可利用class关键字配合extends关键字来实现继承。ES6中引入了class关键字来声明类,而class(类)可通过extends来继承父类中属性和方法,super指向父类的原型对象,可以调用父类的属性和方法,且子类constructor方法中必须有super关键字,且必须出现在this之前。

    4、js数据类型

    数据类型从大的方向来说分为两种

    5、检测数据类型

    6、如何检测一个数据是数组

    var arr = [2, 3, 4]
    console.log(arr instanceof Array)
    console.log(Array.isArray(arr))
    console.log(Object.prototype.toString.call(arr))

    7、深拷贝和浅拷贝

    let obj = {
            name: "zs",
            age: 20,
            father: [2, 3, 4],
          };
    
          function deepClone(target) {
            //这一行如果不用三元判断 如果是数组会有bug会被拷贝成伪数组对象
            let tempObj = Array.isArray(target) ? [] : {};
            for (let key in target) {
              if (typeof target[key] === "object") {
                tempObj[key] = deepClone(target[key]);
              } else {
                tempObj[key] = target[key];
              }
            }
            return tempObj;
          }
    
          let obj1 = deepClone(obj);
          console.log(obj1);

    8、slice和splice的区别

    1.splice改变原数组,slice不改变原数组。
    2.slice会返回一个新的数组,可以用于截取数组
    3.splice除了可以删除之外,还可以替换,添加数组
    4.splice可传入3个参数,slice接受2个参数

    9、substr和substring的区别

    10、let const var区别

    let和const都是用来声明变量的,在ES5中我们可以使用var来进行变量声明 -使用let和const作用
    - 防止for循环中变量提升的经典场景
    - 不污染全局变量

    var关键字声明变量

    1.var关键字声明变量存在,变量提升的问题;
    2.var声明的变量不存在块级作用域,如果是全局变量在任何地方都可以调用;
    3.var声明变量如果名称重复了,后面声明的会将前面声明的覆盖掉;

    let关键子声明变量

    1.不存在变量提升,let声明变量不存在变量提升的问题:如果在let声明变量前调用该变量就会报错(提示初始化前无法访问该变量);
    2.块级作用域,let声明变量存在块级作用域(全局、函数、eval严格模式),只在当前的代码块中生效,如果在当前代码块以外调用就会报错(当前的变量没有定义);
    3.不影响作用域链的操作
    4.不允许变量重复声明,let声明的变量是不允许重复声明的,如果同一个名称被重复声明了就会报错(当前的标识已经被声明了);

    const声明变量

    1.const声明的变量也具有:不存在变量提升块级作用域不允许重复声明的特点;
    2.const声明的变量都是常量(不允许改变的量),一旦声明就不允许被修改,如果修改就会报错--常数变量赋值
    3.一般第三方的框架中会大量使用const声明变量,这样可以避免用户修改框架中的变量;
    4.const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。

    11、new的过程

    12、防抖节流

    防抖

    function debounce(func, delay) {
            let timer = null // 计时器
            return function (...args) {
              clearTimeout(timer) // 清除上一次计时器
              timer = setTimeout(() => {
                // 重新定时
                func.apply(this, args)
              }, delay)
            }
          }

    节流

    function throtte(func, time) {
            let timer = null // 计时器
            return function (...args) {
              if (timer) return // 无视,直接返回
              timer = setTimeout(() => {
                func.apply(this, args)
              }, time)
            }
          }

    13、promise的3种状态

    这点简单介绍概念,用法后面在详细介绍

    1) . 初始态pending

    - pending。它的意思是 "待定的,将发生的",相当于是一个初始状态。创建[Promise]对象时,且没有调用resolve或者是reject方法,相当于是初始状态。这个初始状态会随着你调用resolve,或者是reject函数而切换到另一种状态。

    2 ). 成功态resolved--也叫fulfilled

    - resolved。表示解决了,就是说这个承诺实现了。 要实现从pending到resolved的转变,需要在 创建Promise对象时,在函数体中调用了resolve方法(即第一个参数)。

    3) . 失败态rejected

    - rejected。拒绝,失败。表示这个承诺没有做到,失败了。要实现从pending到rejected的转换,只需要在创建Promise对象时,调用reject函数。

    14、冒泡排序

    // 上口诀 双层for循环 外层长度-1 内层长度-1-i
          let arr = [4, 3, 1, 7, 8, 10]
          for (let i = 0; i < arr.length - 1; i++) {
            for (let j = 0; j < arr.length - 1 - i; j++) {
              if (arr[j] > arr[j + 1]) {
                let temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
              }
            }
          }
          console.log(arr)

    Vue部分

    1、MVVM

    MVVM是三个单词的缩写,model(数据,一般来自ajax或本地存储)+view(视图template)+viewmodel(vue实例)

    2、vue生命周期

    1.分别是创建阶段的beforeCreatecreated,一般在beforeCreate写loading加载效果,使用户体验更好,一般在created中发送ajax请求获取数据

    2.然后是挂载阶段的beforeMountmounted,一般会在mounted中操作DOM元素

    3.更新阶段的是beforeUpdateupdated,当数据更新时需要做统一的业务处理时,拿到最新的dom,可以使用updated 这个钩子函数

    4.最后是销毁阶段的beforeDestroydestroyed,可以在beforeDestroy做一些清理的工作,比如说定时器 和解绑一些addEventListener监听的事件

    3、单向数据流

    单向数据流是指父组件向子组件传递数据,子组件通过props接收,当父组件中的值改变了,子组件中对应的数据也会改变,因为props是只读的,所以无法直接在子组件中对父组件传递过来的值进行修改,但是如果这个数据是一个引用数据类型,是可以直接在子组件中修改数据中的某个属性的,只要不改变这个数据的内存地址就可以

    4、双向数据绑定

    vue中普通指令都可以实现数据变了,视图会跟着变,但是有一个特殊的指令叫v-model,它一般用于表单控件,它可以实现双向数据绑定,所谓的双向数据就是数据变了,视图就会跟着改变,反过来也是

    5、v-model原理

    v-model一般配合input框使用,实现双向数据绑定的效果,它是v-bindv-on的语法糖,原理是通过v-bind将数据绑定给input框,再通过v-on:input,在input中的值改变时,通过$event可以获取到事件源对象 再通过target.value获取到input中更新后的值 将这个值再赋值给绑定的数据即可

    2.png

    6、事件传参

    在vue的组件使用自定义事件时,$event代表子组件抛出的数据,当这个自定义事件触发一个方法时,
    可以不传$event而且可以在方法中进行接收,但是如果写的话就一定要写成$event的形式,这是一个固定写法,
    或者这个方法既要传参又要使用事件对象,这个时候$event也是必须要写的
    - @click='fn' 在回调函数直接通过参数可以拿到事件对象
    - @click='fn($event)' 这个时候@event是固定写法

    7、父子组件的声明周期执行顺序

    1.初始化阶段时,先执行父组件的beforeCreatecreatedbeforeMount三个钩子函数,然后执行子组件的beforeCreatecreatedbeforeMountmounted四个钩子函数,最后执行父组件的mounted钩子函数

    2.更新阶段,先执行父组件的beforeUpdate,然后执行子组件的beforeUpdateupdated,最后执行父组件的updated

    3.销毁阶段,先执行父组件的beforeDestroy,然后执行子组件的eforeDestroydestroyed,最后执行父组件的destroyed

    8、v-if和v-show的区别

    v-ifv-show都可以控制标签,实现组件的显示与隐藏,不同点是v-show是通过display的block和none属性来控制的,当元素隐藏时,页面结构依然存在

    9、v-for和v-if为什么要避免一起使用

    10、自定义指令:directive

    应用场景

    1.bind 属性绑定的时候执行 只会有一次
    2. inserted 当前指令所在的元素插入到页面中的时候执行一次
    3. update 当前指令所在的组件中的 data 数据有更新就会执行,可以执行多次

    // 指令的钩子有三个 bind inserted update
    // bind inserted 只会执行一次
    // update 会反复执行
    Vue.directive('focus', {
      inserted(el) {
        el.focus()
      },
    })
    
    Vue.directive('red', {
      bind(el) {
        el.style.color = 'red'
      },
    })
    
    Vue.directive('check', {
      update(el) {
        const reg = /^[a-zA-Z0-9]+$/
        if (reg.test(el.value)) {
          el.style.color = 'green'
        } else {
          el.style.color = 'red'
        }
      },
    })

    浏览器的缓存机制

    这块部分理解不是很透彻,大家浅看一下就可以了?

    1. 强缓存:过期之前一直用本地离线资源 不会和服务器交互
      • http1.0 expire 具体的时间2023年1月1日
      • http1.1 cache-control 时间期限1年 (优先级高)
    2. 协商缓存 本质是看本地东西和服务器有没有变旧(服务器上有没有更新的资源) 强缓存不会和服务器交互 协商缓存会交互一次来判断东西有没有变旧
      • http1.0 last-modified/if-modified-since
      • http1.1 etag/if-none-match(优先级高)

    设计模式

    本人技术栈是主要是前端vue的,所以对这方面的知识还是有所欠缺的,尽量说的明白一点,其实我也不是很懂,大致明白,如果想要全面理解透还是需要很多技术储备的,很明显我不是的哈哈?

    1、观察者模式

    观察者模式即一个对象被多个对象所依赖,当被依赖的对象发生更新时,会自动通知所有依赖的对象

    2、发布订阅模式

    发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。

    3、两者模式区别

    (学习视频分享:web前端入门jQuery视频教程

    以上就是总结一些前端常见面试题(附答案),带你巩固知识点!的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:面试题 前端 web前端
    上一篇:dom对象是javascript对象吗 下一篇:css和html5是什么
    VIP课程(WEB全栈开发)

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• 【吐血整理】50道Python面试题大全及答案(收藏)• 【吐血整理】40+个PHP面试题附答案(实战经验)• 【吐血整理】Vue.js面试题汇总及答案解析(快来收藏)• 分享一些值得收藏的精选Web前端面试题(附答案)• 【吐血整理】2022年Java 基础高频面试题及答案(收藏)
    1/1

    PHP中文网