年后求职,这些基础你都会了吗?(更新中...)
js相关
javascript 的数据类型
基本类型
- String: 文本字符串.
- Number: 整数和浮点数.
- Boolean: 表示 真 (true) / 伪 (false) 的两个特殊值.
- Null: 表示空值.
- Undefined: 表示未定义或者不存在.
- Symbol: 表示独一无二的值, 可以保证不会与其他属性名产生冲突.
- BigInt: 能够支持比 Number 类型的范围更大的整数值类型. 应用类型 对象object
let,const,var 有什么区别
(1)块级作用域: 块作用域由 { }包括,let 和 const 具有块级作用域,var 不存在块级作用域。块级作用域解决了 ES5 中的两个问题:
- 内层变量可能覆盖外层变量
- 用来计数的循环变量泄露为全局变量
(2)变量提升: var 存在变量提升,let 和 const 不存在变量提升,即在变量只能在声明之后使用,否在会报错。
(3)给全局添加属性: 浏览器的全局对象是 window,Node 的全局对象是 global。var 声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是 let 和 const 不会。
(4)重复声明: var 声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const 和 let 不允许重复声明变量。
(5)暂时性死区: 在使用 let、const 命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用 var 声明的变量不存在暂时性死区。
(6)初始值设置: 在变量声明时,var 和 let 可以不用设置初始值。而 const 声明变量必须设置初始值。
(7)指针指向: let 和 const 都是 ES6 新增的用于创建变量的语法。 let 创建的变量是可以更改指针指向(可以重新赋值)。但 const 声明的变量是不允许改变指针的指向。
如何判断一个变量是数组
- isArray() 方法
console.log(Array.isArray(arr))
- 对象原型(通过原型链判断是否具有和数组同一原型链的顶端。)
console.log(arr.__proto__ === Array.prototype)arr.__proto__ === Array.prototype; // true
- instanceof 运算符
console.log(arr instanceof Array)arr instanceof Array; // true
- Object.prototype.toString.call()
Object.prototype.toString.call()
数组去重
- 利用Set()+Array.from()
- 利用两层循环+数组的splice方法
- 利用数组的indexOf方法\includes方法
- 利用数组的filter()+indexOf()
数组的方法
- 增
- push
- unshift
- concat
- 删
- pop
- shift
- slice
- 改
- splice
- 查
- indexOf
- includes
- find
- 排序
- reverse
- sort
- 转化
- join
- 迭代方法
- some
- every
- forEach
- filter
- map
字符串的常用方法
- 操作方法
- 增(concat)
- 删(slice、substr、substring)
- 改(toLowerCase、toUpperCase)
- 查(indexOf、chatAt、includes、startWith)
- 转换方法
- split
- 模版匹配方法
- match
- search
- replace
JavaScript 中的类型转换机制
- 显示转换(Number、parselnt、String、Boolean)
- 隐式转换
- 比较运算符
- 算术运算符
深拷贝与浅拷贝
- 基本类型数据保存在在栈内存中
- 引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中
- 浅拷贝
- Object.assign
- slice
- concat
- 深拷贝
- JSON.stringify() 弊端:会忽略
undefined、symbol和函数 - _.cloneDeep()
- JSON.stringify() 弊端:会忽略
typeof与instanceof
- typeof
- 操作符返回一个字符串,表示未经计算的操作数的类型
typeof 1 // 'number'
- instanceof
- 运算符用于检测构造函数的
prototype属性是否出现在某个实例对象的原型链上 - object instanceof constructor
- 运算符用于检测构造函数的
- 区别
typeof会返回一个变量的基本类型,instanceof返回的是一个布尔值instanceof可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型- 而
typeof也存在弊端,它虽然可以判断基础数据类型(null除外),但是引用数据类型中,除了function类型以外,其他的也无法判断 - 如果需要通用检测数据类型,可以采用
Object.prototype.toString,调用该方法,统一返回格式“[object Xxx]”的字符串
原型和原型链
- 原型:每一个构造函数都有一个
prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。 - 原型链:任何一个对象,都有原型对象,原型对象本身又是一个对象,所以原型对象也有自己的原型对象,这样一环扣一环就形成了一个链式结构,我们把这个链式结构称为:原型链。
prototype 和 __proto__ 区别是什么?
- prototype是构造函数的属性。
__proto__是每个实例都有的属性,可以访问 [[prototype]] 属性。- 实例的
__proto__与其构造函数的prototype指向的是同一个对象。
说说闭包
- 闭包就是有权访问另一个函数内部变量的函数。
- 闭包产生的原因:内部函数存在对外部函数局部变量的引用就会导致闭包。
- 闭包会造成内存泄漏
- 闭包会包含其他函数的作用域,会比其他函数占据更多的内存空间,不会在调用结束之后被垃圾回收机制回收,过度使用闭包会过度占用内存,造成内存泄漏。
ES6
箭头函数
- 相比普通函数,箭头函数有更加简洁的语法。
- 箭头函数不绑定this,会捕获其所在上下文的this,作为自己的this。
- 使用call,apply,bind并不会改变箭头函数中的this指向。
- 箭头函数是匿名函数,不能作为构造函数,不可以使用new命令,否则抛出错误。
- 箭头函数没有原型对象prototype这个属性
前端项目性能优化
- 页面加载及渲染过程的优化
- 避免多层css
- 避免频繁操作dom
- 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
- 合理使用v-if,v-for,避免频繁操作 DOM
- 图片加载优化(使用webp格式图片、设置适当的分辨率、使用雪碧图、使用占位图片)
- 事件委托,利用JS事件冒泡机制把原本需要绑定在子元素的响应事件(click、keydown……)委托给父元素,减少内存占用,减少事件注册。
- 渲染完成后的页面交互优化
- 防抖节流
promise
- Promise是异步编程的一种解决方案
- 三种状态
pending(进行中)fulfilled(已成功)rejected(已失败) - 三个实例方法
then()catch()finally() - 构造函数方法
all()race()allSettled()resolve()reject()try()
VUE相关
v-model双向绑定原理
- 通过 v-bind:value 绑定变量,每次输入内容的时候触发input事件
- 通过事件对象参数 event.target.value 获得输入的内容,并且把这个内容赋值变量
vue响应式原理
- Vue2.0实现MVVM(双向数据绑定)的原理是通过 Object.defineProperty 来劫持各个属性的setter、getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
- Vue 3.0实现响应式基于ES6的Proxy。
区别:
VUE2
- 1、基于Object.defineProperty,不具备监听数组的能力,需要重新定义数组的原型来达到响应式。
- 2、Object.defineProperty 无法检测到对象属性的添加和删除 。
- 3、由于Vue会在初始化实例时对属性执行getter/setter转化,所有属性必须在data对象上存在才能让Vue将它转换为响应式。
- 4、深度监听需要一次性递归,对性能影响比较大。
VUE3
- 1、基于Proxy和Reflect,可以原生监听数组,可以监听对象属性的添加和删除。
- 2、不需要一次性遍历data的属性,可以显著提高性能。
- 3、因为Proxy是ES6新增的属性,有些浏览器还不支持,只能兼容到IE11 。
虚拟 dom 是什么,为什么要使用虚拟 dom
diff 算法中 key 是做什么用的
用 index 做 key 会有什么问题吗,为什么不推荐使用 index 做 key
用 index 拼接一个随机字符串做 key 可以解决上述的问题吗
http相关
从输入URL到页面加载的全过程?
- URL解析
- DNS查询
- TCP连接
- http请求
- 响应请求
- 页面渲染
TCP三次握手 四次挥手
- 三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个报文。
- 客户端向服务器发送SYN包,请求建立连接。该包中包含一个随机生成的初始序列号ISN(Initial Sequence Number)。
- 服务器收到SYN包后,向客户端发送SYN+ACK包,表示同意建立连接。该包中也包含一个随机生成的序列号ISN,同时将确认序列号ACK设置为客户端的ISN+1。
- 客户端收到服务器的SYN+ACK包后,向服务器发送ACK包,表示客户端也同意建立连接。该包的序列号设置为服务器的ISN+1,确认序列号设置为服务器的ISN+1。
在三次握手完成后,TCP连接建立成功,双方可以开始进行数据传输。这个过程可以确保连接的可靠性和完整性,防止数据包的丢失或重复传输。
跨域
跨域是浏览器受同源(协议、域名、端口)策略的限制,不允许不同源的站点之间进行某些操作(如发送ajax请求,操作dom,读取cookie),如果不进行特殊配置是不能操作成功的
解决方法
- 前端通过脚手架或webpack配置devSever下的proxy选项,将/api开头的请求转发到真实服务器上。
- CORS后端设置请求头
- nginx反向代理
http 状态码都有哪些
状态码第一位数字决定了不同的响应状态,如下:
- 1 表示消息
- 2 表示成功
- 3 表示重定向
- 4 表示请求错误
- 5 表示服务器错误