javascript面试题--持续更新

  • 前端HTML篇

  • 前端CSS篇

  • Vue篇

  • TypeScript篇

  • React篇

  • 微信小程序篇

  • 前端面试题汇总大全(含答案超详细,HTML,JS,CSS汇总篇)-- 持续更新

  • 前端面试题汇总大全二(含答案超详细,Vue,TypeScript,React,微信小程序,Webpack 汇总篇)-- 持续更新

前端面试题js篇--持续更新

      • 1. JS 数据类型 ?存储上的差别?
      • 2.数组常用方法?
      • 3.JavaScript字符串的常用操作方法有哪些?
      • 4.JavaScript字符串的常用转换方法和模板匹配方法?
      • 5.JavaScript 中的类型转换机制
      • 6.null 和 undefined 的区别?
      • 7. “ ===”、“ ==”的区别?
      • 8. “eval是做什么的?
      • 9. 箭头函数有哪些特点?
      • 10. var、let、const 区别?
      • 11. new操作符具体干了什么呢?
      • 12.深拷贝浅拷贝的区别?如何实现一个深拷贝?
      • 13.对作用域链的理解
      • 14.JavaScript原型,原型链 ? 有什么特点?
      • 15.请解释什么是事件代理
      • 16.Javascript如何实现继承?
      • 17.谈谈This对象的理解
      • 18.事件模型
      • 19.new操作符具体干了什么呢?
      • 20.JavaScript中执行上下文和执行栈是什么?
      • 21.typeof 与 instanceof 区别?
      • 22.判断是否为数组的5种方法?
      • 23. 判断一个值是什么类型有哪些方法?
      • 24. ajax过程?
      • 25.Ajax原理,ajax优缺点?
      • 26.bind、call、apply 区别?
      • 27.如何实现一个bind?
      • 28.说说你对正则表达式的理解?应用场景?
      • 29.对事件循环的理解(详细)?
      • 30.DOM常见的操作有哪些?
      • 31.说说你对BOM的理解,常见的BOM对象你了解哪些?
      • 32.BOM和DOM区别?
      • 33.如何解决跨域问题?
      • 34.异步加载js方式?
      • 35.哪些操作会导致内存泄漏?
      • 36.XML和JSON的区别?
      • 37.说说你对递归得理解?
      • 38.说说你对函数式编程的理解?优缺点?纯函数,高阶函数,柯里化
      • 39.Javascript中如何实现函数缓存?函数缓存有哪些应用场景?
      • 40. JSON 的了解?
      • 41. document.write 和 innerHTML 的区别?
      • 42. 请解释一下 JavaScript 的同源策略?
      • 43. 介绍一下闭包和闭包常用场景?
      • 44. javascript的内存(垃圾)回收机制?
      • 45. 用js递归的方式写1到100求和?
      • 46. 事件队列(宏任务微任务)
      • 43.async/await, Generator
      • 48. JavaScript 是单线程的,浏览器是多进程的
      • 49.说说 Javascript 数字精度丢失的问题,如何解决?
      • 50.说说你对模块化方案的理解,比如 CommonJS、AMD、CMD、ES Module 分别是什么?
      • 51.用过哪些设计模式?
      • 52.javascript有哪些方法定义对象?
      • 53.说说你对promise的了解
      • 54.web开发中会话跟踪的方法有哪些?
      • 55.介绍js有哪些内置对象?
      • 56.eval是做什么的?
      • 57.parseInt函数,["1", "2", "3"].map(parseInt) 答案是多少?
      • 58.javascript 代码中的"use strict";是什么意思?说说严格模式的限制
      • 59.js延迟加载的方式有哪些?
      • 60.同步和异步的区别?
      • 61.ES6新特性
      • 62.let,const,var区别?
      • 63.let和var区别?
      • 64.如果new一个箭头函数的会怎么样?
      • 65.箭头函数与普通函数的区别?
      • 66.扩展运算符的作用
      • 67.ES6中模板语法与字符串处理
      • 68.map与forEach的区别
      • 69.Js动画与CSS动画区别及相应实现
      • 70.gulp是什么?
      • 71.事件的各个阶段, addEventListener
      • 72.数组some函数和every函数
      • 73.数组乱序
      • 74.如何渲染几万条数据并不卡住界面,requestAnimationFrame
      • 75.获取到页面中所有的checkbox怎么做
      • 76.怎样添加、移除、移动、复制、创建和查找节点
      • 77.window.onload和$(document).ready
      • 78.addEventListener()和attachEvent()的区别
      • 79.数组去重
      • 80.判断两个对象相等
      • 81.防抖节流
      • 82.检测浏览器版本版本有哪些方式?
      • 83.javascript基本规范
      • 84.npm和yarn,pnpm的优势是什么
      • 85.导致页面加载白屏时间长的原因有哪些,怎么进行优化
      • 86.DOM克隆操作
      • 87.沙箱模式
      • 88.string和tostring什么区别
      • 89.js数据存储方式
      • 90.cookie,session,token区别
      • 91.js十进制转二进制
      • 92.如何让多个异步函数顺序执行
      • 93.settimeout事件机制
      • 94.bind连续绑多次最终this指向
      • 95.mep和set
      • 96.大文件上传
      • 97.移动端Click300毫秒点击延迟 解决办法
      • 98.如何判断一个对象为空对象
      • 99.数组常用方法
      • 100.数组扁平化
      • 101.for..in 和 for ... of区别
      • 102.伪数组,伪数组转换为数组
      • 103.二维数组应用场景

1. JS 数据类型 ?存储上的差别?

数据类型主要包括两部分:

  • 基本数据+类型: Undefined、Null、Boolean、Number 和 String,Symbol(创建后独一无二且不可变的数据类型 )
  • 引用数据类型: Object (包括 Object 、Array 、Function)

存储区别:

  • 基本数据类型存储在栈中
  • 引用类型的对象存储于堆中

2.数组常用方法?

增:

  • push() 向数组的末尾添加一个或更多元素,并返回新的长度
  • unshift() 在数组开头添加任意多个值,然后返回新的数组长度
  • splice() 传入三个参数,分别是开始位置、0(要删除的元素数量)、插入的元素,返回空数组
  • concat() 首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组,不会影响原始数组

删:

  • pop() 方法用于删除数组的最后一项,同时减少数组的length 值,返回被删除的项
  • shift() 方法用于删除数组的第一项,同时减少数组的length 值,返回被删除的项
  • splice() 传入两个参数,分别是开始位置,删除元素的数量,返回包含删除元素的数组
  • slice() 传入两个参数,分别是开始位置和结束位置,不包括结束值,返回一个新数组,不影响原数组

改:

  • splice() 传入三个参数,分别是开始位置,要删除元素的数量,要插入的任意多个元素,返回删除元素的数组,对原数组产生影响

查:

  • indexOf() 返回要查找的元素在数组中的位置,如果没找到则返回 -1
  • includes() 返回要查找的元素在数组中的位置,找到返回true,否则false
  • find() 返回第一个匹配的元素

