一、前端面试题 - js篇

2021-11-08  本文已影响0人  YiYaYiYaHei
1. 四种定时器及区别

setTimeout:定时器,只执行一次
setInterval:间隔定时器,执行n次
setImmediate:浏览器完全结束当前运行的操作之后立即执行指定的函数
requestAnimationFrame: 专门为实现高性能的帧动画而设计的API,但是不能指定延迟时间,而是根据浏览器的刷新频率而定(帧)


2. 浏览器宏任务、微任务

浏览器的微任务MicroTask和宏任务MacroTask
宏任务:比较费时、比较慢的任务,例如setTiemout、setInterval、setImmediate、I/O、UI渲染
微任务:Promise、MutationObserver(监听节点变化)、process、nextTick

浏览器从上之下读取代码,先执行同步代码,遇到异步代码就放到事件循环(堆栈)中去,当同步代码执行完成后,从堆栈中以“先进先出”为原则,依次执行异步代码。
步骤如下:
1.执行完主逻辑中的同步任务
2.取出微任务队列(MicroTask Queue)中的任务执行,直到队列被完全清空
3.取出宏任务队列(MacroTask Queue)中的一个任务执行。
4.取出微任务队列(MicroTask Queue)中的任务执行,直到队列被完全清空
5.重复 3 和 4,直到宏任务队列(MacroTask Queue)被清空。


3. 修改this指向

前端js中this指向及改变this指向的方法
call: 立即执行该函数 - 序列化参数 fn.call(this, 参数1, 参数2, 参数3...)
apply: 立即执行该函数- 数组参数 fn.apply(this, [参数1, 参数2, 参数3...])
bind: 不执行函数,只返回一个可供执行的函数

fn.bind(Person, 4, 5); //只是更改了this指向,没有输出
fn.bind(Person, 4, 5)(); // 更改this指向并执行方法

4. 闭包

js中的闭包

图4-1 什么是闭包

闭包的三个特性:

js闭包及常见的应用场景
使用场景:


5. 浏览器垃圾回收机制
图5-1 什么是垃圾回收机制
6. 函数节流和函数防抖

JS函数节流和函数防抖

6.1. 为什么使用函数节流和函数防抖
图6-1 为什么使用函数节流和函数防抖
简单来说就是防止短时间内频繁的触发事件
6.2. 什么是函数节流和函数防抖
6.3 代码实现

其实就是闭包+定时器

window.onload = function () {
      // 函数防抖
      function debounce(fn, time) {
        let timer = null;
        return function() {
          timer && clearTimeout(timer);
          timer = setTimeout(() => {
            fn();
            console.log('函数防抖执行');
          }, time);
        }
      }
      document.getElementById('box').addEventListener('mousemove', debounce(() => {
        console.log('我滑动');
      }, 2000))
    }
window.onload = function () {
      // 函数节流 (定时器)
      function throttle(fn, time) {
        let timer = null;
        return function() {
          if (!timer) {
            timer = setTimeout(() => {
              fn();
              console.log('函数节流执行');
              timer = null;
            }, time);
          }
        }
      }

      // 函数节流 (时间戳)
      function throttle1(fn, time) {
        let timer = null;
        let prevTime = +new Date();
        return function() {
          let now = +new Date();
          if (now - prevTime > time) {
            fn();
            console.log('函数节流执行');
            prevTime = now;
          }
        }
      }

      document.getElementById('box').addEventListener('mousemove', throttle1(() => {
        console.log('我滑动');
      }, 2000))
    }

7. 数组去重的几种方式
var arr = [1,2,3,4,1,2,3,4,3,3];
// 1、 利用set+扩展运算符
var arr1 = [...new Set(arr)];

// 2、 利用set+Array.from
var arr2 = Array.from(new Set(arr));

// 3、 循环 + find
var arr3 = [];
for (let i = 0; i < arr.length; i++) {
     if (!arr3.find(it => it === arr[i])) {
         arr3.push(arr[i]);
      }
}

// 4、 对象
let obj = {};
for (let i = 0; i < arr.length; i++) {
    if (!Object.values(obj).find(it => it === arr[i])) {
          obj[i] = arr[i];
    }
}
console.log(Object.values(obj));

// 5、 filter
var arr4 = arr.filter((item, index, array) => array.indexOf(item) === index);

8. for...of、for...in、forEach区别

9. jq的on、bind区别

on可以给动态添加的元素也绑定相同事件;可以将子元素的事件委托给父元素处理(事件代理);
bind无法给动态添加的元素绑定相同事件;也无法实现事件代理


10. class 继承和静态方法

es5继承:
属性继承:使用call修改this指向父类.call(this)
方法继承:主要使用prototype,分为拷贝继承(for...in循环对象,将属性一一复制)、类式继承(使用new F(),F为空方法)
es6 class 类静态方法和继承


11. ES6、7

ES6新特性
ES6新特性

ES6、ES7、ES8、ES9、ES10、ES11、ES12新特性
ES7新特性

ES8新特性

// Object.entries返回key、value数组
let obj = {a: 1, b: 2, c: 3}
JSON.stringify(Object.entries(obj))
[["a",1],["b",2],["c",3]]
console.log('react'.padStart(10))         // "       react"
console.log('0.00'.padEnd(5, 0))          // 0.000
console.log('backbone'.padEnd(10))       // "backbone  "

// 长度比字符串本身长度小,返回字符串本身
console.log('hello word'.padEnd(2))       // "hello word"
// 长度比字符串本身长度大,填充字符串
console.log('hello word'.padEnd(20))     // "hello word          "

ES9新特性


12. export、export default、import

因为前端的导入导出主要分为commonjsES6modules两种标准,其中commonjs(module.exports、require)主要用于node环境,而ES6modules(export、export default、import)主要用于浏览器环境,但是ES6modules是兼容commonjs标准的, 详情见js中的export、import、export default等导入导出全解

图12-1
13. 同/异步、promise、function* yield、async/await

promise链式写法、promise.all

13.1 为什么引入async/await

一个列表页面需要根据用户信息来呈现数据,用户需要先登录,登录成功后再调用列表接口,就会出现多层嵌套即回调地狱;为了解决回调地狱,es6引入了promise,但是如果需要多次请求时,就会出现一推的then,也就是promise的链式写法,导致代码不直观,所以又出现了生成器 Generator,Generator 函数是一个普通函数,但是有两个特征:
① function关键字与函数名之间有一个星号 function* name(){}
② 函数体内部使用yield表达式,定义不同的内部状态;
每次调用next方法都会执行一个yield,也就是说Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行,但是Generator 虽然语法简洁了些却不好知道什么时候执行第一阶段什么时候执行第二阶段,所以async/await就出生了,它可以以异步方式实现同步操作

13.2 同/异步

同步:等待程序返回后,才执行后续操作(会发生阻塞)
异步:不需要等待程序返回,就可以执行后续操作

13.3 promise
13.4 function* yield
图13-3 function* yield
13.5 async/await

理解 JavaScript 的 async/await

图13-4
图13-5
图13-6
图13-7
图13-8
14. webSocket、http、https

http与https区别:
① http明文传输不安全,https加密传输安全,而且https可以验证网站真实性;
② http端口默认80,https端口默认443;
③ https需要申请证书,大部分安全性好的证书都需要花钱;
④ https协议握手阶段比较费时,会使页面的加载时间延长近50%,增加10%到20%的耗电,首屏白屏时间比http时间长


相关文章

二、 前端面试题 - vue篇
三、 前端面试题 - 安全篇

上一篇下一篇

猜你喜欢

热点阅读