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有哪些内置对象?
Object 是 JavaScript 中所有对象的父对象
数据封装类对象:Object、Array、Boolean、Number 和 String
其他对象:Function、Arguments、Math、Date、RegExp、Error
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 DOM:document.createElement('script');
XmlHttpRequest 脚本注入
延迟加载工具 LazyLoad
60.同步和异步的区别?
同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作
异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容
61.ES6新特性
增加了let和const命令,用来声明变量。
新增模板字符串(为JavaScript提供了简单的字符串插值功能)
箭头函数
for-of(用来遍历数据—例如数组中的值。)
arguments对象可被不定参数和默认参数完美代替。
扩展运算符,解构赋值
ES6将promise对象纳入规范,提供了原生的Promise对象。
增加了块级作用域,let命令实际上就增加了块级作用域。
还有就是引入module模块的概念
62.let,const,var区别?
通过const声明的对象属性不可修改!!!
63.let和var区别?
let命令不存在变量提升,如果在let前使用,会导致报错
如果块区中存在let和const命令,就会形成封闭作用域
不允许重复声明,因此,不能在函数内部重新声明参数
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.如何让多个异步函数顺序执行
使用 Promise 的 then 方法链接异步任务。
使用 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.大文件上传
分片上传:将大文件分成多个小文件,每个小文件单独上传,最后在服务器端进行合并操作,这样可以减少上传和下载的时间,并且一旦上传失败只需要重新上传失败的那个分片,而不需要整个文件重新上传。
断点续传:在分片上传的基础上,可以利用本地存储技术记录已经上传的分片信息,当上传失败时,可以根据已经上传的分片信息来继续上传失败的那个分片,从而实现断点续传。
流式上传:在传统的上传方式中,文件需要完全读入内存才能上传,而在流式上传中,文件是按照流的方式逐个读取上传,可以避免一次性读取整个大文件,从而减少内存的占用。
压缩上传:对于某些文件类型,比如文本文件、图片、视频等,可以先对其进行压缩再上传,可以减少文件的大小并加快上传速度。
使用断电续传 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 元素集合 NodeList 和 HTMLCollection 等。
伪数组和数组区别:
伪数组没有数组的方法和属性(如 push、pop、length),不能使用数组相关的循环方法(如 forEach、map、reduce)等。但它们具有类数组的结构,可以通过下标来访问元素,并且拥有 length 属性
转换: Array.from() 方法或者扩展运算符
103.二维数组应用场景
游戏开发: 在游戏开发中,二维数组通常被用来表示游戏场景、地图、迷宫等
图像处理: 在图像处理中,二维数组常用于表示图像的像素点,每个像素点可以用一个颜色值来表示
数字计算: 在数学计算中,二维数组经常用于存储和处理矩阵