美文网首页Web 前端开发
从面试题看考察知识点(二)

从面试题看考察知识点(二)

作者: YM雨蒙 | 来源:发表于2019-02-11 15:11 被阅读27次

    题目三

    • 说一下对变量提升的理解
      • 变量定义(提升)
      • 函数声明(提升)
    • 说明 this 几种不同的使用场景
    • 创建 10 个 <a> 标签, 点击的时候弹出不同的序号
      for(var i = 0; i < 10; i++) {
        (function(i){
          var a = document.createElement('a')
          a.innerHTML =i + '<br>'
          a.addEventListener('click', function(e){
            console.log(i)
          })
          document.body.appendChild(a)
        })(i)
      }
      
    • 如何理解作用域
      • 自由变量
      • 作用域链,查找自由变量
      • 闭包的两个场景
    • 实际开发中闭包的应用
      // 封装变量, 收敛权限
      function isFirstLoad() {
        var _list = []
        return function (id) {
          if (_list.indexOf(id) >=0 ) {
            return false
          } else {
            _list.push(id)
            return true
          }
        }
      }
      
      var firstLoad = isFirstLoad()
      console.log(firstLoad(10))  // true
      console.log(firstLoad(10))  // false
      console.log(firstLoad(20))  // true
      

    知识点

    1. 执行上下文
    • 范围: 一段<script> 或者一个函数
    • 全局: 变量定义, 函数声明, 一段<script>
    • 函数: 变量定义, 函数声明, this arguments 函数
    <script>
        console.log(a)  // undefined 变量提升
        var a = 100
        
        fn('yym')  // 'yym' 20
        function fn(name) {  // 函数声明 提升
            age = 20
            console.log(name,age)
            var age
        }
    </script>
    
    1. this
    • this 要在执行时才能确认值, 定义时无法确认
      • 作为构造函数执行
      • 作为对象属性执行
      • 作为普通函数执行
      • call apply bind
    var a = {
      name: 'yym',
      fn: function () {
        console.log(this.name)
      }
    }
    // 不看下面, 上面不能确定this指啥
    
    a.fn()  // this === a
    a.fn.call({name: 'B'})  // this === {name: B}
    var fn1 = a.fn
    fn1()  // this === window
    

    代码演示

    function Foo(name) {
        // this = {}
        this.name = name
        // return this
    }
    var f = new Foo('yym')  // 构造函数的 this
    
    var obj = {
        name: 'A',
        printName: function () {
            console.log(this.name)
        }
    }
    obj.printName()  // 作为对象属性执行 this === Obj
    
    function fn () {
        console.log(this)
    }
    fn()  // 作为普通函数执行 this === window
    
    function fn1 (name) {
        console.log(this)
    }
    fn1.call({x: 100}, 'yym') // call this === {x: 100} apply 第二个参数是数组
    
    var fn2 = function (name) {
        console.log(this)
    }.bind({y: 150})  // .bind 是一个函数表达式
    fn2('yym') // this === {y:150}
    
    1. 作用域
    • JS没有块级作用域
    • 只有函数和全局作用域
    // 无块级作用域
    if (true) {
        var name = 'yym'
    }
    console.log(name)  // 可以访问到 var name = 'yym'
    
    // 函数和全局作用域
    var a = 100
    function fn() {
        var a = 200
        console.log('fn', a)  // fn 200
    }
    console.log('global', a)  // global 100
    fn()
    
    1. 作用域链
    var a = 100
    function fn () {
        var b = 200
        
        // 当前作用域没有定义的变量, 即'自由变量'
        console.log(a)  // 在当前作用域找不到变量 a, 去父级作用域去找
        console.log(b)
    }
    
    var a = 100
    function F1 () {
        var b = 200
        function F2() {
            // 当前作用域没有定义的变量, 即'自由变量'
            console.log(a)
            console.log(b)        
            console.log(c)
        }
        F2()
    }
    F1()
    
    有 3个作用域: F2作用域, F1作用域, 全局作用域
    
    a 在 F2 中没有, 去F1 作用域找, 没有, 继续去全局作用域找
    b 在 F2 中没有, 在F1 作用域找到了 
    
    1. 闭包
    function F1() {
        var a = 100
        
        // 返回一个函数, (函数作为返回值)
        return function () {
            console.log(a)  // 自由变量, 到父级作用域去找
        }
    }
    var f1 = F1()
    var a = 200
    f1()  // 100
    
    1. 闭包的使用场景
    • 函数作为返回值
    • 函数作为参数传递
    // 函数作为参数传递
    function F1() {
        var a = 100
        return function () {
            console.log(a)  // 自由变量, 到父级作用域去找
        }
    }
    var f1 = F1()
    
    function F2(fn) {
        var a = 200
        fn()
    }
    F2(f1)  // 把f1 作为参数传进去 100
    

    题目四

    • 同步和异步的区别是什么? 分别举一个同步和异步的例子
      • 同步会阻塞代码执行, 而异步不会
      • alert是同步, setTimeout是异步
    • 一个关于setTimeout的笔试题
      console.log(1)
      setTimeout(() => {
          console.log(2)
      }, 0)
      console.log(3)
      setTimeout(() => {
          console.log(4)
      }, 1000)
      console.log(5)  // 1 3 5 2 1s后打印 4
      
    • 前端使用异步的场景有哪些
      • ajax 动态<img>加载
      • setTImeout setInterval
      • 事件绑定

    知识点

    1. 什么是异步 (对比同步)
    console.log(100)
    setTimeout(() => {
        console.log(200)
    }, 1000)
    console.log(300)
    
    如果是同步: 先打印100, 停顿1s后打印200, 然后打印300, 这肯定不是我们希望的,我们不希望它停顿
    异步: 打印100, 打印300, 1s后打印200,不阻碍后面程序的加载
    
    console.log(100)
    alert(200)  // 你什么时候点掉,什么时候执行后面的,会卡在那儿
    console.log(300)
    
    1. 前端使用异步的场景
    • 在可能发生等待的情况

    • 等待过程中不能像alert一样阻塞程序进行

    • "等待的情况" 都需要异步

      • 定时任务: setTimeout setInterval
      • 网络请求: ajax请求, 动态<img>加载
      • 事件绑定
      // ajax请求, 异步
      console.log('start')  // 1.start
      $.get('url',function(data1) {  // 异步 3.data1
          console.log('data1')
      })
      console.log('end')  // 2.end
      
      // 事件绑定 异步
      console.log('start')  // 1.start
      $('#app').addEventListener('click', function () {
          alert('clicked')
      })
      console.log('end')  // 2.end
      
    1. 异步和单线程
    • JavaScript是单线程语言,因此,在一个进程上,只能运行一个线程,而不能多个线程同时运行。也就是说JavaScript不允许多个线程共享内存空间。因此,如果有多个线程想同时运行,则需采取排队的方式,即只有当前一个线程执行完毕,后一个线程才开始执行。
    • 任务队列
      • 单线程就意味着,所有任务(线程)需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务不得不一直等待。
      • 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,后一个任务才会执行;异步任务指的是不进入主线程、而进入任务队列的任务,只有当主线程上的所有同步任务执行完毕之后,主线程才会读取任务队列,开始执行异步任务。
    console.log(100)
    setTimeout(() => {
        console.log(200)
    })
    console.log(300)
    
    执行过程: 先打印100 , 遇到setTImeout异步会把里面的东西放到任务队列, 在打印 300,打印完成, 然后执行任务队列的工作
    
    函数 setTimeout 接受两个参数:待加入队列的消息和一个延迟(可选,默认为0)。这个延迟代表了消息被实际加入到队列的最
    小延迟时间。如果队列中没有其它消息,在这段延迟时间过去之后,消息会被马上处理。但是,如果有其它消息,
    setTimeout 消息必须等待其它消息处理完。因此第二个参数仅仅表示最少延迟时间,而非确切的等待时间。
    

    题目五

    • 获取2019-02-10格式的日期
      function formatDate(dt) {
        if (!dt) {
          dt = new Date()
        }
        var year = dt.getFullYear()
        var month = dt.getMonth() + 1
        var date = dt.getDate()
        if (month < 10) {
          // 强制类型转换
          month = '0' + month
        }
        if (date < 10) {
          // 强制类型转换
          date = '0' + date
        }
        // 强制类型转换
        return year + '-' + month + '-' + date
      }
      console.log(formatDate())
      
    • 获取随机数,要求长度一致的字符串格式
      var random =Math.random();
      random = random+'0000000000'
      random = random.slice(0,10)
      console.log(random)
      
    • 写一个能遍历对象和数组的通用 forEach 函数
      function forEach(obj,fn) {
        var key
        if (obj instanceof Array) {
          //判断是不是数组
          obj.forEach(function (item, index) {
            fn(index, item)
          })
        } else {
          // 不是数组就是对象
          for (key in obj) {
            fn(key, obj[key])
          }
        }
      }
      
      var arr = [1, 2, 3]
      forEach(arr, function (index, item) {
        console.log(index, item)
      })
      
      var obj = {x: 100, y: 200}
      forEach(obj, function(key, value) {
        console.log(key, value)
      })
      

    知识点

    1. 日期
    Date.now()  // 获取当前时间的毫秒数 1549788153194
    
    var dt = new Date()
    dt.getTime()  // 获取毫秒数
    dt.getFullYear()  // 得到年
    dt.getMonth()  // 获取的是 0-11, 所以要 + 1
    dt.getDate()  // 获取日 0-31
    dt.getHours()  // 获取小时 0-23
    dt.getMinutes()  // 获取分钟 0-59
    dt.getSeconds()  // 获取秒 0-59
    
    1. Math
    • 获取随机数 Math.random()
    1. 数组 API
    • forEach 遍历所有元素
    • every 判断所有元素是否都符合条件
    • some 判断是否至少一个元素符合条件
    • sort 排序
    • map 对元素重新组装,生成新数组
    • filter 过滤符合条件的元素
    var arr = [1,2,3]
    
    arr.forEach(function (item,index) {
        // 遍历数组所有元素
        console.log(index,item)
    })
    
    var result = arr.every(function (item, index) {
      // 用来判断所有的数组元素,都满足一个条件
      if( item < 4) {
        return true
      }
    })
    console.log(result)  // true
    
    var result = arr.some(function (item, index) {
      // 用来判断所有的数组元素, 只要有一个满足条件即可
      if( item < 2) {
        return true
      }
    })
    console.log(result)  // true
    
    var arr = [1,4,3,5,2]
    var arr2 = arr.sort(function (a, b) {
      // 从小到大排序
      return a - b
    })
    console.log(arr2)
    
    var arr = [1,2,3,4]
    var arr2 = arr.map(function(item,index) {
      // 将元素重新组装, 并返回
      return item * 2
    })
    console.log(arr2)
    
    var arr = [1,2,3]
    var arr2 = arr.filter(function(item,index) {
      // 通过某一条件过滤
      if (item >= 2) {
        return true
      }
    })
    console.log(arr2)  // [2, 3]
    
    1. 对象API
    • for in
    var obj = {
      x: 100,
      y: 200,
      z: 300
    }
    var key
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        console.log(key, obj[key])
      }
    }
    

    从面试题看考察知识点(一)
    从面试题看考察知识点(三)

    相关文章

      网友评论

        本文标题:从面试题看考察知识点(二)

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