3.JavaScript字符串的常用操作方法有哪些?

增:

  • 字符串可以通过‘+’以及${}进行字符串拼接
  • concat 用于将一个或多个字符串拼接成一个新字符串

删:三个函数都接收一个或两个参数,跟数组中slice相似

  • slice()
  • substr() 接受两个参数:起始索引和要提取的字符数
  • substring() 接受两个参数:起始索引和结束索引 不包括结束位置的字符

改:

  • trim()、trimLeft()、trimRight() 删除前、后或前后所有空格符,再返回新的字符串
  • repeat() 接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果
  • padStart()、padEnd() 复制字符串,接收两个参数,第一个参数是长度,第二个参数是想要填充的字符,如果小于指定长度,则在相应一边(end/start)填充字符,直至满足长度条件
  • toLowerCase()、 toUpperCase() 大小写转化

查:

  • chatAt() 返回给定索引位置的字符,由传给方法的整数参数指定
  • indexOf() 从字符串开头去搜索传入的字符串,并返回位置(如果没找到,则返回 -1 )
  • startWith() 从字符串中搜索传入的字符串,判断开头字符串是否与期待值相同,并返回一个表示是否包含的布尔值
  • includes() 从字符串中搜索传入的字符串,判断字符串是否包含期待值,并返回一个表示是否包含的布尔值

4.JavaScript字符串的常用转换方法和模板匹配方法?

转换方法:

  • split() 把字符串按照指定的分割符,拆分成数组中的每一项

模板匹配方法:

  • match() 接收一个参数,可以是一个正则表达式字符串,也可以是一个RegExp对象,返回数组
  • search() 接收一个参数,可以是一个正则表达式字符串,也可以是一个RegExp对象,找到则返回匹配索引,否则返回 -1
  • replace() 接收两个参数,第一个参数为匹配的内容,第二个参数为替换的元素(可用函数)

5.JavaScript 中的类型转换机制

显示转换:

  • Number()
    • 字符串:如果可以被解析为数值,则转换为相应的数值
    • 字符串:如果不可以被解析为数值,返回 NaN
    • 空字符串转换为0
    • 布尔值:true 转成 1,false 转成 0
    • undefined:转成 NaN
    • null:转成0
    • 对象:通常转换成NaN(除了只包含单个数值的数组)
  • parseInt() parseInt相比Number,就没那么严格了,parseInt函数逐个解析字符,遇到不能转换的字符就停下来
  • String() 可以将任意类型的值转化成字符串
    • 特殊:如果接受的是对象则返回[object,object] 如果是数组【1,2,3】返回1,2,3
  • Boolean() 可以将任意类型的值转为布尔值

隐式转换:

  • +运算中,一旦存在字符串,则会进行字符串拼接操作
  • 除了+有可能把运算子转为字符串,其他运算符都会把运算子自动转成数值 。常用就是将字符串转为数值 字符串-0 = 数值

6.null 和 undefined 的区别?

  • null和undefined不能通过==来判断。

  • undefined

    • 这个变量从根本上就没有定义
    • 隐藏式 空值
  • null

    • 这个值虽然定义了,但它并未指向任何内存中的对象
    • 声明式 空值

7. “ ===”、“ ==”的区别?

==: 如果操作数相等,则会返回 true

  • 两个都为简单类型,字符串和布尔值都会转换成数值,再比较
  • 简单类型与引用类型比较,对象转化成其原始类型的值,再比较
  • 两个都为引用类型,则比较它们是否指向同一个对象
  • null 和 undefined 相等
  • 存在 NaN 则返回 false

===:只有在无需类型转换运算数就相等的情况下,才返回 true,需要检查数据类型

区别:

  • 相等操作符(==)会做类型转换,再进行值的比较,全等运算符不会做类型转换

8. “eval是做什么的?

它的功能是把对应的字符串解析成 JS 代码并运行;
应该避免使用 eval,不安全,非常耗性能(2次,一次解析成 js 语句,一次执行)。

9. 箭头函数有哪些特点?

不需要function关键字来创建函数
省略return关键字
改变this指向

10. var、let、const 区别?

var 存在变量提升。
let 只能在块级作用域内访问。
const 用来定义常量,必须初始化,不能修改(对象特殊)

11. new操作符具体干了什么呢?

1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到 this 引用的对象中。
3、新创建的对象由 this 所引用,并且最后隐式的返回 this 。

12.深拷贝浅拷贝的区别?如何实现一个深拷贝?

浅拷贝: 指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝 , 两个对象指向同一个地址

深拷贝: 深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

如何实现深拷贝:

  • JSON.stringify()
  • 手写循环递归
  • _.cloneDeep()
  • MessageChannel 新增
  • jquery的extend

13.对作用域链的理解

  • 作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的
  • 简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期

14.JavaScript原型,原型链 ? 有什么特点?

  • 原型:
    • JavaScript的所有对象中都包含了一个 [__proto__] 内部属性,这个属性所对应的就是该对象的原型
    • JavaScript的函数对象,除了原型 [__proto__] 之外,还预置了 prototype 属性
    • 当函数对象作为构造函数创建实例时,该 prototype 属性值将被作为实例对象的原型 [__proto__]
  • 原型链:
    • 当一个对象调用的属性/方法自身不存在时,就会去自己 [__proto__] 关联的前辈 prototype 对象上去找
    • 如果没找到,就会去该 prototype 原型 [__proto__] 关联的前辈 prototype 去找。依次类推,直到找到属性/方法或 undefined 为止。从而形成了所谓的“原型链”
  • 原型特点:
    • JavaScript对象是通过引用来传递的,当修改原型时,与之相关的对象也会继承这一改变

15.请解释什么是事件代理

  • 事件代理(Event Delegation),又称之为事件委托。是 JavaScript 中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能
  • 可以大量节省内存占用,减少事件注册,比如在table上代理所有tdclick事件就非常棒
  • 可以实现当新增子对象时无需再次对其绑定

16.Javascript如何实现继承?

  • 构造函数绑定:使用 callapply 方法,将父对象的构造函数绑定在子对象上
  • 实例继承:将子对象的 prototype 指向父对象的一个实例 Cat.prototype = new Animal();
  • 拷贝继承:如果把父对象的所有属性和方法,拷贝进子对象
  • 原型继承:将子对象的 prototype 指向父对象的 prototype F.prototype = Parent.prototype;
  • ES6 语法糖 extends:class ColorPoint extends Point {}

17.谈谈This对象的理解

  • this总是指向函数的直接调用者(而非间接调用者)
  • 如果有new关键字,this指向new出来的那个对象
  • 在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window

18.事件模型

