Skip to content
On this page

深拷贝和浅拷贝

  1. 浅拷贝:把一个对象里面的所有的属性值和方法都复制给另一个对象
    浅拷贝的方式
    Object.assign('要拷贝给谁','拷贝的是哪一个对象')
    Array.prototype.slice()
    扩展运算符
  2. 深拷贝:开辟一个新的栈,两个对象属性完全相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
    深拷贝的方式
    • JSON.parse(JSON.stringify('要拷贝的对象')) 有一个缺陷会忽略 undefined 和函数
    • 递归循环 如果数据自己引用自己 拷贝会进入死循环 解决方法:使用 map 数据, map 的 key 可以是任意数据类型
    • loadsh 的.cloneDeep()
  3. 使用扩展运算符 当拷贝对象的属性值对应的都是简单的基本类型数据,可以理解为深拷贝。当拷贝对象的属性对应的值为数组或对象等引用类型时,为浅拷贝。

闭包

  1. 什么是闭包:在内层函数访问它外层函数的作用域
  2. 内层函数访问外层函数的变量就会形成闭包
  3. 原理:利用作用域链的特性,先在当前作用域访问数据,如果访问不到,向父级访问,父级没有继续向上一层一层找,一直找到全局
  4. 作用:数据私有化,防止污染全局
  5. 缺点:可能会造成内存泄漏,解决方法:在退出函数之前,将不使用的局部变量全部删除

Promise

  1. 使异步操作更加容易,将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
  2. 三种状态:pending(等待,进行中) resolved(成功) rejected(失败)
  3. promise 的状态一旦由等待 pending 变为成功 resolved 或者失败 rejected。那么当前 promise 被标记为完成,后面则不会再次改变该状态。
  1. localStorage 和 sessionStorage 存储大小 5MB,cookie 存储大小是 4kb
  2. locaStorage 数据得手动删除 sessionStorage 关闭页面或浏览器清除数据; cookie:如果在浏览器端生成 cookie 默认是关闭浏览器后失效
  3. localStorage 和 sessionStorage 只在浏览器中保存,不参与和服务器的通信; cookie:与服务器通信的时候每次都会携带在 HTTP 头中 如果使用 cookie 保存过多数据都会带来性能问题

垃圾回收

  1. 引用计数:计算当前内存被引用的次数,被引用一次计数+1.不被引用一次计数-1,当计数为 0,该内存释放回收
  2. 标记清除:通过根节点,标记所有从根节点开始的能够访问到的对象,未被标记得对象就是未被全局引用的垃圾对象,最终清除所有未被标记的对象

静态成员和实例成员

  1. 静态成员:类的属性
  2. 实例成员:实例对象的属性

作用域链

  • 在某个函数作用域中,要使用一个变量的时候,会先看自己有没有,如果没有就向外面一层层找直到找到全局作用域,如果还没有就报错

如何检测一个数据是数组

  1. 变量 instanceof Array
  2. Array.isArray(变量)
  3. Object.prototype.toString.call(变量)

继承

  1. 原型链继承 (只能实现原型上方法的继承) Father.prototype.方法名 = function(){} Son.prototype = new Father() (引用类型值的原型属性会被所有的实例共享)
  2. 借用构造函数继承 (只能实现属性的继承) function Son(name) {Father.call(this,name)} 将 Father 类的 this 指向 Son
  3. 组合继承 = 原型链+借用构造函数 (原型链继承+借用构造函数继承,可以继承方法也可以继承属性,但是属性继承了两次)
  4. 寄生组合继承 Son.prototype = Object.create(Father.prototype)(解决了组合继承的缺陷)
  5. es6 的继承 extends

原型链的理解

  1. 访问实例的属性或方法的时候,会先看自己有没有,实例没有就通过__proto__找原型对象也就是对应的构造函数的 prototype,如果还没有就通过构造函数的 prototype.__proto__找 Object.prototype,如果还没有,最后就是 null 了

构造函数,实例和原型对象的三角关系

  1. 首先创建一个构造函数 构造函数通过 new 创建一个实例
  2. 将实例的__proto__指向了构造函数的 prototype
  3. 把构造函数的 this 指向这个实例 给这个实例添加属性和方法
  4. 此时实例就可以通过__proto__访问到构造函数的 prototype

new 的过程

  1. 在内存中创建一个空对象
  2. 将该空对象的__proto__指向了构造函数的 prototype
  3. 将 new 后面的构造函数的 this 指向 new 出来的空对象
  4. 把构造函数的属性和方法给这个对象
  5. 在构造函数内部返回实例化对象

this 的指向

  1. 全局 this 指向 window 严格模式指向 undefined
  2. 对象中的 this 指向这个对象
  3. 构造函数中 this 指向实例
  4. 事件绑定中 this 指向 DOM 元素 btn.onclick = cb 中 this 指向 btn
  5. 定时器中 this 指向 window
  6. 对象中的方法中定义的函数 this 指向 window

改变 this 指向

  1. call() apply() bind()方法都可以改变 this 指向 区别

  2. Call,apply 会立即调用,bind 不会立即调用,返回一个新的函数

  3. apply 只有两个参数,第一个参数是调用者,第二个参数是函数的实参

  4. 使用场景

  • call 可以用于借用构造函数继承的实现
  • apply 可以用来求最大值

跨域

  1. 浏览器存在一个同源策略,必须域名、IP、端口三个全部一样才能同源,否则就是跨域,ajax 默认情况拿跨域的数据会报错,这个现象是浏览器的安全策略导致

解决跨域的问题的方案

  1. jsonp 原理利用 script 标签的 src 属性去请求数据 属于 Js 请求没有跨域这个问题,但是 src 只能去发起请求 所有 jsonP 只支持 get 请求, 服务器要返回给前端一个函数的调用,把数据放在实参里面,前端准备好一个全局函数,函数名字要和后台数据函数名一致(只支持 get 请求)
  2. cors(类似白名单) 后端人员再接口配置 cors
  3. 反向代理 开发的时候在 vue.config.js 中设置 proxy

什么是模块化

  • 不把所有的 js 代码放在一个文件中,因为难以维护,变量命易起冲突,代码尽量一个功能一个 js 文件,一个文件最好要有一个自己的作用域,不会和别的文件起冲突,文件最终要合在一起,所以还有一个导入,这就是模块化

学过那些模块化的方案

ES6 的模块化规范
Export default export 导出
import 导入

数组的方法

  1. es3 (1) Join
    (2) Sort
    (3) Reverse
    (4) Concat
    (5) Push
    (6) Pop
    (7) Splice
    (8) Shift
    (9) Unshift
    (10) slice
  2. es5 (1) Map
    (2) Filter
    (3) Reduce 一堆数据加在一起
    (4) Some
    (5) Every
  3. es6 (1) Find
    (2) findIndex