Redbattle
踩坑
环境
项目
配置
知识点
踩坑
环境
项目
配置
知识点
  • 浏览器/网络
  • HTML
  • CSS
  • JS
    • Vue
    • ES6
    • TS
    • 格式化上下文
    • 工程化
    • 常用 Web 坐标转换
    • 算法
    • 安全性
    • CSS 选择器
    • CSS 函数
    • CSS 属性
    • CSS @
    • CSS 过渡与动画
    • CSS 预处理器
    • knowledge
    2022-01-21

    JS

    # 原型和原型链

    • 每个对象都会在内部初始化一个属性 prototype,当访问对象的属性时,如果这个对象内部不存在这个属性,就会去 prototype 里找这个属性,这个 prototype 又会有自己的 prototype 属性,这样一直找下去就是原型链概念
    • 优先取构造函数的上属性
    • 每个函数都有 prototype 属性,除了 Function.prototype.bind(),该属性指向原型。
    • 每个对象都有proto属性,指向了创建该对象的构造函数的原型。其实这个属性指向了 prototype,但是 prototype 是内部属性,我们并不能访问到,所以使用proto来访问。
    • 对象可以通过 proto 来寻找不属于该对象的属性,proto 将对象连接起来组成了原型链。
    • 原型链的终集是 null

    # 防抖和节流

    • 防抖,触发事件后在一段时间内只执行一次,若在这段时间内再次触发则会重新计算执行时间
    • 节流,连续发生的事件在一段时间内只执行一次,节流会减少执行频率

    # es6 转 es5 的实现思路

    # call、apply、bind 的区别

    • 都可以改变指针的对象,将函数放到特定作用域中执行
    • call 函数名.call(作用域对象, 多个参数)
    • apply 函数名.apply(作用域对象, 数组参数)
    • bind 绑定作用域 函数名.bind(作用域对象, 多个参数)

    # void 0 与 undefined

    # let 与 var 区别

    • var 会全局污染,用 var 声明的变量会挂在 window 全局变量下,用 let 声明的变量则不会;两者都可以跨标签使用。
    • let 有块级作用域
    • let 在执行上下文时会有暂时性死区,不允许在声明前使用变量;var 可以在声明前使用变量,值为 undefined
    • var 允许重复声明,let 不允许重复声明

    # this 指向

    • 通常情况下指向函数的直接调用者,而非间接调用者,如果该对象没有对应属性,则不会再往上一层查找
    • 在事件中,this 指向触发这个事件的对象,特殊情况 IE 中 attachEvent 的 this 总是指向 window
    • 如果有 new 关键字,this 指向 new 出来的那个对象
    • 箭头函数没有自己的 this 如果我们在函数中引用 this,this 值取决于外部“正常的”函数。这是箭头函数的一个特性,当我们并不想要一个独立的 this,反而想从外部上下文中获取时,它很有用
    • 一个函数在声明时,可能就使用了 this,但是这个 this 只有在函数被调用时才会有值。

    # 闭包

    • 在函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用域链
    • 让这些变量始终保存在内存中,不会随着函数的结束而自动销毁,用完需要对闭包做 null 的处理手动销毁
    • 作用域链,如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,查找过程形成的链条就叫做作用域链
    • 优点:
      • 避免全局变量的污染
      • 封装对象的私有属性和方法
    • 缺点:
      • 会常驻内存,增大内存使用量
      • 使用不当会造成内存泄露

    # 混合

    # 继承

    • 构造继承,函数内使用 call、apply 调用
    • 原型继承,设置 prototype 属性

    # 模板引擎

    • 模板引擎负责组装数据,将变量模板编译成浏览器能识别的代码

    # Flux

    # 同构

    # 浅拷贝

    只拷贝第一层

    • 循环
    • es6 解构
    • Object.assign()

    # 深拷贝

    • json 转换,正则、函数、会变成{},日期会变成字符串
      • 不能序列化函数
      • 会忽略 undefined
      • 不能解决循环引用的对象
    • 递归,判断正则、日期、函数等特殊类型

    # 面向对象

    • 将对象方法封装成相互独立的模块
    • 以功能来划分

    # 面向过程

    • 分析出解决问题所需要的步骤,然后一步一步解决

    # 多线程实现

    • 单线程原因:避免 dom 渲染的冲突
    • webworker 支持多线程,但是不能操作 dom

    # 遍历(异步遍历,提前返回问题)

    • forEach(item, index, array) 类似 for 循环,没有返回值。IE 不支持,无法使用 break,continue 跳出循环,使用 return 跳出循环
    • map(item, index) 需要返回值
    • reduce((prev, item, index) => {}, initValue) 对数组中每个元素执行回调,并将累计结果返回给下一个回调
    • for...in 可以遍历对象
    • for...of

    # 模块化开发

    • 立即执行函数不暴露私有属性

    # 懒加载原理

    • 图片加载是由 src 的值引起的,当对 src 进行赋值时浏览器会请求图片资源,可以用 html5 属性 data-xxx 来保存图片路径,当需要显示图片时,再将 data-xxx 的值赋给 src,实现按需加载

    # 异步加载 js

    • defer(只支持 IE),async
    • 创建 script,插入到 dom 中,再执行 callback

    # 装饰器

    • 对类或属性方法加上前置操作
    • 实现复用

    # 异步

    • 执行顺序,一个宏任务里必须执行完所有微任务才会执行下一个宏任务,同级先微任务后宏任务
    • 宏任务:定时器、事件绑定、ajax
    • 微任务:async、await、promise

    # fetch

    • 基于 promise,支持 async/await
    • 需要进行封装
    • 只对网络请求报错,400,500 均为正常
    • 默认不会带 cookie,需要配置项。fetch(url, {credentials: 'include'})
    • 不支持超时控制。使用 setTimeout 及 promise.reject 的实现的超时控制并不能阻止请求过程继续在后台运行
    • 没有办法原生监测请求的进度

    # axios

    • 支持浏览器和 nodejs 发请求
    • 支持 promise
    • 客户端支持防 CSRF
    • 提供了一些并发请求的接口
    • 拦截请求和响应
    • 取消请求
    • 自动转换 json 数据
    • 监测请求的进度

    # 多标签页之间的通信

    • localStorage,页面 a 使用 localStorage.setItem 存储值,页面 b 监听 storage 事件
    • cookie,页面 a 存储值,页面 b 轮询 cookie 值
    • websocket,全双工通信,服务器可以主动发数据,页面 a 发送数据到服务器,服务器发送数据到页面 b
    • sharedWorker,多页面多线程

    # 判断类型

    Object.prototype.toString.call(value).slice(8, -1)
    
    • typeof
      • 对于原始类型来说,除了 null 都可以显示正确的类型
      • 对于对象来说,除了函数都会显示 object
    • instanceof
      • 可以正确的判断对象的类型,因为内部机制是通过对象 prototype 原型链判断

    # 比较运算符 ==

    • 对象/数组==字符串,会转换成字符串
    • null==undefined,与其他值不相等
    • NAN!=NAN
    • 对象/数组==数字,会先转换成字符串,然后再转换成数字
    • 剩下的都是转换成数字

    # 事件代理

    • 把原本需要绑定的事件委托给父元素,让父元素监听处理多个子元素
    • 事件代理的原理是 dom 事件冒泡,使用事件代理的好处是可以提高性能,节省内存空间,减少事件注册
    • 可以实现新增子对象是无需再次对其绑定

    # 事件

    • 事件冒泡,子元素先触发,父元素后触发
    • 时间捕获,父元素先触发,子元素后触发
    • dom 事件流,同时支持冒泡和捕获,document.addEventListener(),第三个参数 true 表示捕获,false 表示冒泡
    • 阻止冒泡,w3c 使用 stopPropagation(),IE 使用 cancelBubble = true
    • 阻止捕获,阻止事件的默认行为,w3c 中使用 preventDefault(),IE 中设置 window.event.returnValue = false

    # new 操作符

    • 1,创建一个新对象,并分配给 this 变量,同时继承该函数的原型;2,函数体执行。通常它会修改 this,为其添加新的属性和方法;3, 返回 this

      function User(name) {
        // this = {};(隐式创建)
        // 添加属性到 this
        this.name = name
        this.isAdmin = false
        // return this;(隐式返回)
      }
      
    • 在一个函数内部,我们可以使用 new.target 属性来检查它是否被使用 new 进行调用了。对于常规调用,它为 undefined,对于使用 new 的调用,则等于该函数

      function User() {
        alert(new.target)
      }
      // 不带 "new":
      User() // undefined
      // 带 "new":
      new User() // function User { ... }
      

    # ajax

    • 创建 xhr 连接
    • 设置参数,并打开连接
    • 发送请求
    • 接收请求
    • 优点
      • 异步请求提升了用户体验
      • 实现局部数据更新
    • 缺点
      • 安全问题,ajax 暴露了客户端与服务器交互细节
      • 对搜索引擎支持弱,不利于 seo

    # 内存泄露

    • 闭包使用不当,不需要的对象仍存在于内存中
    • 死循环

    # 垃圾回收

    • 在 JavaScript 引擎中有一个被称作 垃圾回收器 的东西在后台执行,它监控着所有对象的状态,并删除掉那些已经不可达的
    • 如果一个值可以通过引用链从根访问任何其他值,则认为该值是可达的。比方说,如果全局变量中有一个对象,并且该对象有一个属性引用了另一个对象,则 该 对象被认为是可达的。而且它引用的内容也是可达的
    • 几个对象相互引用,但外部没有对其任意对象的引用,这些对象也可能是不可达的,并被从内存中删除。
    • 固有的可达值的基本集合,这些值被称作 根(roots)
      • 当前执行的函数,它的局部变量和参数
      • 当前嵌套调用链上的其他函数、它们的局部变量和参数
      • 全局变量
    • 定期执行以下“垃圾回收”步骤
      • 垃圾收集器找到所有的根,并“标记”(记住)它们
      • 然后它遍历并“标记”来自它们的所有引用
      • 然后它遍历标记的对象并标记 它们的 引用。所有被遍历到的对象都会被记住,以免将来再次遍历到同一个对象
      • 如此操作,直到所有可达的(从根部)引用都被访问到
      • 没有被标记的对象都会被删除

    # AMD,Commonjs,ES6

    • AMD 是异步加载模块,允许指定回调函数
    • AMD 推荐通过返回一个对象作为模块对象
    • Commonjs 是服务器端的模块规范,加载模块是同步的,只有模块加载完成才能执行后面的操作
    • Commonjs 推荐通过 module.exports 或 exports 的属性赋值来达到暴露模块对象的目的
    • Commonjs 支持动态导入,例如 require(${path}/xx.js),导出时是值拷贝,
    • ES6 中一个模块就是一个文件,改文件内左右的变量和方法外部无法直接获取只能通过 export 输出
    • ES6 异步加载,导入导出都指向同一个内存地址

    # window.onload 和$(document).ready

    • window.onload 必须等页面内所有元素(包括图片)加载完毕后才能执行
    • $(document).ready 是 dom 结构绘制完毕后就会执行,不必等到加载完毕

    # 判断标准浏览器和 IE 浏览器

    • 标准,document.addEventListener,支持冒泡和捕获,事件类型不需要添加 on,添加多个事件正序执行
    • IE,document.attachEvent,支持冒泡,事件类型需要添加 on,添加多个事件倒序执行

    # event loop

    # 事件流

    # canvas 图片跨域

    # Map and Set(映射和集合)

    • Map 是一个带键的数据项的集合,就像一个 Object 一样。 但是它们最大的差别是 Map 允许任何类型的键(key)。它的方法和属性如下:

      • new Map() —— 创建 map。
      • map.set(key, value) —— 根据键存储值。
      • map.get(key) —— 根据键来返回值,如果 map 中不存在对应的 key,则返回 undefined。
      • map.has(key) —— 如果 key 存在则返回 true,否则返回 false。
      • map.delete(key) —— 删除指定键的值。
      • map.clear() —— 清空 map。
      • map.size —— 返回当前元素个数。
    • 对象仅支持 string/symbol 作为键。Map 还可以使用对象作为键

      // 在 Object 中,我们则无法使用对象作为键。在 Object 中使用字符串作为键是可以的,但我们无法使用另一个 Object 作为 Object 中的键
      let john = { name: 'John' }
      let ben = { name: 'Ben' }
      let visitsCountObj = {} // 尝试使用对象
      visitsCountObj[ben] = 234 // 尝试将对象 ben 用作键
      visitsCountObj[john] = 123 // 尝试将对象 john 用作键,但我们会发现使用对象 ben 作为键存下的值会被替换掉
      // 变成这样了!
      alert(visitsCountObj['[object Object]']) // 123
      // 因为 visitsCountObj 是一个对象,它会将所有 Object 键例如上面的 john 和 ben 转换为字符串 "[object Object]"
      
    • Map 使用 SameValueZero 算法来比较键是否相等。它和严格等于 === 差不多,但区别是 NaN 被看成是等于 NaN。所以 NaN 也可以被用作键。

      // 1,如果我们想从一个已有的普通对象(plain object)来创建一个 Map,那么我们可以使用内建方法 Object.entries(obj),该方法返回对象的键/值对数组,该数组格式完全按照 Map 所需的格式。
      let obj = {
        name: 'John',
        age: 30
      }
      let map = new Map(Object.entries(obj)) // Object.entries() 返回一个包含该对象所有 [key, value] 键值对的数组。
      alert(map.get('name')) // John
      
      // 2,因为 Object.fromEntries 期望得到一个可迭代对象作为参数,而不一定是数组。并且 map 的标准迭代会返回跟 map.entries() 一样的键/值对。因此,我们可以获得一个普通对象(plain object),其键/值对与 map 相同。
      let map = new Map()
      map.set('banana', 1)
      map.set('orange', 2)
      map.set('meat', 4)
      let obj = Object.fromEntries(map.entries()) // 创建一个普通对象(plain object)(*)
      // 完成了!
      // obj = { banana: 1, orange: 2, meat: 4 }
      alert(obj.orange) // 2
      
    • Set 是一个特殊的类型集合 —— “值的集合”(没有键),它的每一个值只能出现一次。

      • new Set(iterable) —— 创建一个 set,如果提供了一个 iterable 对象(通常是数组),将会从数组里面复制值到 set 中。
      • set.add(value) —— 添加一个值,返回 set 本身
      • set.delete(value) —— 删除值,如果 value 在这个方法调用的时候存在则返回 true ,否则返回 false。
      • set.has(value) —— 如果 value 在 set 中,返回 true,否则返回 false。
      • set.clear() —— 清空 set。
      • set.size —— 返回元素个数。
    最近更新
    01
    烧虾球
    05-13
    02
    二次开发
    12-20
    03
    文字展开收起
    10-17
    更多文章>
    Theme by Vdoing
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式