W3C中定义事件的发生经历三个阶段:捕获阶段(capturing)、目标阶段(targetin)、冒泡阶段(bubbling

  • 冒泡型事件:当你使用事件冒泡时,子级元素先触发,父级元素后触发
  • 捕获型事件:当你使用事件捕获时,父级元素先触发,子级元素后触发
  • DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件
  • 阻止冒泡:在W3c中,使用stopPropagation()方法;在IE下设置cancelBubble = true
  • 阻止捕获:阻止事件的默认行为,例如click - 后的跳转。在W3c中,使用preventDefault()方法,在IE下设置window.event.returnValue = false

19.new操作符具体干了什么呢?

  • 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型
  • 属性和方法被加入到 this 引用的对象中
  • 新创建的对象由 this 所引用,并且最后隐式的返回 this

20.JavaScript中执行上下文和执行栈是什么?

执行上下文: 是一种对Javascript代码执行环境的抽象概念,也就是说只要有Javascript代码运行,那么它就一定是运行在执行上下文中

  • 全局执行上下文:只有一个,浏览器中的全局对象就是 window对象,this 指向这个全局对象
  • 函数执行上下文:存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文
  • Eval 函数执行上下文: 指的是运行在 eval 函数中的代码,很少用而且不建议使用

执行栈:也叫调用栈,具有 LIFO(后进先出)结构,用于存储在代码执行期间创建的所有执行上下文

  • Javascript引擎开始执行你第一行脚本代码的时候,它就会创建一个全局执行上下文然后将它压到执行栈中
  • 每当引擎碰到一个函数的时候,它就会创建一个函数执行上下文,然后将这个执行上下文压到执行栈中
  • 引擎会执行位于执行栈栈顶的执行上下文(一般是函数执行上下文),当该函数执行结束后,对应的执行上下文就会被弹出,然后控制流程到达执行栈的下一个执行上下文

21.typeof 与 instanceof 区别?

typeof 操作符返回一个字符串,表示未经计算的操作数的类型

>  [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O2At0a2V-1684669265343)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1683945877205.png)]

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

区别:

  • typeof会返回一个变量的基本类型,instanceof返回的是一个布尔值
  • instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型(instanceof 判断对象是通过原型链来确定)
  • typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了function 类型以外,其他的也无法判断

22.判断是否为数组的5种方法?

  • instanceof data instanceof Array
  • constructor data.constructor == Array
  • Array.isArray() Array.isArray(data) 最推荐
  • typeof typeof(data)
  • Object.prototype.toSrtring.call()

23. 判断一个值是什么类型有哪些方法?

  • typeof 运算符
  • instanceof 运算符
  • Object.prototype.toString.call 方法
  • constructor

24. ajax过程?

(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
(3)设置响应HTTP请求状态变化的函数.
(4)发送HTTP请求.
(5)获取异步调用返回的数据.
(6)使用JavaScript和DOM实现局部刷新.

25.Ajax原理,ajax优缺点?

  • Ajax的原理简单来说是在用户和服务器之间加了—个中间层(AJAX引擎),通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。使用户操作与服务器响应异步化。这其中最关键的一步就是从服务器获得请求数据

  • Ajax的过程只涉及JavaScriptXMLHttpRequestDOMXMLHttpRequestajax的核心机制

在这里插入图片描述
在这里插入图片描述

  • 优点:
    • 通过异步模式,提升了用户体验.
    • 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用.
    • Ajax在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。
    • Ajax可以实现动态不刷新(局部刷新)
  • 缺点:
    • 安全问题 AJAX暴露了与服务器交互的细节。
    • 对搜索引擎的支持比较弱。
    • 不容易调试。

26.bind、call、apply 区别?

bind、call、apply用来改变this指向

apply:接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入

改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次 fn.apply(null,[1,2,3]);

call: 第一个参数也是this的指向,后面传入的是一个参数列表 fn.call(obj,1,2,3)

bind: bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入) 返回的是新的函数

27.如何实现一个bind?

实现bind三步:

  • 修改this指向
  • 动态传递参数
  • 兼容new关键字

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oUK93GGz-1684669265344)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1683947651751.png)]

28.说说你对正则表达式的理解?应用场景?

正则表达式是一种用来匹配字符串的强有力的武器

应用场景:

  • 验证QQ合法性(5~15位、全是数字、不以0开头):
  • 验证手机号格式

29.对事件循环的理解(详细)?

前提: JavaScript是一门单线程的语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环

JavaScript中,所有的任务都可以分为

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
  • 异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等

同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就事件循环

异步任务分为微任务宏任务:

微任务: 一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前

  • Promise
  • MutaionObserver 监听dom发生改变的
  • Object.observe(已废弃;Proxy 对象替代)
  • process.nextTick(Node.js)

宏任务: 宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合

  • script (可以理解为外层同步代码)
  • setTimeout/setInterval
  • postMessage、MessageChannel
  • setImmediate、I/O(Node.js)

执行顺序:

  • 先执行同步代码,
  • 遇到异步宏任务则将异步宏任务放入宏任务队列中,
  • 遇到异步微任务则将异步微任务放入微任务队列中,
  • 当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,
  • 微任务执行完毕后再将异步宏任务从队列中调入主线程执行,
  • 一直循环直至所有任务执行完毕。

30.DOM常见的操作有哪些?

  • 创建节点
    • createElement 创建新元素,接受一个参数,即要创建元素的标签名
  • 查询节点
    • querySelector 传入任何有效的css 选择器,即可选中单个 DOM元素(首个) 如果页面上没有指定的元素时,返回 null
    • querySelectorAll 返回一个包含节点子树内所有与之相匹配的Element节点列表,如果没有相匹配的,则返回一个空节点列表
  • 更新节点
    • innerHTML 不但可以修改一个DOM节点的文本内容,还可以直接通过HTML片段修改DOM节点内部的子树
    • innerText
    • style dom对象.style.样式属性 = ‘’
  • 添加节点
    • innerHTML
    • appendChild 把一个子节点添加到父节点的最后一个子节点
    • insertBefore(新dom,指定dom对象) 把子节点插入到指定的位置的前面
    • setAttribute 在指定元素中添加一个属性节点,如果元素中已有该属性改变属性值
  • 删除节点
    • removeChild 拿到父节点,要删除的节点dom对象。父.removeChild(子)

31.说说你对BOM的理解,常见的BOM对象你了解哪些?

BOM (Browser Object Model),浏览器对象模型,提供了独立于内容与浏览器窗口进行交互的对象 。

浏览器的全部内容可以看成DOM,整个浏览器可以看成BOM

BOM对象:

  • window: Bom的核心对象是window,它表示浏览器的一个实例 。 在浏览器中,window对象有双重角色,即是浏览器窗口的一个接口,又是全局对象
  • location:获取url地址信息
  • navigator: 对象主要用来获取浏览器的属性,区分浏览器类型
  • screen: 保存的纯粹是客户端能力信息,也就是浏览器窗口外面的客户端显示器的信息,比如像素宽度和像素高度
  • history: 主要用来操作浏览器URL的历史记录,可以通过参数向前,向后,或者向指定URL跳转

