Skip to content

js

JS由哪三部分组成

ECMAScript、BOM、DOM

内置对象

String、Number、Boolean、Array、Date、RegExp、Object、Math、JSON、Error

数组的常用方法

forEach、map、filter、reduce、reduceRight、some、every、indexOf、lastIndexOf、concat、slice、splice、join、sort、reverse、push、pop、shift、unshift

数据类型检测

  • typeof
  • instanceof
  • Object.prototype.toString.call

闭包

在函数内部,可以访问函数外的变量

  • 重复利用变量
  • 不会全局污染
  • 存在内存当中,提升性能
js
function fn(x) {
    return function () {
        console.log(' =====', x)
    }
}

const y = fn('abcd')

内存泄露

已经分配地址的对象,长时间占用或者无法清除导致

事件委托

利用事件冒泡实现,把子元素的事件委托给父元素,减少事件监听,提升性能

阻止事件冒泡,event.stopPropagation()

基本、引用数据类型(存放堆栈的不同)

  • Number、String、Boolean、Null、undefined、Symbol
  • Object、Array、Function

原型链

构造函数的实例共享属性和方法

js
class Person {
    sayName = function () {
        console.log('this is function sayName')
    }
}

const p = new Person()
console.log(' =====', p.__proto__ === Person.prototype)

__proto__可以理解成一个指针(实例对象当中的一个属性),指向原型对象(构造函数的原型prototype)

一个实例对象在调用属性/方法的时候,执行过程:实例本身--> 构造函数的原型 --> 原型的原型

new做了什么

  • 创建空对象
  • 空对象的构造函数通过原型链进行连接
  • 把构造函数的this绑定到空对象
  • 根据构造函数返回类型判断
    • 值类型 --> 返回对象
    • 引用类型 --> 返回该引用类型
js
function newFun(Fun, ...args) {
    let newObj = {}
    newObj.__proto__ = Fun.prototype
    const result = Fun.apply(newObj, args)
    return result instanceof Object ? result : newObj
}

function Person(name) {
    this.name = name
}

Person.prototype.sayName = function () {
    console.log(this.name)
}

const p = newFun(Person, 'abc')
p.sayName()
console.log(' =====', p)

继承

  • 原型链
  • 构造函数
  • 组合式
  • class

js设计原理

  • js引擎(V8引擎)
  • 运行上下文
  • 调用栈
  • 事件循环
  • 回调

this指向

  • 全局this、普通函数、匿名函数都指向window
  • apply、call、bind改变了的this指向
  • 箭头函数看外层是否改变了this,否则指向window
  • 非箭头函数,this指向最后调用它的对象
  • new改变this的指向

script标签 async defer区别

未指定直接运行js

  • async 加载DOM树的时候,同时执行js
  • defer 加载DOM树的时候,等DOM树加载完毕后,再执行js

setTimeout、setInterval最小执行时间

  • 4ms
  • 10ms

ES新特性

  • 块级作用域
  • class
  • set/map
  • 解构
  • async/await
  • 数组的新API
  • 扩展运算符
  • 模块化
  • Promise
  • 箭头函数
  • 函数参数默认值

apply、call、bind区别

都是用来改变this指向和函数调用

  • call 传一个参数列表,call方法和apply方法调用一致,只是传参不同,其中call的性能更好,
  • apply 传一个数组
  • bind 传参不会立即执行,会返回一个改变this指向的函数,这个函数还可以继续传参 bind()()

递归当中的问题

在递归当中,需要指定对应的终止条件(return)避免栈溢出

深拷贝

  • JSON.parse(JSON.stringify(obj))
  • 扩展运算符
  • 递归+遍历

事件循环

  • 主线程
  • 执行栈
  • 任务队列
  • 宏任务
  • 微任务

主线程执行同步任务,然后执行任务队列当中的任务(并且在这里微任务会在宏任务之前执行),循环反复

Ajax

  • 创建XmlHttpRequest对象
  • xhr.open()建立连接
  • xhr.send()发送请求
  • 接收响应
  • 渲染

get、post区别

  • 安全性
  • 获取/提交
  • 缓存方式
  • 请求退回,get无影响,post会重新提交
  • 浏览记录
  • get参数只能url编码、post可以传文件等其他格式

Promise内部原理

Promise是用来解决回调地狱问题的

  • pendding 初始化
  • fulfilled 成功
  • rejected 失败

其中当使用了Promise之后,是无法取消的,如果没有给Promise设置回调,那么其内部的错误无法反馈到外部

Promise、async、await区别

都是用于处理异步请求,分别在ES6和ES7被加入,其中async、await也是基于Promise进行实现的

  • Promise通过then、catch捕获异常、并且Promise是链式调用、不方便维护
  • async和await是通过try、catch捕获异常,让异步代码看起来和同步一样,易于维护

