执行上下文与this 闭包<前端学习笔记>

执行上下文(execution context)

  • 函数执行时,会创建一个称为执行上下文的环境,分为创建和执行两个阶段。

创建阶段

  • 创建一个拥有3个属性的excutionContext对象
executionContext = {
    scopeChain: {}, // 创建作⽤域链(scope chain)
    variableObject: {}, // 初始化变量、函数、形参
    this: {} // 指定this
}

执行阶段

    1. 分配变量、函数引用、赋值
    1. 执行代码

AO

AO步骤:

  1. 创建AO(Activation Object)对象,又叫执行期上下文;
  2. 寻找形式参数和变量声明作为AO的属性名,并赋值为undefined;
  3. 传入实际参数的值;
  4. 在函数体内寻找函数声明,放入作为AO的属性,并赋值为其函数体。

GO

GO步骤:

  1. 创建GO(Global Object)对象;
  2. 寻找变量声明作为GO的属性名,并赋值为undefined;
  3. 寻找函数声明,放入作为GO的属性,并赋值为其函数体。

执行上下文栈

  • 一个全局执行上下文和多个函数执行上下文 === 执行上下文栈

作用域

  • js中有全局作用域、函数作用域、es6新增块级作用域
  • 隔离函数或者变量
  • 作用域在执行上下文创建时定义

作用域链

  • 函数嵌套另一个函数,发生作用域嵌套
  • js引擎在当前函数中无法找到某个变量,就会往上一级嵌套的作用域中寻找,直到找到该变量或者抵达全局作用域
  • 这样的链式关系被称为作用域链

闭包

  • 有权访问 另一个函数作用域中变量的函数(能够读取其他函数内部变量的函数)
  • 私有性体现在:创建多个实例,互不影响(多个实例数据独立性);延长变量生命周期体现在,同一个实例对象下闭包函数访问的变量不销毁,防抖和节流应用(单个实例数据持久性)
  1. 封装私有属性,私有环境互不干扰
// ⼯⼚⽅法
function Person() {
  // 外部无法访问,私有 
  var _attackVolume = 100;
  function attack(val){
    _attackVolume += val
  }
  return {
    add:function(){
      attack(1)
    },
    reduce:function(){
      attack(-1)
    },
    value:function(){
      return  _attackVolume 
    }

  };
}

// 拥有各自的词法环境
var person = new Person();
var person2  = new Person()

person.add()
console.log(person.value()) // 101
console.log(person2.value()) // 100

person.add()
// 延长变量生命周期
console.log(person.value()) // 102 
  1. 存储变量,延长变量生命周期
/ 封装的时候
function getListDataManager() {
    // 外层scope中定义⼀个变量
    let localData = null;
    return {
        getData() {
            // ⾥⾯的函数使⽤外层的变量,⽽且是反复使⽤
            if (localData) {
                return Promise.resolve(localData);
            }
            return fetch('xxxx')
                .then(data => localData = data.json());
        }
    };
}
// ⽤的时候
const listDataManager = getListDataManager();
//listDataManager 接收闭包函数,localData不会销毁

button.onclick = () => {
    // 每次都会去获取数据,但是有可能是获取的缓存的数据
    text.innerHTML = listDataManager.getData();
};
window.onscroll = () => {
    // 每次都会去获取数据,但是有可能是获取的缓存的数据
    text.innerHTML = listDataManager.getData();
};

this

1、对于直接调⽤的函数来说,不管函数被放在了什么地⽅,this都是window

2、对于被别⼈调⽤的函数来说,被谁点出来的,this就是谁

3、在构造函数中,类中(函数体中)出现的this.xxx=xxx中的this是当前类的⼀个实例

4、call、apply时,this是第⼀个参数。bind要优与call/apply哦,call参数多,apply参数少

5、箭头函数没有⾃⼰的this,需要看其外层的是否有函数,如果有,外层函数的this就是内部箭头函数
的this,如果没有,则this是window

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值