32.BOM和DOM区别?

  • BOM(浏览器对象):与浏览器交互的方法和对象
    • BOM是浏览器对象模型,它指的是将浏览器当作一个对象来对待,这个对象主要定义了与浏览器进行交互的方法和接口
    • BOM的核心是window,而window对象具有双重角色,它既是js访问浏览器窗口的一个接口,又是一个全局对象(Global)
    • 这就意味着网页中定义的任何对象、变量和函数,都会作为全局对象的一个属性或者方法存在
  • DOM(文档对象模型):处理网页内容的方法和接
    • DOM是文档对象模型,它指的是把文档当作一个对象来对待,这个对象主要定义了处理网页的内容和接口

33.如何解决跨域问题?

了解同源策略: 同源是指"协议+域名+端口"三者相同,它是浏览器最核心也最基本的安全功能如果缺少了同源策略,浏览器很容易受到XSSCSRF等攻击

  • 通过jsonp跨域
  • nginx代理跨域
  • nodejs中间件跨域
  • 后端在头部信息中设置安全域名
  • 前端代理

34.异步加载js方式?

  • 设置``属性 async="async" (一旦脚本可用,则会异步执行)
  • 动态创建 script DOMdocument.createElement('script');
  • XmlHttpRequest 脚本注入
  • 异步加载库 LABjs
  • 模块加载器 Sea.js

35.哪些操作会导致内存泄漏?

内存泄漏: JavaScript 内存泄露指对象在不需要使用它时仍然存在,导致占用的内存不能使用或回收

  • 未使用 var 声明的全局变量
  • 闭包函数(Closures)
  • 循环引用(两个对象相互引用)
  • 控制台日志(console.log)
  • 移除存在绑定事件的DOM元素(IE)
  • setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏
  • 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收

36.XML和JSON的区别?

  • 数据体积:JSON数据体积更小
  • 数据交互:JSON与JavaScript得交互更加方便,更容易被解析,更好的数据传输
  • 传输速度:JSON传输速度快
  • 数据描述:JSON对数据的描述相比XML较差

37.说说你对递归得理解?

递归: 在数学与计算机科学中,是指在函数的定义中使用函数自身的方法

38.说说你对函数式编程的理解?优缺点?纯函数,高阶函数,柯里化

主要的编程范式有三种:命令式编程,声明式编程和函数式编程

函数式编程: 更加强调程序执行的结果而非执行的过程,简单来讲,就是要把过程逻辑写成函数,定义好输入参数,只关心它的输出结果

纯函数: 纯函数是对给定的输入返还相同输出的函数,并且要求你所有的数据都是不可变的,即纯函数=无状态+数据不可变

  • 函数内部传入指定的值,就会返回确定唯一的值
  • 不会造成超出作用域的变化,例如修改全局变量或引用传递的参数

高阶函数: 是以函数作为输入或者输出的函数被称为高阶函数

柯里化: 把一个多参数函数转化成一个嵌套的一元函数的过程

优点:

  • 更好的管理状态
  • 更简单的复用
  • 减少代码量,提高维护性

缺点:

  • 性能:函数式编程相对于指令式编程,性能绝对是一个短板,因为它往往会对一个方法进行过度包装,从而产生上下文切换的性能开销
  • 资源占用:在 JS 中为了实现对象状态的不可变,往往会创建新的对象,因此,它对垃圾回收所产生的压力远远超过其他编程方式
  • 递归陷阱:在函数式编程中,为了实现迭代,通常会采用递归操作

39.Javascript中如何实现函数缓存?函数缓存有哪些应用场景?

函数缓存,就是将函数运算过的结果进行缓存

实现方式: 实现函数缓存主要依靠闭包、柯里化、高阶函数

应用场景:

  • 对于昂贵的函数调用,执行复杂计算的函数
  • 对于具有有限且高度重复输入范围的函数
  • 对于具有重复输入值的递归函数
  • 对于纯函数,即每次使用特定输入调用时返回相同输出的函数

40. JSON 的了解?

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小
{‘age’:‘12’, ‘name’:‘back’}

41. document.write 和 innerHTML 的区别?

document.write 只能重绘整个页面
innerHTML 可以重绘页面的一部分

42. 请解释一下 JavaScript 的同源策略?

