JS原型链、闭包

2019/10/14 js

# 原型链

  • 概念:JS里面的对象可能会有父对象,父对象还会有父对象
  • 根本:原型链的根本是继承
    对象中几乎都有一个 __proto__ 属性,指向他的父对象,可以实现让该对象访问到父对象种的相关属性
  • 根对象:Object.prototype
    let arr = [1, 3, 5]
    // arr.__proto__: Array.prototype
    // arr.__proto__.__proto__: 根对象
    function Animal () {}
    let cat = new Animal()
    // cat.__proto__: Animal.prototype
    // cat.__proto__.__proto__: 根对象
    
    1
    2
    3
    4
    5
    6
    7

# 闭包

# 变量作用域

  • 概念:一个变量可以使用的范围叫做变量作用域
  • 全局作用域:最外层的作用域
  • 独立作用域:JS中还可以通过函数创建出一个独立的作用域,其中函数可以嵌套,所以作用域也可以嵌套
let age = 18 // 全局变量
function f1 () {
  let name = 'haha' // f1函数内部的变量 
}
1
2
3
4

变量的声名和赋值是在两个不同时期的
fn函数执行的时候,首先找到函数内部所有的变量、函数声名,把他们放在作用域中,给变量一个初始值undefined
然后逐条执行代码,在执行代码的过程中,如果有赋值语句,对变量进行赋值

# 作用域链

  • 概念:由于作用域是相对于变量而言的,而如果存在多级作用域,那变量的查找过程就叫做变量的作用域链
  • 意义:查找变量
    • 确定变量来自于那个作用域
    • 变量是否可以访问
  • 难点:看上一级作用域,不是看函数在哪里调用,而是看函数在哪里编写,因为这种特别,我们通常会把作用域说成是词法作用域

查看当前作用域,如果当前作用域声名了这个变量,就确定结果,然后查找当前作用域的上级作用域,也就是当前函数的上级函数,看看上级函数中有没有声名,直到全局作用域为止,如果全局作用域中也没有,我们就认为这个变量没声明

# 闭包的产生

function fn() {
  var a = 5
  return function () {
    a++
  }
}

var f1 = fn()
f1()
f1()
f1()
1
2
3
4
5
6
7
8
9
10
11
  • 一般认为函数执行完毕,变量就会释放
  • 但是由于js引擎发现匿名函数要使用a变量,所以a变量并不能得到释放,而是把a变量放在匿名函数可以访问到的地方去了。
  • a变量存在于f1函数可以访问到的地方,此时a变量只能被f1函数访问
  • 再次执行fn会初始化一个新的a变量
  • 可以通过 f1 = null 来释放f1里面保存的a变量

# 闭包的应用场景

  • 模块化
  • 防止变量被破坏
此生不换
青鸟飞鱼