前端HTML篇
前端CSS篇
Vue篇
TypeScript篇
React篇
微信小程序篇
前端面试题汇总大全(含答案超详细,HTML,JS,CSS汇总篇)-- 持续更新
前端面试题汇总大全二(含答案超详细,Vue,TypeScript,React,微信小程序,Webpack 汇总篇)-- 持续更新
数据类型主要包括两部分:
- 基本数据+类型: Undefined、Null、Boolean、Number 和 String,Symbol(创建后独一无二且不可变的数据类型 )
- 引用数据类型: Object (包括 Object 、Array 、Function)
存储区别:
- 基本数据类型存储在栈中
- 引用类型的对象存储于堆中
增:
- push() 向数组的末尾添加一个或更多元素,并返回新的长度
- unshift() 在数组开头添加任意多个值,然后返回新的数组长度
- splice() 传入三个参数,分别是开始位置、0(要删除的元素数量)、插入的元素,返回空数组
- concat() 首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组,不会影响原始数组
删:
- pop() 方法用于删除数组的最后一项,同时减少数组的
length
值,返回被删除的项- shift() 方法用于删除数组的第一项,同时减少数组的
length
值,返回被删除的项- splice() 传入两个参数,分别是开始位置,删除元素的数量,返回包含删除元素的数组
- slice() 传入两个参数,分别是开始位置和结束位置,不包括结束值,返回一个新数组,不影响原数组
改:
- splice() 传入三个参数,分别是开始位置,要删除元素的数量,要插入的任意多个元素,返回删除元素的数组,对原数组产生影响
查:
- indexOf() 返回要查找的元素在数组中的位置,如果没找到则返回 -1
- includes() 返回要查找的元素在数组中的位置,找到返回
true
,否则false
- find() 返回第一个匹配的元素
增:
- 字符串可以通过‘+’以及${}进行字符串拼接
- concat 用于将一个或多个字符串拼接成一个新字符串
删:三个函数都接收一个或两个参数,跟数组中slice相似
- slice()
- substr() 接受两个参数:起始索引和要提取的字符数
- substring() 接受两个参数:起始索引和结束索引 不包括结束位置的字符
改:
- trim()、trimLeft()、trimRight() 删除前、后或前后所有空格符,再返回新的字符串
- repeat() 接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果
- padStart()、padEnd() 复制字符串,接收两个参数,第一个参数是长度,第二个参数是想要填充的字符,如果小于指定长度,则在相应一边(end/start)填充字符,直至满足长度条件
- toLowerCase()、 toUpperCase() 大小写转化
查:
- chatAt() 返回给定索引位置的字符,由传给方法的整数参数指定
- indexOf() 从字符串开头去搜索传入的字符串,并
返回位置
(如果没找到,则返回 -1 )- startWith() 从字符串中搜索传入的字符串,
判断开头字符串是否与期待值相同
,并返回一个表示是否包含的布尔值- includes() 从字符串中搜索传入的字符串,
判断字符串是否包含期待值
,并返回一个表示是否包含的布尔值
转换方法:
- split() 把字符串按照指定的分割符,拆分成数组中的每一项
模板匹配方法:
- match() 接收一个参数,可以是一个正则表达式字符串,也可以是一个
RegExp
对象,返回数组- search() 接收一个参数,可以是一个正则表达式字符串,也可以是一个
RegExp
对象,找到则返回匹配索引,否则返回 -1- replace() 接收两个参数,第一个参数为匹配的内容,第二个参数为替换的元素(可用函数)
显示转换:
- 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 = 数值
null和undefined不能通过==来判断。
undefined
- 这个变量从根本上就没有定义
- 隐藏式 空值
null
- 这个值虽然定义了,但它并未指向任何内存中的对象
- 声明式 空值
==: 如果操作数相等,则会返回
true
- 两个都为简单类型,字符串和布尔值都会转换成数值,再比较
- 简单类型与引用类型比较,对象转化成其原始类型的值,再比较
- 两个都为引用类型,则比较它们是否指向同一个对象
- null 和 undefined 相等
- 存在 NaN 则返回 false
===:只有在无需类型转换运算数就相等的情况下,才返回 true,需要检查数据类型
区别:
- 相等操作符(==)会做
类型转换
,再进行值的比较,全等运算符不会做类型转换
它的功能是把对应的字符串解析成 JS 代码并运行;
应该避免使用 eval,不安全,非常耗性能(2次,一次解析成 js 语句,一次执行)。
不需要function关键字来创建函数
省略return关键字
改变this指向
var 存在变量提升。
let 只能在块级作用域内访问。
const 用来定义常量,必须初始化,不能修改(对象特殊)
1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到 this 引用的对象中。
3、新创建的对象由 this 所引用,并且最后隐式的返回 this 。
浅拷贝: 指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝 , 两个对象指向同一个地址
深拷贝: 深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,
不会改变另一个对象的属性
如何实现深拷贝:
- JSON.stringify()
- 手写循环递归
- _.cloneDeep()
- MessageChannel 新增
- jquery的extend
- 作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到
window
对象即被终止,作用域链向下访问变量是不被允许的- 简单的说,
作用域就是变量与函数的可访问范围
,即作用域控制着变量与函数的可见性和生命周期
- 原型:
JavaScript
的所有对象中都包含了一个[__proto__]
内部属性,这个属性所对应的就是该对象的原型- JavaScript的函数对象,除了原型
[__proto__]
之外,还预置了prototype
属性- 当函数对象作为构造函数创建实例时,该 prototype 属性值将被作为实例对象的原型
[__proto__]
- 原型链:
- 当一个对象调用的属性/方法自身不存在时,就会去自己
[__proto__]
关联的前辈prototype
对象上去找- 如果没找到,就会去该
prototype
原型[__proto__]
关联的前辈prototype
去找。依次类推,直到找到属性/方法或undefined
为止。从而形成了所谓的“原型链”- 原型特点:
JavaScript
对象是通过引用来传递的,当修改原型时,与之相关的对象也会继承这一改变
- 事件代理(
Event Delegation
),又称之为事件委托。是JavaScript
中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能- 可以大量节省内存占用,减少事件注册,比如在
table
上代理所有td
的click
事件就非常棒- 可以实现当新增子对象时无需再次对其绑定
- 构造函数绑定:使用
call
或apply
方法,将父对象的构造函数绑定在子对象上- 实例继承:将子对象的 prototype 指向父对象的一个实例 Cat.prototype = new Animal();
- 拷贝继承:如果把父对象的所有属性和方法,拷贝进子对象
- 原型继承:将子对象的
prototype
指向父对象的prototype
F.prototype = Parent.prototype;ES6
语法糖extends:class ColorPoint extends Point {}
this
总是指向函数的直接调用者(而非间接调用者)- 如果有
new
关键字,this
指向new
出来的那个对象- 在事件中,
this
指向触发这个事件的对象,特殊的是,IE
中的attachEvent
中的this
总是指向全局对象Window
W3C
中定义事件的发生经历三个阶段:捕获阶段(capturing
)、目标阶段(targetin
)、冒泡阶段(bubbling
)
- 冒泡型事件:当你使用事件冒泡时,子级元素先触发,父级元素后触发
- 捕获型事件:当你使用事件捕获时,父级元素先触发,子级元素后触发
DOM
事件流:同时支持两种事件模型:捕获型事件和冒泡型事件- 阻止冒泡:在
W3c
中,使用stopPropagation()
方法;在IE下设置cancelBubble = true
- 阻止捕获:阻止事件的默认行为,例如
click -
后的跳转。在W3c
中,使用preventDefault()
方法,在IE
下设置window.event.returnValue = false
- 创建一个空对象,并且
this
变量引用该对象,同时还继承了该函数的原型- 属性和方法被加入到
this
引用的对象中- 新创建的对象由
this
所引用,并且最后隐式的返回this
执行上下文: 是一种对
Javascript
代码执行环境的抽象概念,也就是说只要有Javascript
代码运行,那么它就一定是运行在执行上下文中
- 全局执行上下文:只有一个,浏览器中的全局对象就是
window
对象,this
指向这个全局对象- 函数执行上下文:存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文
- Eval 函数执行上下文: 指的是运行在
eval
函数中的代码,很少用而且不建议使用执行栈:也叫调用栈,具有 LIFO(后进先出)结构,用于存储在代码执行期间创建的所有执行上下文
- 当
Javascript
引擎开始执行你第一行脚本代码的时候,它就会创建一个全局执行上下文然后将它压到执行栈中- 每当引擎碰到一个函数的时候,它就会创建一个函数执行上下文,然后将这个执行上下文压到执行栈中
- 引擎会执行位于执行栈栈顶的执行上下文(一般是函数执行上下文),当该函数执行结束后,对应的执行上下文就会被弹出,然后控制流程到达执行栈的下一个执行上下文
typeof
操作符返回一个字符串,表示未经计算的操作数的类型
instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上区别:
typeof
会返回一个变量的基本类型,instanceof
返回的是一个布尔值instanceof
可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型(instanceof 判断对象是通过原型链来确定)- 而
typeof
也存在弊端,它虽然可以判断基础数据类型(null
除外),但是引用数据类型中,除了function
类型以外,其他的也无法判断
instanceof
data instanceof Arrayconstructor
data.constructor == ArrayArray.isArray()
Array.isArray(data) 最推荐typeof
typeof(data)Object.prototype.toSrtring.call()
- typeof 运算符
- instanceof 运算符
- Object.prototype.toString.call 方法
- constructor
(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
(3)设置响应HTTP请求状态变化的函数.
(4)发送HTTP请求.
(5)获取异步调用返回的数据.
(6)使用JavaScript和DOM实现局部刷新.
Ajax
的原理简单来说是在用户和服务器之间加了—个中间层(AJAX
引擎),通过XmlHttpRequest
对象来向服务器发异步请求,从服务器获得数据,然后用javascrip
t来操作DOM
而更新页面。使用户操作与服务器响应异步化。这其中最关键的一步就是从服务器获得请求数据
Ajax
的过程只涉及JavaScript
、XMLHttpRequest
和DOM
。XMLHttpRequest
是ajax
的核心机制
- 优点:
- 通过异步模式,提升了用户体验.
- 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用.
Ajax
在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。Ajax
可以实现动态不刷新(局部刷新)- 缺点:
- 安全问题
AJAX
暴露了与服务器交互的细节。- 对搜索引擎的支持比较弱。
- 不容易调试。
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
的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)返回的是新的函数
实现bind三步:
- 修改this指向
- 动态传递参数
- 兼容new关键字
正则表达式是一种用来
匹配字符串
的强有力的武器应用场景:
- 验证QQ合法性(5~15位、全是数字、不以0开头):
- 验证手机号格式
前提:
JavaScript
是一门单线程
的语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环在
JavaScript
中,所有的任务都可以分为
- 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
- 异步任务:异步执行的任务,比如
ajax
网络请求,setTimeout
定时函数等同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就事件循环
异步任务分为
微任务
和宏任务
:
微任务
: 一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前
- Promise
- MutaionObserver 监听dom发生改变的
- Object.observe(已废弃;Proxy 对象替代)
- process.nextTick(Node.js)
宏任务
: 宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合
- script (可以理解为外层同步代码)
- setTimeout/setInterval
- postMessage、MessageChannel
- setImmediate、I/O(Node.js)
执行顺序:
- 先执行同步代码,
- 遇到异步宏任务则将异步宏任务放入宏任务队列中,
- 遇到异步微任务则将异步微任务放入微任务队列中,
- 当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,
- 微任务执行完毕后再将异步宏任务从队列中调入主线程执行,
- 一直循环直至所有任务执行完毕。
- 创建节点
- createElement 创建新元素,接受一个参数,即要创建元素的标签名
- 查询节点
- querySelector 传入任何有效的
css
选择器,即可选中单个DOM
元素(首个) 如果页面上没有指定的元素时,返回null
- querySelectorAll 返回一个包含节点子树内所有与之相匹配的
Element
节点列表,如果没有相匹配的,则返回一个空节点列表- 更新节点
- innerHTML 不但可以修改一个
DOM
节点的文本内容,还可以直接通过HTML
片段修改DOM
节点内部的子树- innerText
- style dom对象.style.样式属性 = ‘’
- 添加节点
- innerHTML
- appendChild 把一个子节点添加到父节点的最后一个子节点
- insertBefore(新dom,指定dom对象) 把子节点插入到指定的位置的前面
- setAttribute 在指定元素中添加一个属性节点,如果元素中已有该属性改变属性值
- 删除节点
- removeChild 拿到父节点,要删除的节点dom对象。父.removeChild(子)
BOM
(Browser Object Model),浏览器对象模型,提供了独立于内容与浏览器窗口进行交互的对象 。浏览器的全部内容可以看成
DOM
,整个浏览器可以看成BOM
。BOM对象:
- window:
Bom
的核心对象是window
,它表示浏览器的一个实例 。 在浏览器中,window
对象有双重角色,即是浏览器窗口的一个接口,又是全局对象- location:获取url地址信息
- navigator: 对象主要用来获取浏览器的属性,区分浏览器类型
- screen: 保存的纯粹是客户端能力信息,也就是浏览器窗口外面的客户端显示器的信息,比如像素宽度和像素高度
- history: 主要用来操作浏览器
URL
的历史记录,可以通过参数向前,向后,或者向指定URL
跳转
- BOM(浏览器对象):与浏览器交互的方法和对象
- BOM是浏览器对象模型,它指的是
将浏览器当作一个对象
来对待,这个对象主要定义了与浏览器进行交互的方法和接口- BOM的核心是window,而window对象具有双重角色,它既是js访问浏览器窗口的一个接口,又是一个全局对象(Global)
- 这就意味着网页中定义的任何对象、变量和函数,都会作为全局对象的一个属性或者方法存在
- DOM(文档对象模型):处理网页内容的方法和接
- DOM是文档对象模型,它指的是把文档当作一个对象来对待,这个对象主要定义了处理网页的内容和接口
了解同源策略: 同源是指"协议+域名+端口"三者相同,它是浏览器最核心也最基本的安全功能如果缺少了同源策略,浏览器很容易受到
XSS
、CSRF
等攻击
- 通过jsonp跨域
- nginx代理跨域
- nodejs中间件跨域
- 后端在头部信息中设置安全域名
- 前端代理
- 设置``属性
async="async"
(一旦脚本可用,则会异步执行)- 动态创建
script DOM
:document.createElement('script');
XmlHttpRequest
脚本注入- 异步加载库
LABjs
- 模块加载器
Sea.js
内存泄漏: JavaScript 内存泄露指对象在不需要使用它时仍然存在,导致占用的内存不能使用或回收
- 未使用
var
声明的全局变量- 闭包函数(
Closures
)- 循环引用(两个对象相互引用)
- 控制台日志(
console.log
)- 移除存在绑定事件的
DOM
元素(IE
)setTimeout
的第一个参数使用字符串而非函数的话,会引发内存泄漏- 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为
0
(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收
- 数据体积:JSON数据体积更小
- 数据交互:JSON与JavaScript得交互更加方便,更容易被解析,更好的数据传输
- 传输速度:JSON传输速度快
- 数据描述:JSON对数据的描述相比XML较差
递归: 在数学与计算机科学中,是指在函数的定义中使用函数自身的方法
主要的编程范式有三种:命令式编程,声明式编程和函数式编程
函数式编程: 更加强调程序执行的结果而非执行的过程,简单来讲,就是要把过程逻辑写成函数,定义好输入参数,只关心它的输出结果
纯函数
: 纯函数是对给定的输入返还相同输出的函数,并且要求你所有的数据都是不可变的,即纯函数=无状态+数据不可变
- 函数内部传入指定的值,就会返回确定唯一的值
- 不会造成超出作用域的变化,例如修改全局变量或引用传递的参数
高阶函数
: 是以函数作为输入或者输出的函数被称为高阶函数
柯里化
: 把一个多参数函数转化成一个嵌套的一元函数的过程优点:
- 更好的管理状态
- 更简单的复用
- 减少代码量,提高维护性
缺点:
- 性能:函数式编程相对于指令式编程,性能绝对是一个短板,因为它往往会对一个方法进行过度包装,从而产生上下文切换的性能开销
- 资源占用:在 JS 中为了实现对象状态的不可变,往往会创建新的对象,因此,它对垃圾回收所产生的压力远远超过其他编程方式
- 递归陷阱:在函数式编程中,为了实现迭代,通常会采用递归操作
函数缓存,就是将函数运算过的结果进行缓存
实现方式: 实现函数缓存主要依靠闭包、柯里化、高阶函数
应用场景:
- 对于昂贵的函数调用,执行复杂计算的函数
- 对于具有有限且高度重复输入范围的函数
- 对于具有重复输入值的递归函数
- 对于纯函数,即每次使用特定输入调用时返回相同输出的函数
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小
{‘age’:‘12’, ‘name’:‘back’}
document.write 只能重绘整个页面
innerHTML 可以重绘页面的一部分
概念:同源策略是客户端脚本(尤其是Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。
- 闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包常见方式,就是在一个函数的内部创建另一个函数
- 使用闭包主要为了设计私有的方法和变量,闭包的优点是可以避免变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念。
- 闭包有三个特性:
- 函数内再嵌套函数
- 内部函数可以引用外层的参数和变量
- 参数和变量不会被垃圾回收机制回收
- 闭包的好处: 能够实现封装和缓存等;
- 闭包的缺点就是常驻内存,会增大内存使用量,使用不当会造成内存泄漏
- 应用场景:
- 常见的防抖节流
- 使用闭包可以在
JavaScript
中模拟块级作用域- 闭包可以用于在对象中创建私有变量
- 垃圾回收器会每隔一段时间找出那些不再使用的内存,然后为其释放内存
- 标记清除方法(mark and sweep),
- 这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”
- 垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了
- 引用计数方法(reference counting)
- 在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。
- 在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 也就是说只要涉及BOM及DOM就会出现循环引用问题。
function add(num1, num2) {
const num = num1 + num2;
if(num2 === 100) {
return num;
} else {
return add(num, num2 + 1)
}
}
var sum = add(1, 2);
可以分为微任务(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
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 函数可以更简单地实现异步操作,避免回调嵌套带来的问题。
- 每打开一个新网页就会创建一个渲染进程
- 渲染进程是多线程的
- 负责页面渲染的 GUI 渲染线程
- 负责JavaScript的执行的 JavaScript 引擎线程,
- 负责浏览器事件循环的事件触发线程,注意这不归 JavaScript 引擎线程管
- 负责定时器的定时触发器线程,setTimeout 中低于 4ms 的时间间隔算为4ms
- 负责XMLHttpRequest的异步 http 请求线程
- GUI 渲染线程与 JavaScript 引擎线程是互斥的
- 单线程JavaScript是因为避免 DOM 渲染的冲突,web worker 支持多线程,但是 web worker 不能访问 window 对象,document 对象等。
例子:0.1+0.2===0.3 =>false 涉及IEE754标准
问题原因:
- 计算机存储双精度浮点数需要先把十进制数转换为二进制的科学记数法的形式,然后计算机以自己的规则{符号位+(指数位+指数偏移量的二进制)+小数部分}存储二进制的科学记数法
- 因为存储时有位数限制(64位),并且某些十进制的浮点数在转换为二进制数时会出现无限循环,会造成二进制的舍入操作(0舍1入),当再转换为十进制时就造成了计算误差
解决:
- 使用 toFixed() 方法:将浮点数转化为一个指定位数小数的字符串形式
- 使用第三方库,
Math.js
、BigDecimal.js
- CommonJS加载模块同步,主要用于服务器端,它主要依靠require和exports来实现模块化,require用户加载模块,exports用于导出模块
- AMD异步模块定义,他解决了在浏览器环境下文件以来管理,模块加载的问题。与commonjs不同,AMD使用异步方式加载模块
- CMD通用模块定义,cmd也是为了解决浏览器端模块化出现的,与AMD不同的是它使用同步方式加载模块,主要依赖require和define来实现模块化
- ES Module是es6新增的模块化方案,支持在浏览器和node.js使用,并且已经得到了嵌入式运行环境的支持,与commonjs和amd不同,ES Module是静态加载它使用import和export关键字实现模块化
- 工厂模式:
- 工厂模式解决了重复实例化的问题,但还有一个问题,那就是识别问题
- 主要好处就是可以消除对象间的耦合,通过使用工程方法而不是
new
关键字- 构造函数模式
- 使用构造函数的方法,即解决了重复实例化的问题,又解决了对象识别的问题,该模式与工厂模式的不同之处在于,直接将属性和方法赋值给
this
对象;
- 对象字面量:
var obj = {};
原型是Object.prototype
- 构造函数:
var obj = new Object();
Object.create()
:var obj = Object.create(Object.prototype);
cookie
session
url
重写- 隐藏
input
ip
地址
Object
是JavaScript
中所有对象的父对象- 数据封装类对象:
Object
、Array
、Boolean
、Number
和String
- 其他对象:
Function
、Arguments
、Math
、Date
、RegExp
、Error
- 它的功能是把对应的字符串解析成
JS
代码并运行- 应该避免使用
eval
,不安全,非常耗性能(2
次,一次解析成js
语句,一次执行)- 由
JSON
字符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')')
parseInt函数接收两个参数第一个参数是要被解析的字符串,第二个参数是一个可选的进制数。
答案:【1,NaN,NaN】
解析:
- [‘1’,‘2’,‘3’].map(parseInt)通过map便利的数组会将索引作为第二个参数传入,所以会以parseint(2,1)第二个参数1不是合法的进制数,paeseint(3,2)这里因为3不是二进制数
use strict
是一种ECMAscript 5
添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行,使JS
编码更加规范化的模式,消除Javascript
语法的一些不合理、不严谨之处,减少一些怪异行为限制:
- 变量必须声明后再使用
- 函数的参数不能有同名属性
- 不能使用with语句
- 禁止this指向window
- 设置``属性
defer="defer"
(脚本将在页面完成解析时执行)- 动态创建
script DOM
:document.createElement('script');
XmlHttpRequest
脚本注入- 延迟加载工具
LazyLoad
- 同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作
- 异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容
- 增加了
let
和const
命令,用来声明变量。- 新增模板字符串(为
JavaScript
提供了简单的字符串插值功能)- 箭头函数
for-of
(用来遍历数据—例如数组中的值。)arguments
对象可被不定参数和默认参数完美代替。- 扩展运算符,解构赋值
ES6
将promise
对象纳入规范,提供了原生的Promise
对象。- 增加了块级作用域,
let
命令实际上就增加了块级作用域。- 还有就是引入
module
模块的概念
通过const声明的对象属性不可修改!!!
let
命令不存在变量提升,如果在let
前使用,会导致报错- 如果块区中存在
let
和const
命令,就会形成封闭作用域- 不允许重复声明,因此,不能在函数内部重新声明参数
箭头函数是ES6中的提出来的,它没有prototype,也没有自己的this指向,更不可以使用arguments参数,所以不能New一个箭头函数。
- 箭头函数比普通函数更加简洁
- 箭头函数没有自己的this
- 箭头函数继承来的this永远不会改变
- 箭头函数不能走为构造函数
- 箭头函数没有arguments
- call,bind,apply无法改变this指向
扩展运算符:(…)
对象扩展运算符:用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
数组扩展运算符:可以将一个数组转为用逗号分隔的参数序列,且每次只能展开一层数组
在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}`
forEach
方法,是最基本的方法,就是遍历与循环,默认有3个传参:分别是遍历的数组内容item
、数组索引index
、和当前遍历数组Array
map
方法,基本用法与forEach
一致,但是不同的,它会返回一个新的数组,所以在callback需要有return
值,如果没有,会返回undefined
- CSS3的动画的优点
- 在性能上会稍微好一些,浏览器会对
CSS3
的动画做一些优化- 代码相对简单
- 缺点
- 在动画控制上不够灵活
- 兼容性不好
JavaScript
的动画正好弥补了这两个缺点,控制能力很强,可以单帧的控制、变换,同时写得好完全可以兼容IE6
,并且功能强大。对于一些复杂控制的动画,使用javascript
会比较靠谱。而在实现一些小的交互动效的时候,就多考虑考虑CSS
吧
gulp
是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器;它不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成- Gulp的特点:
- 易于使用:通过代码优于配置的策略,gulp 让简单的任务简单,复杂的任务可管理
- 构建快速 利用
Node.js
流的威力,你可以快速构建项目并减少频繁的IO
操作- 易于学习 通过最少的
API
,掌握gulp
毫不费力,构建工作尽在掌握:如同一系列流管道
捕获阶段–目标阶段–冒泡阶段
- 由此,addEventListener的第三个参数设置为true和false的区别已经非常清晰了
true
表示该元素在事件的“捕获阶段”(由外往内传递时)响应事件false
表示该元素在事件的“冒泡阶段”(由内向外传递时)响应事件默认false
every
函数接受一个函数作为参数,这个函数会被依次应用到数组中的每个元素。该函数应该返回一个布尔值:
- 如果返回
true
,则表示当前元素满足条件,继续检查下一个元素。- 如果返回
false
,则表示当前元素不满足条件,every
函数将立即返回false
,不再检查后面的元素
some
函数接受一个函数作为参数,这个函数会被依次应用到数组中的每个元素。该函数应该返回一个布尔值:
- 如果返回
true
,则表示当前元素满足条件,some
函数将立即返回true
,不再检查后面的元素。- 如果返回
false
,则表示当前元素不满足条件,继续检查下一个元素。
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.sort(() => Math.random() - 0.5)
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();
var domList = document.getElementsByTagName(‘input’)
var checkBoxList = [];
var len = domList.length; //缓存到局部变量
while (len--) { //使用while的效率会比for循环更高
if (domList[len].type == ‘checkbox’) {
checkBoxList.push(domList[len]);
}
}
创建节点:
- createElement() 创建一个具体元素
- createDocumentFragment() 创建一个dom片段
- createTextNode() 创建一个文本节点
添加、移除、替换、插入:
- appendChild() 添加
- removeChild() 移除
- replaceChild() 替换
- insertBefore() 插入
查找:
- getElementsByTagName() //通过标签名称
- getElementsByName() //通过元素的Name属性的值
- getElementById() //通过元素Id,唯一性
window.onload()
方法是必须等到页面内包括图片的所有元素加载完毕后才能执行。$(document).ready()
是DOM
结构绘制完毕后就执行,不必等到加载完毕
addEventListener()
是符合W3C规范的标准方法;attachEvent()
是IE低版本的非标准方法addEventListener()
支持事件冒泡和事件捕获; - 而attachEvent()
只支持事件冒泡addEventListener()
的第一个参数中,事件类型不需要添加on
;attachEvent()
需要添加'on'
- 如果为同一个元素绑定多个事件,
addEventListener()
会按照事件绑定的顺序依次执行,attachEvent()
会按照事件绑定的顺序倒序执行
利用ES6 Set去重(ES6中最常用)
var arr = [1,2,2,2,3,3,3,3];
console.log(new Set(arr))
遍历去重
include,indexof
正常通过==比较,不可以判断对象是否相等
需要通过JSON.stringify()先转化为字符串再进行比较
节流: 如果这个事件会被频繁触发,那么节流函数会按照一定的
频率
来执行函数,不管在这个中间有多少次触发这个事件,执行函数的频次总是固定的;防抖: 当事件触发时,相应的函数并不会立即触发,而是会
等待一定的时间
(非常短的时间),当事件密集触发时,函数的触发会被频繁的推迟,只有等待了一段时间也没有事件触发,才会真正的执行响应函数
- 根据
navigator.userAgent
UA.toLowerCase().indexOf('chrome')
- 根据
window
对象的成员'ActiveXObject' in window
- 不要在同一行声明多个变量
- 请使用
===/!==
来比较true/false
或者数值- 使用对象字面量替代
new Array
这种形式- 不要使用全局函数
Switch
语句必须带有default
分支If
语句必须使用大括号for-in
循环中的变量 应该使用let
关键字明确限定作用域,从而避免作用域污
npm:
- npm 是 Node.js 自带的包管理器,因此使用 npm 时不需要另外安装软件包,而且能够使用大量的第三方包。npm 的命令简单易学,而且能够满足大部分项目的需求。
yarn :
- 提供了更好的性能和速度,安装包时能够并行下载,从而提高了安装的效率
- 引入了锁定文件的概念,用于确保开发环境和生产环境的包版本一致性,从而避免了由于包版本不兼容而引发的问题。
- 支持离线模式,如果项目中已经安装了所需的包,yarn 不需要从互联网中下载包,而是直接使用本地缓存中的包。
pnpm:
- 最大优势是节约磁盘空间 pnpm 只在项目中安装一份软件包
- pnpm 不需要重新安装所有依赖项,而是对每个工程和依赖进行增量安装
原因:
- 大量 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 布局等方式来优化页面渲染速度。
深克隆(克隆元素内文本节点加上所有后辈元素节点),
浅克隆(克隆元素本身,不克隆文本节点和后辈节点)
cloneNode()接受一个可选值为true或false的参数。True 表示克隆元素和它的所有子节点。False表示克隆元素但不包含它的子节点
沙箱模式是一种软件设计模式,用于创建一个独立的、受保护的执行环境,隔离代码与外部世界的交互,并限制代码所能访问的资源和功能。在JavaScript中,沙箱模式通常通过将代码封装在匿名函数中并立即调用来实现。这样可以创建一个私有作用域,其中的变量也不会泄漏到全局作用域,从而避免了变量名冲突和数据污染。
虽然闭包和沙箱模式是不同的概念,但它们可以相互结合,以实现更高级别的编程需求。例如,可以使用闭包来创建一个沙箱,限制函数所能访问的变量范围。这种组合可以使代码更加清晰、安全和易于维护。
string和ToString方法的区别在于它们的作用不同。
string是一种数据类型,用于存储和处理字符串,而ToString是一个通用方法,用于将数据转换为字符串。当我们需要将一些非字符串类型的数据转换为字符串时,就可以使用ToString方法来实现。
- 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:废弃
- Cookie:Cookie是在用户端存储数据的一种机制,它可以存储一些简单的用户信息和标识。服务器通过设置Cookie并发送到客户端,在下次请求时客户端会自动携带该Cookie,从而实现对用户身份的验证或其他操作。Cookie的缺点是可能面临安全问题,因为Cookie存储在客户端,容易遭受窃取或伪造攻击。
- Session:Session是在服务器端存储数据的一种机制,它可以保存一些复杂的用户信息和状态,用于实现对用户身份的验证和跟踪。服务器使用一个唯一的Session ID来和客户端进行交互,从而避免了安全性问题。但是Session也存在一些缺点,例如对服务器负载压力较大等问题。
- Token:Token是一种包含用户身份和权限信息的加密字符串,通常由服务器生成并发送给客户端。客户端使用Token代替Cookie或Session来进行身份验证和数据传输。Token的优点是可以减轻服务器压力,减少网络流量和延迟,并且减少了安全性问题。Token的缺点是需要保证其加密和传输的安全性。
Cookie适用于简单的身份验证和数据存储,Session适用于需要复杂状态管理和用户跟踪的场景,而Token则更适合于分布式系统和APP等跨平台的数据传输。
- 使用
toString()
方法和参数 2:let num = 123 num.toString() //'123' num.toString(2) //'1111011'
使用
Promise
的then
方法链接异步任务。使用
async/await
关键字。
setTimeout()
方法的实现基于事件机制,它会将回调函数添加到事件队列中。当指定的延迟时间到达后,该回调函数被推入到事件队列的最后,等待 JavaScript 引擎空闲时执行。由于 JavaScript 的单线程特性和事件循环机制,多个任务可能会阻塞事件队列,从而导致异步代码无法按照预期的顺序执行,我们需要合理地使用定时器以避免这种情况。
如果设置的延迟时间小于 4 毫秒,则实际的延迟时间可能会大于设置值,因为浏览器通常会使用 4 毫秒的最小时间间隔来执行定时器任务。
先看代码:
function say() { alert(this.x); }; var a = say.bind({x: 1}); var b = a.bind({x: 2}); b(); // 这里会输出1还是2呢? 答案:1
无论使用bind绑定多少次,最终原函数的this值是由第一次绑定传的参数决定的。
Map
:可迭代的集合,其中每个元素都由一个键和一个相应的值组成。Map
中的键可以是任何类型,而值也可以是任何类型,包括对象引用和原始值。Set
:一种只含有唯一值的集合,不允许出现重复项。Set
中的值可以是任何类型,包括对象引用和原始值。
- 分片上传:将大文件分成多个小文件,每个小文件单独上传,最后在服务器端进行合并操作,这样可以减少上传和下载的时间,并且一旦上传失败只需要重新上传失败的那个分片,而不需要整个文件重新上传。
- 断点续传:在分片上传的基础上,可以利用本地存储技术记录已经上传的分片信息,当上传失败时,可以根据已经上传的分片信息来继续上传失败的那个分片,从而实现断点续传。
- 流式上传:在传统的上传方式中,文件需要完全读入内存才能上传,而在流式上传中,文件是按照流的方式逐个读取上传,可以避免一次性读取整个大文件,从而减少内存的占用。
- 压缩上传:对于某些文件类型,比如文本文件、图片、视频等,可以先对其进行压缩再上传,可以减少文件的大小并加快上传速度。
- 使用断电续传 SDK:除了自己实现断点续传外,也可以使用一些第三方的断点续传 SDK,如七牛、阿里云等都提供了相关的 SDK,可以简化大文件上传的实现。
产生原因: 浏览器需要等待一段时间(大约 300 毫秒)来检测用户是单击还是双击。
- 使用
FastClick
:FastClick 是一个 JavaScript 插件,它可以通过消除移动浏览器上的点击延迟来提高 Web 应用程序的响应速度。使用 FastClick 只需要在页面加载完成后引入库文件,并在需要绑定快速点击的元素上通过FastClick.attach(element)
方法进行绑定即可。- 使用
touch 事件
:如果不想使用第三方库或插件,也可以通过原生的 touch 事件来模拟快速点击。例如,可以通过监听touchstart
事件来代替click
事件,实现更快的响应速度。- 设置
meta 标签
:将以下 meta 标签添加到 HTML 文件的head
标签中,可以告诉浏览器不要缩放页面,并且禁用缩放手势,从而提高点击响应速度:
通过
Object.keys(obj)
方法获取对象的所有属性名,并判断属性数量是否为 0 来实现 、let obj = {'name':'zs'} Object.keys(obj).length //1 let objs = {} Object.keys(objs).length //0
push
:向数组末尾添加一个或多个元素,并返回新的长度。pop
:删除并返回数组最后一个元素。shift
:删除并返回数组第一个元素。unshift
:向数组开头添加一个或多个元素,并返回新的长度。concat
:合并两个或多个数组,并返回新的数组。不改变原数组。join
:将数组中的所有元素转化为字符串,并用指定的分隔符连接起来。slice
:返回数组的一个片段(浅拷贝),不影响原数组。splice
:在数组中添加或删除元素,可修改原数组。sort
:对数组元素进行排序,默认按照 Unicode 码点升序排列,可传入回调函数实现自定义排序。reverse
:翻转数组元素顺序,改变原数组。indexOf
:查询元素在数组中第一次出现的位置,找到返回其下标,否则返回-1。lastIndexOf
:从数组末尾开始查询元素在数组中最后一次出现的位置,找到返回其下标,否则返回-1。filter
:返回由满足回调函数条件的所有元素组成的新数组,不改变原数组。map
:返回一个新数组,其中的元素是对原有数组元素应用回调函数后得到的结果。reduce
:累加器方法,对数组的每个元素(从左到右)执行一个回调函数,返回单个值。some
:判断数组是否具有满足条件的值,有就返回trueevery
:判断数组所有值是否都满足条件,都满足返回trueforEach
:循环数组
- 使用递归
- 使用 reduce 方法:reduce 方法可以用来将数组中的每个元素累加到一个结果中
- 使用 flat 方法:
- ES2019 中引入了数组的 flat 方法,可以将嵌套的数组扁平化成一维数组。
- flat 方法只能够将嵌套的层数降至一维,如果需要将多维数组扁平化成一维数组,则需要传递一个大于等于嵌套层数的参数 arr.flat( Infinity ), Infinity 表示扁平化任何深度的嵌套数组
for…in 循环是用来遍历对象属性的,它可以枚举目标对象的所有可枚举属性,包括继承链上的属性,但遍历的顺序是不确定的
for…of 循环是用来遍历可迭代对象 (Iterable) 的,它可以遍历数组、字符串、Map、Set 等内置的可迭代对象,但不能遍历普通的对象,也不能遍历对象的属性
区别:
- for…in遍历数组返回下标,遍历对象返回键
- for…of遍历数组返回数据,不可以遍历普通对象
伪数组是一种类数组对象,它具有类似数组的结构和特性,但并不是真正的数组。
在 JavaScript 中,常见的伪数组包括函数参数
arguments
、DOM 元素集合NodeList
和HTMLCollection
等。伪数组和数组区别:
- 伪数组没有数组的方法和属性(如 push、pop、length),
不能使用数组相关的循环方法
(如 forEach、map、reduce)等。但它们具有类数组的结构,可以通过下标来访问元素,并且拥有 length 属性
转换: Array.from() 方法或者扩展运算符
- 游戏开发: 在游戏开发中,二维数组通常被用来表示游戏场景、地图、迷宫等
- 图像处理: 在图像处理中,二维数组常用于表示图像的像素点,每个像素点可以用一个颜色值来表示
- 数字计算: 在数学计算中,二维数组经常用于存储和处理矩阵