概念:同源策略是客户端脚本(尤其是Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。

43. 介绍一下闭包和闭包常用场景?

  • 闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包常见方式,就是在一个函数的内部创建另一个函数
  • 使用闭包主要为了设计私有的方法和变量,闭包的优点是可以避免变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念。
  • 闭包有三个特性:
    • 函数内再嵌套函数
    • 内部函数可以引用外层的参数和变量
    • 参数和变量不会被垃圾回收机制回收
  • 闭包的好处: 能够实现封装和缓存等;
  • 闭包的缺点就是常驻内存,会增大内存使用量,使用不当会造成内存泄漏
  • 应用场景:
    • 常见的防抖节流
    • 使用闭包可以在 JavaScript 中模拟块级作用域
    • 闭包可以用于在对象中创建私有变量

44. javascript的内存(垃圾)回收机制?

  • 垃圾回收器会每隔一段时间找出那些不再使用的内存,然后为其释放内存
  • 标记清除方法(mark and sweep),
    • 这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”
    • 垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了
  • 引用计数方法(reference counting)
    • 在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。
  • 在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 也就是说只要涉及BOM及DOM就会出现循环引用问题。

45. 用js递归的方式写1到100求和?

function add(num1, num2) {
	const num = num1 + num2;
    if(num2 === 100) {
        return num;
	} else {
	    return add(num, num2 + 1)
    }
}
var sum = add(1, 2);              

46. 事件队列(宏任务微任务)

可以分为微任务(micro task)队列和宏任务(macro task)队列。

微任务一般比宏任务先执行,并且微任务队列只有一个,宏任务队列可能有多个。另外我们常见的点击和键盘等事件也属于宏任务。

下面我们看一下常见宏任务和常见微任务。

常见宏任务:

  • setTimeout()
  • setInterval()
  • setImmediate()

常见微任务:

  • promise.then()、promise.catch()
  • new MutaionObserver()
  • process.nextTick()

微任务和宏任务的本质区别。

  • 宏任务特征:有明确的异步任务需要执行和回调;需要其他异步线程支持。
  • 微任务特征:没有明确的异步任务需要执行,只有回调;不需要其他异步线程支持。
setTimeout(function () {
 console.log("1");
}, 0);
async function async1() {
 console.log("2");
 const data = await async2();
 console.log("3");
 return data;
}
async function async2() {
 return new Promise((resolve) => {
     console.log("4");
     resolve("async2的结果");
 }).then((data) => {
     console.log("5");
     return data;
 });
}
async1().then((data) => {
 console.log("6");
 console.log(data);
});
new Promise(function (resolve) {
 console.log("7");
resolve()
}).then(function () {
 console.log("8");
});

// 2 4 7 5 8 3 6 async2的结果 1

43.async/await, Generator

async 是一个通过异步执行并隐式返回 Promise 作为结果的函数。是Generator函数的语法糖,并对Generator函数进行了改进。
改进:

  • 内置执行器,无需手动执行 next() 方法。
  • 更好的语义
  • 更广的适用性:co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
  • 返回值是 Promise,比 Generator 函数返回的 Iterator 对象方便,可以直接使用 then() 方法进行调用。
  • async 隐式返回 Promise 作为结果的函数,那么可以简单理解为,await后面的函数执行完毕时,await会产生一个微任务(Promise.then是微任务)。

Generator 是 ES6 引入的新概念,它允许在函数执行过程中暂停和恢复它们的状态。通过 function* 声明一个 Generator 函数,可以在函数体内使用关键字 yield 来生成一个状态,并将函数挂起,等待下一次调用。Generator 函数返回一个可迭代对象,可以通过 next() 方法获取当前生成器的状态值。使用 Generator 函数可以更简单地实现异步操作,避免回调嵌套带来的问题。

48. JavaScript 是单线程的,浏览器是多进程的

  • 每打开一个新网页就会创建一个渲染进程
  • 渲染进程是多线程的
  • 负责页面渲染的 GUI 渲染线程
  • 负责JavaScript的执行的 JavaScript 引擎线程,
  • 负责浏览器事件循环的事件触发线程,注意这不归 JavaScript 引擎线程管
  • 负责定时器的定时触发器线程,setTimeout 中低于 4ms 的时间间隔算为4ms
  • 负责XMLHttpRequest的异步 http 请求线程
  • GUI 渲染线程与 JavaScript 引擎线程是互斥的
  • 单线程JavaScript是因为避免 DOM 渲染的冲突,web worker 支持多线程,但是 web worker 不能访问 window 对象,document 对象等。

49.说说 Javascript 数字精度丢失的问题,如何解决?

例子:0.1+0.2===0.3 =>false 涉及IEE754标准

问题原因:

  • 计算机存储双精度浮点数需要先把十进制数转换为二进制的科学记数法的形式,然后计算机以自己的规则{符号位+(指数位+指数偏移量的二进制)+小数部分}存储二进制的科学记数法
  • 因为存储时有位数限制(64位),并且某些十进制的浮点数在转换为二进制数时会出现无限循环,会造成二进制的舍入操作(0舍1入),当再转换为十进制时就造成了计算误差

解决:

  • 使用 toFixed() 方法:将浮点数转化为一个指定位数小数的字符串形式
  • 使用第三方库,Math.jsBigDecimal.js

50.说说你对模块化方案的理解,比如 CommonJS、AMD、CMD、ES Module 分别是什么?

  • CommonJS加载模块同步,主要用于服务器端,它主要依靠require和exports来实现模块化,require用户加载模块,exports用于导出模块
  • AMD异步模块定义,他解决了在浏览器环境下文件以来管理,模块加载的问题。与commonjs不同,AMD使用异步方式加载模块
  • CMD通用模块定义,cmd也是为了解决浏览器端模块化出现的,与AMD不同的是它使用同步方式加载模块,主要依赖require和define来实现模块化
  • ES Module是es6新增的模块化方案,支持在浏览器和node.js使用,并且已经得到了嵌入式运行环境的支持,与commonjs和amd不同,ES Module是静态加载它使用import和export关键字实现模块化

51.用过哪些设计模式?

  • 工厂模式:
    • 工厂模式解决了重复实例化的问题,但还有一个问题,那就是识别问题
    • 主要好处就是可以消除对象间的耦合,通过使用工程方法而不是new关键字
  • 构造函数模式
    • 使用构造函数的方法,即解决了重复实例化的问题,又解决了对象识别的问题,该模式与工厂模式的不同之处在于,直接将属性和方法赋值给 this对象;

52.javascript有哪些方法定义对象?

  • 对象字面量: var obj = {}; 原型是Object.prototype
  • 构造函数: var obj = new Object();
  • Object.create(): var obj = Object.create(Object.prototype);

53.说说你对promise的了解

54.web开发中会话跟踪的方法有哪些?

  • cookie
  • session
  • url重写
  • 隐藏input
  • ip地址

55.介绍js有哪些内置对象?

  • ObjectJavaScript 中所有对象的父对象
  • 数据封装类对象:ObjectArrayBooleanNumberString
  • 其他对象:FunctionArgumentsMathDateRegExpError

56.eval是做什么的?

  • 它的功能是把对应的字符串解析成JS代码并运行
  • 应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)
  • JSON字符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')')

57.parseInt函数,[“1”, “2”, “3”].map(parseInt) 答案是多少?

parseInt函数接收两个参数第一个参数是要被解析的字符串,第二个参数是一个可选的进制数。

答案:【1,NaN,NaN】

解析:

  • [‘1’,‘2’,‘3’].map(parseInt)通过map便利的数组会将索引作为第二个参数传入,所以会以parseint(2,1)第二个参数1不是合法的进制数,paeseint(3,2)这里因为3不是二进制数

58.javascript 代码中的"use strict";是什么意思?说说严格模式的限制

  • use strict是一种ECMAscript 5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行,使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为

限制:

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性
  • 不能使用with语句
  • 禁止this指向window

59.js延迟加载的方式有哪些?

  • 设置``属性 defer="defer" (脚本将在页面完成解析时执行)
  • 动态创建 script DOMdocument.createElement('script');
  • XmlHttpRequest 脚本注入
  • 延迟加载工具 LazyLoad

60.同步和异步的区别?

  • 同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作
  • 异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容

61.ES6新特性

  • 增加了letconst命令,用来声明变量。
  • 新增模板字符串(为JavaScript提供了简单的字符串插值功能)
  • 箭头函数
  • for-of(用来遍历数据—例如数组中的值。)
  • arguments对象可被不定参数和默认参数完美代替。
  • 扩展运算符,解构赋值
  • ES6promise对象纳入规范,提供了原生的Promise对象。
  • 增加了块级作用域,let命令实际上就增加了块级作用域。
  • 还有就是引入module模块的概念

62.let,const,var区别?

通过const声明的对象属性不可修改!!!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BqBOkSmH-1684669265345)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1684154487983.png)]

63.let和var区别?

  • let命令不存在变量提升,如果在let前使用,会导致报错
  • 如果块区中存在letconst命令,就会形成封闭作用域
  • 不允许重复声明,因此,不能在函数内部重新声明参数

64.如果new一个箭头函数的会怎么样?

箭头函数是ES6中的提出来的,它没有prototype,也没有自己的this指向,更不可以使用arguments参数,所以不能New一个箭头函数。

65.箭头函数与普通函数的区别?

  • 箭头函数比普通函数更加简洁
  • 箭头函数没有自己的this
  • 箭头函数继承来的this永远不会改变
  • 箭头函数不能走为构造函数
  • 箭头函数没有arguments
  • call,bind,apply无法改变this指向

66.扩展运算符的作用

扩展运算符:(…)

