javaScript 基础知识(解决80%js面试问题)
一、变量类型
1.基本类型
直接用typeof进行判断
主要存储位置在栈中
2.引用类型
用typeof进行判断出来是Object,不能直接确定类型(对象、数组等都会被判断为object),
需要用instanceof、constructor、Object.getPrototypeof()和isPrototypeof()、 symbol.toStringTag
主要存储在堆中,栈中存贮指向堆中的地址
3.基本类型和引用类型的拷贝
这里会涉及到深拷贝和浅拷贝的知识,我们在复制基本数据类型的时候,直接let一个变量等
于上一个变量就可以了,但是当我们这样拷贝引用类型的时候(例如一个对象),当我们修
改一处就会一起另外一处也跟着变化,这是因为我们只拷贝了栈中的地址,这两个变量是同
时指向相同的堆中数据的,所以才会相互影响
实现深拷贝的方法:
①JSON.parse(JSON.stringify());
这种方式存在的问题:
函数、undefined:原对象中的函数和undefined值会被忽略。
时间对象(Date):会被转换为字符串格式(如"2021-08-12T01:56:37.328Z"
)。
正则表达式(RegExp):会变成空对象。
错误对象(Error):会变成空对象。
NaN、Infinity、-Infinity:会被转为null。
②递归拷贝
③structuredClone()注意兼容性
_.cloneDeep();
④lodash库里的
4.类型转换
强制类型转换:String()、Number()、Boolean()
隐式类型转换:+、==、&&
math.random():随机树的取值范围在[0,1),取不到1
float转int:① Math.floor(),向下取整
② Math.ceil(),向上取整
③ Math.round(),四舍五入到最接近的整数
④ ParseInt(),会解析一个字符串,并返回整数部分
⑤ ~~(双否运算符),等同于Math.floor,不适用负数
⑥ |0(按位与运算符),等同于Math.floor,不适用负数
二、原型和原型链
1.原型:
是JavaScript中实现继承的一种机制,通过它,对象可以共享方法和属性。
构造函数:
1> 使用function关键字定义,名字首字母大写,使用new关键字创建实例,并且方
法通常挂载在原型上。
2> 需要手动开启严格模式
3> 继承比较复杂,正常使用Object.creat或者借助三方库(lodash的extend)来实
现原型链继承
4> 需要在函数本身上定义静态方法
5> 不太容易集成生成器和装饰器这些高级特性
6> 既可以作为过后再函数也可以作为普通函数进行调用
7> 如果new一个构造函数return对象({}、[]、function等)new操作返回该对象
如果返回原始值(null\1\true\false\String等)会被new忽略,并返回新创建的实
例对象
类(Class):
1> 使用Class关键字定义new关键字实例化,通过constructor构造函数,使用
extends关键字实现继承,子类通过super()来初始化父类的构造函数,Es6引入
的Class语法简洁、直
观、增加了代码的可读性。
2> Class内部默认是严格模式
3> 直接定义静态方法和静态属性
4> 更容易与生成器和装饰器结合使用
5> 自身不能够被调用,必须通过new关键字实例化
2.原型链:
每个对象都有一个与之关联的原型(prototype),这个原型对象也有自己的原型,这样就
形成了一个链式结构,这种结构被称为“原型链”。
3.继承方式
1> 原型链继承
优点:父类新增的方法和属性可以被子类共享
缺点:如果修改父类也会影响子类
2> 构造函数继承
优点:子类可以向父类的构造函数传递参数
缺点:每次重新创建子类都会重新创建父类的方法
3> 组合式继承(构造函数+原型链继承)
优点:既能复用方法又能传递参数
缺点:调用两次父类构造函数,一次原型一次子类的构造函数
4> 原型式继承
优点:实现简单、适用于对象之间的继承
缺点:引用属性会被多个实例共享
5> 寄生式继承
优点:可以在继承的基础上为对象添加新的方法或属性
缺点:和原型链一样,引用属性仍然共享
6> 寄生组合式继承
优点:避免多次调用父类,又保留了组合继承的优点
缺点:代码实现起来比较复杂,理解成本比较高
三、作用域和闭包
1.作用域
变量的可见性和生命周期(变量的合法区域)。
1> 自由变量:在当前作用域中没有定义的变量,自由变量的查找是在函数定义的地方向
上级查找,而不是在执行的地方向上查找
2> this的值实在执行时决定的,不是在定义时决定的,在不改变绑定的情况下的情况下
谁调用指向谁
① 普通函数调用立即执行的情况下指向windows
② call \ apply \ bind 可以改变this的指向,其中call和apply是立即执行,它们的区别
在于传参,call是一个一个传参、apply是数组传参,bind是返回一个新的函数
③ 作为对象的方法调用,this指向该对象
④ 在Class方法中调用,this指向新创建的实例对象
⑤ 箭头函数没有自己的this,它继承外层函数的this
3> arguments 作用域中接收所有参数,他是一个伪数组,有下标,但是没有数组的push
等方法,通过Array.propotype slice call() ,扩展运算符、Array.from、手动遍历复制
callee是存在于arguments对象中的一个属性,用于调用匿名函数的自引用,尤其是
在递归之中,类似的caller是存在于函数对象上的属性,用于获取调用当前函数的那
个函数,严格模式下禁用,一般用于调试
2.闭包
闭包是一个函数,它可以访问并操作定义在它外部的变量。即使外部函数已经执行完
毕,闭包仍然可以访问这些变量。这是因为闭包保存了对这些变量的引用。
闭包的应用场景:
数据封装:用于封装私有数据。
模块化:创建模块化代码,避免全局变量污染。
回调函数:在异步编程中,如setTimeout、事件监听等,经常使用闭包来保存状
态。
柯里化:通过闭包实现函数的柯里化。
回调函数:
是一个作为参数传递给另一个函数的函数。并在特定事件发生或操作完成执行,它
是一种非常常见的模式,特别是在异步编程中
作用:处理异步操作,解耦代码的逻辑、支持事件驱动编程、提高代码的可读性和
灵活性
柯里化:
是将一个接收多个参数的函数变为一系列接收单个参数的函数
四、异步
JavaScript本身是单线程的,但通过异步编程(如回调函数、Promise、async/await)和浏
览器环境中的Web Workers等技术,可在主线程执行其他任务时后台处理耗时操作,实现
并发效果。
1.异步线程、轮询机制、宏任务、微任务
异步线程:是一种非阻塞式任务处理方式
轮询机制:一种通过不断检查某个条件是否满足来等待特定的事件发生的技术
宏任务、微任务:是js事件循环中的两种任务类型,用于管理异步操作的执行顺序
执行顺序:同步任务==> 清空当前微任务队列 ==> 执行一个宏任务 ==> 清空微任务队列
2.Promise、generator 、async/await 、defer
Promise:是一个对象,表示异步操作的最终完成(或失败)及其结果值,基于链式调
用,通过.then解决callback hell ,Promise自身是同步的,.then 是异步的
Promise.all:用于并发执行多个Promise并等待所有Promise完成,所有
Promise都成功时才会fulfilled,返回一个包换所有Promise的数
组的新的Promise,任意一个Promise触发了rejected,都会返回
rejected,并抛出第一个错误。
Promise.allsettled:等待所有Promise都完成(无轮成功失败),返回每一个
Promise的状态和结果
Promise.race:返回第一个完成Promise的结果(无论成功失败)
Promise.any:返回第一个成功的Promise的结果,若是所有的Promise都失
败,则抛出聚合错误
generator:是一种特殊的函数,可以暂停其执行,并在稍后恢复,使用function*定义,
用yield暂停执行并返回值,需要手动管理异步逻辑。
async/await:async声明异步,await等待Promise执行完之后再继续执行后续代码,用
try/cach捕获错误,相较Promise提高了可读性和可维护性
defer:延迟
设置defer属性之后,浏览器同样会并行下载脚本,同时继续解析HTML文档,也不
阻塞页面渲染,defer脚本会在整个文档解析完毕之后,DomContentLoaded事件触
发前按照顺序执行,更适合哪些需要再DOM完全加载后再运行并且彼此之间存在依
赖顺序的脚本
3.时间死区
可以理解为由于事件循环机制和异步任务处理导致的时间延迟或不一致的显现
产生的原因:
宏任务与微任务的调度差异
时间 测量工具的精度问题
主线程被长时间占用导致的延迟
异步任务之间的竞争条件
五、WEB-API
1.DOM
创建节点:document.creatElement()
添加节点:appendChild()
复制节点:cloneNode(false)//true 深
移除节点:removeChild()
查找节点:getElementById()、getElementByClassName()...
事件绑定:addEventListener
事件冒泡:例如点击事件,会逐级向上传递,直至根元素
事件代理:依赖与事件冒泡,将子节点的点击事件放到父级触发
src与href:src是指定嵌入资源的url是页面的一部分,解析到就会立即开始下载并
处理资源,href指定超链接的url,指向另外一个页面、文件或是锚点,
浏览器不会立即加载资源
window.write 和ducment.innerhtml:window.write是重写整个页面,不安全
ducment.innerhtml是操作指定DOM节点的,安全性较高
处理焦点:element = document.getElementById('id')
① 获取焦点:element.focus()
② 移除元素焦点:element.blur()
③监听焦点:addEventListener
④判断是否有焦点:document。activeElement == element
⑤Tab键顺序控制:element.satAttribute('tabIndex','3')
页面渲染过程:
① url解析与DNS查找
② 建立TCP连接
③ TLS/SSL握手(仅限于HTTPS)
④ 发送HTTP请求
⑤ 服务器处理
⑥ 接收HTTP响应
⑦ DOM树构建
⑧ CSSOM树构建
⑨ 渲染树生成
⑩ 布局与绘制
⑪ 合成显示
⑫ 执行JS
⑬ 事件循环交互
2.BOM
浏览器模型对象 Browser object Model
window.history.back();#回退到上一页
window.history.forward();#前进到下一页
window.location.href #获取当前页面的url
window.location.href #跳转到指定的url
window.location.reload()#剔新页面 浏览器上方的刷新按钮
3.事件
document.onload:js原生事件,当整个页面所有资源完全加载之后触发。
优点:确保页面所有资源都加载完毕之后执行
缺点:如果外部资源多,会影响交互
document.ready:是jq的一个方法,它在DOM树完成时触发,不需要等资源加载完
优点:更快的初始化页面,更快的与用户进行交互
缺点:若果代码操作尚未加载的资源就会报错
use strict:是一个字面量表达式,用于js顶部,告诉js解析器用严格模式,在严格模
式下一些不安全的操作会被抛出错误。可用于整个的js脚本,也可以用
于单个的函数
优点:防止意外创建全局变量,禁用对只读属性的修改,禁用with语句,
改进错误检测,提高代码质量
缺点:兼容性问题,增加开发复杂度,可能会破坏现有代码
location.search:解析查询浏览器URL中的字符串
new URLSearchParams(window.location.search)
eval:是一个内置函数,它可以将闯入的字符串作为代码进行解析和执行,他的作
用就是动态运行js代码
Set:存储唯一集的集合,适用于去重和集合操作
Map:键值对组合,键可以是任意类型,适用于复杂的映射关系
WeakSet:存储对象的集合,键是弱引用,适用于临时存储对象
WeakMap:键值对集合,键是弱引用对象,适用于为对象附加私有数据
proxy与Reflect:
proxy:是js中用于定义对象的自定义行为的一种机制,通过Proxy可以拦截并
重新定义目标对像的操作,例如属性访问,赋值、枚举
Reflect:是一个内置对象,提供一组静态方法,用于操作对象的行为,它与
Proxy配合使用,可以使代码更加清晰和一致。
关系:在Proxy的拦截器中可以使用Reflect调用开始操作,从而避免无限递归
或覆盖默认;增强代码的可读性,Reflect提供了统一的操作接口,使得
Proxy拦截器更易于维护;错误处理,Reflect放返回布尔值或结果,而
直接操作对象可能抛出异常,这使得错误处理更加灵活
4.Ajax
是一种在无需重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技
术。它通过在后台与服务器交换数据,实现了网页的局部更新,提高了用户体验,
使用 XMLHttpRequest
对象Fetch API
提供了一个更现代、更灵活的方式来处理网络请求。Axios
是一个基于Promise的HTTP客户端,用于浏览器和node.js。它提供了简洁的
API来发送请求并处理响应。使用Axios可以更简洁地实现Ajax请求。
跨域:(所有的跨域必须经过server端允许和配合)
同源策略:浏览器当前网页和server的协议、域名、端口必须一致
无视同源:<img>可用于统计打点,可使用第三方统计服务
<link>可使用CDN
<script>可实现JSOP
cors _服务器设置http header
长连接:
是一种网络通信机制,通常用于实现实时数据传输和服务器推行
是指客户端与服务端之间建立的一种持久性连接,这种连接不像普通的连接请
求那样,一次交互之后即关闭,而是保持打开状态以供后续使用,通过这种方
式,服务器可以在任何时候主动向客户端发送数据,而不需要客户端频繁地发
起请求。
使用场景:聊天应用,在线游戏,股票行情,直播平台
方法:
1> webSocket:是一种专为全双工通信设计的协议,支持客户端与服务
端之间的双向数据流
2> HTTP长轮询:客户端向服务器发起一个请求,服务器在有数据可返
回的时候才响应,如果收到响应之后,立即发起下一
个请求
3> SSE:是一种单项的长连接技术,仅支持服务器向客户端推送数据,
基于HTTP协议