Promise 的方法

reject resole catch all

  • allSettled在其中一个promise返回错误时还可以继续等待结果
  • race 接收一个数组 得到最快返回的 这是一个新的promise
  • any 只要有一个reject就会得到一个失败的promise,但是会等全部promise执行完

游览器的存储方式

  • cookie
    • 兼容好,请求头会自动携带,
    • 存储小,使用麻烦
  • localStorage
    • 操作方便,永久存储,兼容好
    • 值的类型被限定,并且在隐私模式下不可读取,不能进行爬虫
  • sessionStorage
    • 会话级的,页面关闭后失效
  • indexedDB
    • 键值存储,可快速读取

token存localStorage、cookie的区别

  • localStorage 后续请求发送都需要手动添加token
  • cookie 会自动发送token,不能跨域

token登录流程

  • 请求登录
  • 服务端验证,下发token
  • 前端存储token
  • 后续请求携带token
  • 服务端验证token
  • 响应

页面渲染流程

  • DNS解析
  • 建立TCP连接
  • 发送HTTP请求
  • 服务器响应
  • 页面渲染
    • 获取HTML、CSS
    • 把HTML解析成DOM树、把CSS解析成样式表CSSOM树
    • DOM+CSSOM树生成渲染树
    • 布局 把渲染树进行渲染
  • 断开TCP连接

DOM树和渲染树的区别

  • DOM树和HTML标签一一对应,包含了head和隐藏元素
  • 渲染树不包含head和隐藏元素

精灵图与Base64

  • 精灵图:把图片整合到一张图片中,减少HTTP请求次数,提升性能
  • Base64:将图片转换成字符串,然后通过url的形式进行展示

svg (Xml语法格式的图像)

  • 可直接插入页面,是DOM树的一部分
  • 可作为文件进行引入 <img src="xxx.svg" />
  • 可转成base64引入

JWT

json web token

  • 获取后端响应的JWT(token)携带了用户信息
  • HTTP请求头携带Authorization
  • 后端解析token校验
  • 解析出用户信息做后续逻辑操作

npm底层环境原理

node project manager

  • 网站 npmjs.com
  • 注册表 用来管理所有的包
  • 命令行工具

HTTP请求头与响应头的区别

请求头

  • Accept 支持的类型
  • Host 主机地址
  • User-Agent 浏览器信息
  • Referer 来源
  • Cookie 认证信息
  • Date 时间
  • connection 连接方式
  • x-request-with 与服务器通信的协议

响应头

  • Content-Type 内容类型
  • Server 服务器信息
  • Location 服务器地址
  • Refresh 重定向

缓存类型

  • 强缓存(本地缓存)不发送请求,直接从缓存中读取
  • 弱缓存(协商缓存)发送请求判断是否使用缓存,服务器返回304,从缓存中读取

同源策略

协议+域名+端口(一致表示同源)

其中:img、link、script标签是允许跨域的

解决跨域的方案

  • JSONP
  • CORS 后端允许跨域
  • nginx反向代理
  • webSocket

防抖、节流

  • 防抖:在 n 时间以后触发函数,若时间未到再次被触发,则会重置执行函数的倒计时。(多用于搜索框优化)
  • 节流:在 n 时间内无论触发多少次函数,只会执行第一次触发。从而稀释出发频率。 (多用于按钮,以及页面滚动)

后端接口无数据响应

  • 填充默认数据
  • if判断数据是否为空

无感登录(无感刷新token)

在token过期的时候,不需要用户操作,后台自动刷新token

  • 在响应器当中拦截,判断token返回过期之后,重新调用获取token
  • 后端返回过期时间,前端根据超时时间判断是否过期,何时发送请求获取token
  • 前端定时请求获取token

大文件上传

  • 分片上传
  • 断点续传
    • 服务端返回,从哪里重新开始上传,在浏览器端判断

函数中定义变量,返回一个立即执行函数,外部怎么修改这个变量

可以通过返回一个对象,该对象包含一个用于修改变量的方法

js
function myFunction() {
    let myVar = 0;

    return {
        getVar: function () {
            return myVar;
        },
        setVar: function (value) {
            myVar = value;
        }
    };
}

const obj = myFunction();
obj.setVar(10);

实现const

  • object.freeze({})
  • Object.defineProperty
js
Object.defineProperty(obj, 'value', {
    value: value,
    writable: false,
    enumerable: true,
    configurable: false
});

实现instanceof

js
function myInstanceOf(obj, constructor) {
    let prototype = Object.getPrototypeOf(obj);
    while (prototype !== null) {
        if (prototype === constructor.prototype) {
            return true;
        }
        prototype = Object.getPrototypeOf(prototype);
    }
    return false
}

By Modify.