对象扩展运算符:用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中

数组扩展运算符:可以将一个数组转为用逗号分隔的参数序列,且每次只能展开一层数组

67.ES6中模板语法与字符串处理

在es6之前拼接字符串采用的是字符串通过’+'拼接,很麻烦

es6字符模板使用:``结合${变量名}

var name='lc'
var age = 27
var address = 'zg'
var information = `my name ${name},I am ${age} years old this year,I'm from ${address}`

68.map与forEach的区别

  • forEach方法,是最基本的方法,就是遍历与循环,默认有3个传参:分别是遍历的数组内容item、数组索引index、和当前遍历数组Array
  • map方法,基本用法与forEach一致,但是不同的,它会返回一个新的数组,所以在callback需要有return值,如果没有,会返回undefined

69.Js动画与CSS动画区别及相应实现

  • CSS3的动画的优点
    • 在性能上会稍微好一些,浏览器会对CSS3的动画做一些优化
    • 代码相对简单
  • 缺点
    • 在动画控制上不够灵活
    • 兼容性不好
  • JavaScript的动画正好弥补了这两个缺点,控制能力很强,可以单帧的控制、变换,同时写得好完全可以兼容IE6,并且功能强大。对于一些复杂控制的动画,使用javascript会比较靠谱。而在实现一些小的交互动效的时候,就多考虑考虑CSS

70.gulp是什么?

  • gulp是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器;它不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成
  • Gulp的特点:
    • 易于使用:通过代码优于配置的策略,gulp 让简单的任务简单,复杂的任务可管理
    • 构建快速 利用 Node.js 流的威力,你可以快速构建项目并减少频繁的 IO 操作
    • 易于学习 通过最少的 API,掌握 gulp 毫不费力,构建工作尽在掌握:如同一系列流管道

71.事件的各个阶段, addEventListener

捕获阶段–目标阶段–冒泡阶段

  • 由此,addEventListener的第三个参数设置为true和false的区别已经非常清晰了
    • true表示该元素在事件的“捕获阶段”(由外往内传递时)响应事件
    • false表示该元素在事件的“冒泡阶段”(由内向外传递时)响应事件 默认false

72.数组some函数和every函数

every 函数接受一个函数作为参数,这个函数会被依次应用到数组中的每个元素。该函数应该返回一个布尔值:

  • 如果返回 true,则表示当前元素满足条件,继续检查下一个元素。
  • 如果返回 false,则表示当前元素不满足条件,every 函数将立即返回 false,不再检查后面的元素

some 函数接受一个函数作为参数,这个函数会被依次应用到数组中的每个元素。该函数应该返回一个布尔值:

  • 如果返回 true,则表示当前元素满足条件,some 函数将立即返回 true,不再检查后面的元素。
  • 如果返回 false,则表示当前元素不满足条件,继续检查下一个元素。

73.数组乱序

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    arr.sort(() => Math.random() - 0.5)

74.如何渲染几万条数据并不卡住界面,requestAnimationFrame

requestAnimationFrame 是一个由浏览器提供的 API,用于优化页面动画、避免出现卡顿、异闻和掉帧的情况。它能够在浏览器下一次重绘之前,通知浏览器调用一个指定的函数来更新动画,从而使得动画呈现更加流畅、自然。

实现流程:假如有一万条数据,我们还需要设置每次渲染条数,总计渲染次数,当前渲染次数三个变量。首先自动执行一次渲染函数(loop),通过条件判断当前渲染次数是否小于总渲染次数进行继续执行,满足条件调用window.requestAnimationFrame(具体渲染函数add);add函数中创建空标签用来接收每次渲染的结构,减少回流次数,当前渲染次数+1,继续执行loop函数

// 插入十万条数据
        const total = 100000
        // 一次插入 20 条,如果觉得性能不好就减少
        const once = 20
        // 渲染数据总共需要几次
        const loopCount = total / once
        // 当前渲染次数
        let countOfRender = 0
        let ul = document.querySelector("ul");
        function add() {
            // 优化性能,插入不会造成回流  createDocumentFragment是一个指向空DocumentFragment对象的引用。下面先将20条插入空元素避免回流
            const fragment = document.createDocumentFragment();
            for (let i = 0; i < once; i++) {
                const li = document.createElement("li");
                li.innerText = Math.floor(Math.random() * total);
                fragment.appendChild(li);
            }
            // 一次性添加dom,减少回流次数
            ul.appendChild(fragment);
            countOfRender += 1;  
            loop();
        }
        function loop() {
            if (countOfRender < loopCount) {
                window.requestAnimationFrame(add);
            }
        }
        loop();

75.获取到页面中所有的checkbox怎么做

 var domList = document.getElementsByTagName(‘input’)
 var checkBoxList = [];
 var len = domList.length;  //缓存到局部变量
 while (len--) {  //使用while的效率会比for循环更高
   if (domList[len].type == ‘checkbox’) {
       checkBoxList.push(domList[len]);
   }
 }

76.怎样添加、移除、移动、复制、创建和查找节点

创建节点:

  • createElement() 创建一个具体元素
  • createDocumentFragment() 创建一个dom片段
  • createTextNode() 创建一个文本节点

添加、移除、替换、插入:

  • appendChild() 添加
  • removeChild() 移除
  • replaceChild() 替换
  • insertBefore() 插入

查找:

  • getElementsByTagName() //通过标签名称
  • getElementsByName() //通过元素的Name属性的值
  • getElementById() //通过元素Id,唯一性

77.window.onload和$(document).ready

  • window.onload()方法是必须等到页面内包括图片的所有元素加载完毕后才能执行。
  • $(document).ready()DOM结构绘制完毕后就执行,不必等到加载完毕

78.addEventListener()和attachEvent()的区别

  • addEventListener()是符合W3C规范的标准方法; attachEvent()是IE低版本的非标准方法
  • addEventListener()支持事件冒泡和事件捕获; - 而attachEvent()只支持事件冒泡
  • addEventListener()的第一个参数中,事件类型不需要添加on; attachEvent()需要添加'on'
  • 如果为同一个元素绑定多个事件, addEventListener()会按照事件绑定的顺序依次执行, attachEvent()会按照事件绑定的顺序倒序执行

79.数组去重

利用ES6 Set去重(ES6中最常用)

var arr = [1,2,2,2,3,3,3,3];

console.log(new Set(arr))

遍历去重

include,indexof

80.判断两个对象相等

正常通过==比较,不可以判断对象是否相等

需要通过JSON.stringify()先转化为字符串再进行比较

81.防抖节流

节流: 如果这个事件会被频繁触发,那么节流函数会按照一定的频率来执行函数,不管在这个中间有多少次触发这个事件,执行函数的频次总是固定的;

防抖: 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间(非常短的时间),当事件密集触发时,函数的触发会被频繁的推迟,只有等待了一段时间也没有事件触发,才会真正的执行响应函数

