zoukankan      html  css  js  c++  java
  • 前端面试题总结

    原生js

    描述js的事件循环机制

    任务进入执行栈之后会判断一下是否是同步任务,若是同步任务就会进入主线程执行;异步任务就会到事件表里面注册回调函数到事件队列。

    1. 同步和异步任务分别进入不同的执行”场所”,同步的进入主线程,异步的进入Event Table并注册函数
    2. 当指定的事情完成时,Event Table会将这个函数移入Event Queue
    3. 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
    4. 上述过程会不断重复,也就是常说的Event Loop(事件循环)
    • 宏任务:整体代码script、setTimeout、setInterval、setImmediate, I/O, UI rendering。
    • 微任务:原生Promise中then方法、process.nextTick、MutationObserver, Object.observe

    事件循环机制

    什么是闭包,为什么有闭包概念,存在什么问题,适用什么应用场景

    闭包就是能够读取其他函数内部变量的函数

    1. 函数嵌套函数
    2. 函数内部可以引用函数外部的参数和变量
    3. 参数和变量不会被垃圾回收机制回收

    浏览器渲染

    手动实现浅拷贝、深拷贝

    // 基础版
    function clone(target) {
      let cloneTarget = {}
      for (const key in target) {
        cloneTarget[key] = target[key]
      }
      return cloneTarget
    }
    // 只考虑{}
    function deepClone(target) {
      if (typeof target === 'object') {
        let cloneTarget = {}
        for (const key in target) {
          cloneTarget[key] = deepClone(target[key])
        }
        return cloneTarget
      } else {
        return target
      }
    }
    

    手动实现防抖节流函数

    
    // 防抖
    // keyup事件、resize scroll
    function debounce(fn, delay, scope) {
        let timer = null;
        // 返回函数对debounce作用域形成闭包
        return function () {
            // setTimeout()中用到函数环境总是window,故需要当前环境的副本;
            let context = scope || this, args = arguments;
            // 如果事件被触发,清除timer并重新开始计时
            clearTimeout(timer);
            timer = setTimeout(function () {
                fn.apply(context, args);
            }, delay);
        }
    }
    // 节流
    function throttle(fn, threshold, scope) {
        let timer;
        let prev = Date.now();
        return function () {
            let context = scope || this, args = arguments;
            let now = Date.now();
            if (now - prev > threshold) {
                prev = now;
                fn.apply(context, args);
            }
        }
    }
    function throttle2(fn, threshold, scope) {
        let timer;
        return function () {
            let context = scope || this, args = arguments;
            if (!timer) {
                timer = setTimeout(function () {
                    fn.apply(context, args);
                    timer = null;
                }, threshold)
            }
        }
    }
    
    

    new 操作符过程发生了什么

    1. 创建一个空对象
    2. 设置原型链。把构造函数的prototype属性 作为空对象的原型(同时也有了prototype的方法,例如this.age 就是用到了prototype的this这个方法)
    3. 改变this指向。this赋值给这个空对象,执行构造函数函数,完成赋值
    4. 如果函数没有返回值 就返回这个this对象

    为什么会有跨域、怎么解决

    图片压缩原理

    函数参数为外部的一个对象,函数内部删除对象的某个属性,元数据会不会改变

    继承(手写class继承)

    class Person {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
      sayHello(name) {
        console.log(`hello ${name}`)
      }
    }
    class men extends Person {
      constuctor(name, age) {
        super(name, age)
      }
    }
    const xiaohong = new Person('小红', 18)
    xiaohong.sayHello() // hello 小红
    const xiaogang = new men('小刚', 20)
    xiaogang.sayHello()
    

    Promise简述

    vue

    Vue双向绑定、router原理

    nextTick原理,除了Mutation Observer还有什么实现方式

    keepalive如何实现刷新

    computed实现原理

    created和mounted的区别

    react

    react的setState是同步异步?为什么

    react里性能优化在哪个生命周期函数?

    shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能。

    什么是高阶组件(hoc)

    高阶组件[higher order component]是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。最常见的可能是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为。如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC。

    react生命周期,各生命周期作用

    componentWillMount() – 在渲染之前执行,在客户端和服务器端都会执行。
    componentDidMount() – 仅在第一次渲染后在客户端执行。
    componentWillReceiveProps() – 当从父类接收到 props 并且在调用另一个渲染器之前调用。
    shouldComponentUpdate() – 根据特定条件返回 true 或 false。如果你希望更新组件,请返回true 否则返回 false。默认情况下,它返回 false。
    componentWillUpdate() – 在 DOM 中进行渲染之前调用。
    componentDidUpdate() – 在渲染发生后立即调用。
    componentWillUnmount() – 从 DOM 卸载组件后调用。用于清理内存空间。
    16.8+
    1. 挂载阶段: constructor(props): 实例化。
    static getDerivedStateFromProps 从 props 中获取 state。
    render 渲染。
    componentDidMount: 完成挂载。
    
    2. 更新阶段: static getDerivedStateFromProps 从 props 中获取 state。
    shouldComponentUpdate 判断是否需要重绘。
    render 渲染。
    getSnapshotBeforeUpdate 获取快照。
    componentDidUpdate 渲染完成后回调。
    
    3. 卸载阶段: componentWillUnmount 即将卸载。
    
    4. 错误处理: static getDerivedStateFromError 从错误中获取 state。
    componentDidCatch 捕获错误并进行处理。
    

    简述redux

    // 三个原则
    // 单一事实来源:整个应用的状态存储在单个 store 中的对象/状态树里。单一状态树可以更容易地跟踪随时间的变化,并调试或检查应用程序。
    // 状态是只读的:改变状态的唯一方法是去触发一个动作。动作是描述变化的普通 JS 对象。就像 state 是数据的最小表示一样,该操作是对数据更改的最小表示。
    // 使用纯函数进行更改:为了指定状态树如何通过操作进行转换,你需要纯函数。纯函数是那些返回值仅取决于其参数值的函数。
    
    // redux的组件
    // Action – 这是一个用来描述发生了什么事情的对象。
    // Reducer – 这是一个确定状态将如何变化的地方。
    // Store – 整个程序的状态/对象树保存在Store中。
    // View – 只显示 Store 提供的数据。
    
    // 定义action
    // React 中的 Action 必须具有 type 属性,该属性指示正在执行的 ACTION 的类型。必须将它们定义为字符串常量,并且还可以向其添加更多的属性。在 Redux 中,action 被名为 Action Creators 的函数所创建。以下是 Action 和Action Creator 的示例:
    function addTodo(text) {
      return {
        type: ADD_TODO,    
        text
      }
    }
    // 简述
    // redux 是一个应用数据流框架,主要是解决了组件间状态共享的问题,原理是集中式管理,主要有三个核心方法,action,store,reducer,
    // 工作流程是 view 调用 store 的 dispatch 接收 action 传入 store,reducer 进行 state 操作,view 通过 store 提供的 getState 获取最新的数据,
    // flux 也是用来进行数据操作的,有四个组成部分 action,dispatch,view,store,工作流程是 view 发出一个 action,派发器接收 action,让 store 进行数据更新,更新完成以后 store 发出 change,view 接受 change 更新视图。Redux 和 Flux 很像。主要区别在于 Flux 有多个可以改变应用状态的 store,在 Flux 中 dispatcher 被用来传递数据到注册的回调事件,但是在 redux 中只能定义一个可更新状态的 store,redux 把 store 和 Dispatcher 合并,结构更加简单清晰
    // 新增 state,对状态的管理更加明确,通过 redux,流程更加规范了,减少手动编码量,提高了编码效率,同时缺点时当数据更新时有时候组件不需要,但是也要重新绘制,有些影响效率。一般情况下,我们在构建多交互,多数据流的复杂项目应用时才会使用它们
    

    react类组件和函数组件区别与使用场景

    webpack

    生产环境,webpack如何加快编译速度

    webpack的几大概念?都是做什么的

    • entry
    • output
    • loader
    • plugin

    loader和plugins的区别和基本原理

    网络

    tcp

    第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
    第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
    第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

    握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终确定断开)

    http、https、http2

    什么是进程、什么是线程

    设计原则与设计模式

    1. 工厂模式

    故名思意,我们从字面上的意思就可以看到,可以想象一座工厂源源不断产出一样的产品,流水线作业。没错,工厂模式就是这样。

    1. 单例模式

    单例模式就是保证一个类仅有一个实例,并提供一个访问它的全局访问点。其实这有一点像我们vuex当中的实现,也是一个全局的状态管理,并且提供一个接口访问。

    1. 代理模式

    我们在事件代理的时候其实就是使用了代理模式,通过把监听事件全部交由父节点进行监听,这样你添加节点或者删除节点的时候就不用去改变监听的代码。

    1. 发布订阅模式

    这种模式在生活中随处可见,比如你订阅了一个网课,开始前10分钟就会提醒你去听课。这里其实就是发布-订阅的模式,你订阅了它的开课信息,但是你不会接收到另一门的开课信息,因为你没有订阅。

    1. 适配器模式
    2. 策略模式
    3. 迭代器模式

    JS垃圾回收与V8垃圾回收机制

    算法

    排序

    • 快速排序
    • 插入排序
    • 冒泡排序
    • 选择排序
    • 归并排序

    快速排序

    快速排序的基本思想就是分治法的思想,寻找中间点,并对其左右的序列递归进行排序,直到左右都排序完成。

    function quickSort (arr) {
        if (arr.length == 0) {
            return arr
        }
        var pirotIndex = Math.floor(arr.length/2)
        var pirot = arr.splice(pirotIndex,1)[0]
        var left = [], right = []
        for (var i = 0; i < arr.length; i++) {
            if (arr[i] > pirot) {
                right.push(arr[i])
            } else {
                left.push(arr[i])
            }
        }
        return quickSort(left).concat(pirot, quickSort(right))
    }
    console.log(quickSort([2,4,6,1,7,8,4,9,99,6]))
    

    插入排序

    将数组分为无序区和有序区两个区,然后不断将无序区的第一个元素按大小顺序插入到有序区中去,最终将所有无序区元素都移动到有序区完成排序

    冒泡排序

    比较相邻的元素。如果第一个比第二个大,就交换他们两个。对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

    function bubbleSort(arr){
        if(arr.length==0){
            return arr
        }
        for(var i=0;i<arr.length;i++){
            for(j=0;j<arr.length-1;j++){
                if(arr[j]>arr[j+1]){
                    // 交换位置
                    [arr[j],arr[j+1]]=[arr[j+1],arr[j]] //ES6解构
                }
            }
        }
        return arr
    }
    console.log(bubbleSort([2,4,6,1,7,8,4,9,99,6]))
    

    二叉树

    diff算法

  • 相关阅读:
    BZOJ3697: 采药人的路径
    解题:WC 2007 石头剪刀布
    解题:CQOI 2017 老C的方块
    解题:洛谷4314 CPU监控
    解题:CQOI 2017 老C的任务
    解题:CF1009 Dominant Indices
    解题:CF570D Tree Requests
    解题:APIO 2012 派遣
    解题:ZJOI 2015 幻想乡战略游戏
    解题:洛谷4178 Tree
  • 原文地址:https://www.cnblogs.com/laine001/p/14120873.html
Copyright © 2011-2022 走看看