82.检测浏览器版本版本有哪些方式?

  • 根据 navigator.userAgent UA.toLowerCase().indexOf('chrome')
  • 根据 window 对象的成员 'ActiveXObject' in window

83.javascript基本规范

  • 不要在同一行声明多个变量
  • 请使用===/!==来比较true/false或者数值
  • 使用对象字面量替代new Array这种形式
  • 不要使用全局函数
  • Switch语句必须带有default分支
  • If语句必须使用大括号
  • for-in循环中的变量 应该使用let关键字明确限定作用域,从而避免作用域污

84.npm和yarn,pnpm的优势是什么

npm:

  • npm 是 Node.js 自带的包管理器,因此使用 npm 时不需要另外安装软件包,而且能够使用大量的第三方包。npm 的命令简单易学,而且能够满足大部分项目的需求。

yarn :

  • 提供了更好的性能和速度,安装包时能够并行下载,从而提高了安装的效率
  • 引入了锁定文件的概念,用于确保开发环境和生产环境的包版本一致性,从而避免了由于包版本不兼容而引发的问题。
  • 支持离线模式,如果项目中已经安装了所需的包,yarn 不需要从互联网中下载包,而是直接使用本地缓存中的包。

pnpm:

  • 最大优势是节约磁盘空间 pnpm 只在项目中安装一份软件包
  • pnpm 不需要重新安装所有依赖项,而是对每个工程和依赖进行增量安装

85.导致页面加载白屏时间长的原因有哪些,怎么进行优化

原因:

  • 大量 HTTP 请求:在页面加载过程中,浏览器需要请求服务器获取页面的 HTML、CSS、JavaScript、图片等资源,如果请求过多,会导致页面加载时间变长。可以通过减少 HTTP 请求的数量来优化加载速度,例如合并 CSS 和 JavaScript 文件,压缩图片等。
  • 大量 JavaScript 代码:当浏览器下载并解析 JavaScript 代码时,页面的渲染会被阻塞,这也会导致页面加载时间变长。可以通过将 JavaScript 代码异步加载、延迟加载或分割成多个小文件来优化加载速度。
  • 大量 CSS 代码:与 JavaScript 类似,CSS 代码也会阻塞页面渲染,可以通过压缩 CSS 代码、减少 CSS 文件的大小和数量、使用外部链接等方法来优化加载速度。
  • 服务器响应时间过长:如果服务器响应时间过长,也会导致页面加载时间变长。可以通过升级服务器硬件、优化代码等方式来减少服务器响应时间。
  • 不合理的 DOM 结构:如果页面的 DOM 结构不合理,也会导致页面加载时间变长。可以通过减少 DOM 节点数量、避免使用 table 布局、使用 CSS Sprite(雪碧图) 等方式来优化加载速度。

优化:

  • 压缩 HTML、CSS、JavaScript、图片等资源,减少文件大小。
  • 合并 CSS 和 JavaScript 文件,减少 HTTP 请求的数量。
  • 将 JavaScript 代码异步加载、延迟加载或分割成多个小文件。
  • 使用浏览器缓存,避免重复下载资源。
  • 使用外部链接或 CDN 加速器等方式来加速资源加载。
  • 减少 DOM 节点数量,避免使用 table 布局等方式来优化页面渲染速度。

86.DOM克隆操作

深克隆(克隆元素内文本节点加上所有后辈元素节点),

浅克隆(克隆元素本身,不克隆文本节点和后辈节点)

cloneNode()接受一个可选值为true或false的参数。True 表示克隆元素和它的所有子节点。False表示克隆元素但不包含它的子节点

87.沙箱模式

沙箱模式是一种软件设计模式,用于创建一个独立的、受保护的执行环境,隔离代码与外部世界的交互,并限制代码所能访问的资源和功能。在JavaScript中,沙箱模式通常通过将代码封装在匿名函数中并立即调用来实现。这样可以创建一个私有作用域,其中的变量也不会泄漏到全局作用域,从而避免了变量名冲突和数据污染。

虽然闭包和沙箱模式是不同的概念,但它们可以相互结合,以实现更高级别的编程需求。例如,可以使用闭包来创建一个沙箱,限制函数所能访问的变量范围。这种组合可以使代码更加清晰、安全和易于维护。

88.string和tostring什么区别

string和ToString方法的区别在于它们的作用不同。

string是一种数据类型,用于存储和处理字符串,而ToString是一个通用方法,用于将数据转换为字符串。当我们需要将一些非字符串类型的数据转换为字符串时,就可以使用ToString方法来实现。

89.js数据存储方式

  • Cookie:Cookie是一种在浏览器端存储数据的机制,它可以支持长期存储数据,并且数据可以在不同的页面之间共享。使用JavaScript可以通过document.cookie属性来操作Cookie。
  • Web Storage:Web Storage提供了Session Storage和Local Storage两种机制,都是HTML5新增的。Session Storage用于临时性的会话数据存储,数据在用户关闭浏览器后将被清除,而Local Storage则可以长期存储数据,即使用户关闭浏览器也不会丢失。使用JavaScript可以通过window.sessionStorage和window.localStorage对象来操作这两种存储机制。
  • IndexedDB:IndexedDB是一种在浏览器中存储大量结构化数据的机制,它类似于一个本地数据库。IndexedDB提供了一个异步的API,可以在浏览器中建立对象存储空间,在其中存储键值对数据。使用JavaScript可以通过IndexedDB API来操作这种存储机制。
  • Web SQL:废弃

90.cookie,session,token区别

  • Cookie:Cookie是在用户端存储数据的一种机制,它可以存储一些简单的用户信息和标识。服务器通过设置Cookie并发送到客户端,在下次请求时客户端会自动携带该Cookie,从而实现对用户身份的验证或其他操作。Cookie的缺点是可能面临安全问题,因为Cookie存储在客户端,容易遭受窃取或伪造攻击。
  • Session:Session是在服务器端存储数据的一种机制,它可以保存一些复杂的用户信息和状态,用于实现对用户身份的验证和跟踪。服务器使用一个唯一的Session ID来和客户端进行交互,从而避免了安全性问题。但是Session也存在一些缺点,例如对服务器负载压力较大等问题。
  • Token:Token是一种包含用户身份和权限信息的加密字符串,通常由服务器生成并发送给客户端。客户端使用Token代替Cookie或Session来进行身份验证和数据传输。Token的优点是可以减轻服务器压力,减少网络流量和延迟,并且减少了安全性问题。Token的缺点是需要保证其加密和传输的安全性。

Cookie适用于简单的身份验证和数据存储,Session适用于需要复杂状态管理和用户跟踪的场景,而Token则更适合于分布式系统和APP等跨平台的数据传输。

91.js十进制转二进制

  • 使用 toString() 方法和参数 2:
let num = 123
num.toString()  //'123'
num.toString(2)  //'1111011'

92.如何让多个异步函数顺序执行

  • 使用 Promisethen 方法链接异步任务。

  • 使用 async/await 关键字。

93.settimeout事件机制

setTimeout() 方法的实现基于事件机制,它会将回调函数添加到事件队列中。当指定的延迟时间到达后,该回调函数被推入到事件队列的最后,等待 JavaScript 引擎空闲时执行。

由于 JavaScript 的单线程特性和事件循环机制,多个任务可能会阻塞事件队列,从而导致异步代码无法按照预期的顺序执行,我们需要合理地使用定时器以避免这种情况。

如果设置的延迟时间小于 4 毫秒,则实际的延迟时间可能会大于设置值,因为浏览器通常会使用 4 毫秒的最小时间间隔来执行定时器任务。

94.bind连续绑多次最终this指向

先看代码:

function say() {
	alert(this.x);
};
var a = say.bind({x: 1});
var b = a.bind({x: 2});
b(); // 这里会输出1还是2呢?    答案:1

无论使用bind绑定多少次,最终原函数的this值是由第一次绑定传的参数决定的。

95.mep和set

  • Map:可迭代的集合,其中每个元素都由一个键和一个相应的值组成。Map 中的键可以是任何类型,而值也可以是任何类型,包括对象引用和原始值。
  • Set:一种只含有唯一值的集合,不允许出现重复项。Set 中的值可以是任何类型,包括对象引用和原始值。

96.大文件上传

  1. 分片上传:将大文件分成多个小文件,每个小文件单独上传,最后在服务器端进行合并操作,这样可以减少上传和下载的时间,并且一旦上传失败只需要重新上传失败的那个分片,而不需要整个文件重新上传。
  2. 断点续传:在分片上传的基础上,可以利用本地存储技术记录已经上传的分片信息,当上传失败时,可以根据已经上传的分片信息来继续上传失败的那个分片,从而实现断点续传。
  3. 流式上传:在传统的上传方式中,文件需要完全读入内存才能上传,而在流式上传中,文件是按照流的方式逐个读取上传,可以避免一次性读取整个大文件,从而减少内存的占用。
  4. 压缩上传:对于某些文件类型,比如文本文件、图片、视频等,可以先对其进行压缩再上传,可以减少文件的大小并加快上传速度。
  5. 使用断电续传 SDK:除了自己实现断点续传外,也可以使用一些第三方的断点续传 SDK,如七牛、阿里云等都提供了相关的 SDK,可以简化大文件上传的实现。

97.移动端Click300毫秒点击延迟 解决办法

产生原因: 浏览器需要等待一段时间(大约 300 毫秒)来检测用户是单击还是双击。

  • 使用 FastClick:FastClick 是一个 JavaScript 插件,它可以通过消除移动浏览器上的点击延迟来提高 Web 应用程序的响应速度。使用 FastClick 只需要在页面加载完成后引入库文件,并在需要绑定快速点击的元素上通过 FastClick.attach(element) 方法进行绑定即可。
  • 使用 touch 事件:如果不想使用第三方库或插件,也可以通过原生的 touch 事件来模拟快速点击。例如,可以通过监听 touchstart 事件来代替 click 事件,实现更快的响应速度。
  • 设置 meta 标签:将以下 meta 标签添加到 HTML 文件的 head 标签中,可以告诉浏览器不要缩放页面,并且禁用缩放手势,从而提高点击响应速度:

98.如何判断一个对象为空对象

通过 Object.keys(obj) 方法获取对象的所有属性名,并判断属性数量是否为 0 来实现 、

let obj = {'name':'zs'}
Object.keys(obj).length     //1
let objs = {}
Object.keys(objs).length	//0

99.数组常用方法

  • push:向数组末尾添加一个或多个元素,并返回新的长度。
  • pop:删除并返回数组最后一个元素。
  • shift:删除并返回数组第一个元素。
  • unshift:向数组开头添加一个或多个元素,并返回新的长度。
  • concat:合并两个或多个数组,并返回新的数组。不改变原数组。
  • join:将数组中的所有元素转化为字符串,并用指定的分隔符连接起来。
  • slice:返回数组的一个片段(浅拷贝),不影响原数组。
  • splice:在数组中添加或删除元素,可修改原数组。
  • sort:对数组元素进行排序,默认按照 Unicode 码点升序排列,可传入回调函数实现自定义排序。
  • reverse:翻转数组元素顺序,改变原数组。
  • indexOf:查询元素在数组中第一次出现的位置,找到返回其下标,否则返回-1。
  • lastIndexOf:从数组末尾开始查询元素在数组中最后一次出现的位置,找到返回其下标,否则返回-1。
  • filter:返回由满足回调函数条件的所有元素组成的新数组,不改变原数组。
  • map:返回一个新数组,其中的元素是对原有数组元素应用回调函数后得到的结果。
  • reduce:累加器方法,对数组的每个元素(从左到右)执行一个回调函数,返回单个值。
  • some:判断数组是否具有满足条件的值,有就返回true
  • every:判断数组所有值是否都满足条件,都满足返回true
  • forEach:循环数组

100.数组扁平化

  • 使用递归
  • 使用 reduce 方法:reduce 方法可以用来将数组中的每个元素累加到一个结果中
  • 使用 flat 方法:
    • ES2019 中引入了数组的 flat 方法,可以将嵌套的数组扁平化成一维数组。
    • flat 方法只能够将嵌套的层数降至一维,如果需要将多维数组扁平化成一维数组,则需要传递一个大于等于嵌套层数的参数 arr.flat( Infinity ), Infinity 表示扁平化任何深度的嵌套数组

101.for…in 和 for … of区别

for…in 循环是用来遍历对象属性的,它可以枚举目标对象的所有可枚举属性,包括继承链上的属性,但遍历的顺序是不确定的

for…of 循环是用来遍历可迭代对象 (Iterable) 的,它可以遍历数组、字符串、Map、Set 等内置的可迭代对象,但不能遍历普通的对象,也不能遍历对象的属性

区别:

  • for…in遍历数组返回下标,遍历对象返回键
  • for…of遍历数组返回数据,不可以遍历普通对象

102.伪数组,伪数组转换为数组

伪数组是一种类数组对象,它具有类似数组的结构和特性,但并不是真正的数组。

在 JavaScript 中,常见的伪数组包括函数参数 arguments、DOM 元素集合 NodeListHTMLCollection 等。

伪数组和数组区别:

  • 伪数组没有数组的方法和属性(如 push、pop、length),不能使用数组相关的循环方法(如 forEach、map、reduce)等。但它们具有类数组的结构,可以通过下标来访问元素,并且拥有 length 属性

转换: Array.from() 方法或者扩展运算符

103.二维数组应用场景

  • 游戏开发: 在游戏开发中,二维数组通常被用来表示游戏场景、地图、迷宫等
  • 图像处理: 在图像处理中,二维数组常用于表示图像的像素点,每个像素点可以用一个颜色值来表示
  • 数字计算: 在数学计算中,二维数组经常用于存储和处理矩阵

你可能感兴趣的:(前端,javascript,webpack)