执行上下文

278 阅读2分钟

执行上下文: 当前代码被解析和执行的环境

全局执行上下文

只有一个,不在函数内的变量

函数执行上下文

调用函数时创建函数执行上下文

eval执行上下文

运行在eval函数中的代码

执行上下文的生命周期

创建阶段

创建变量,初始化arguments 提升函数声明和变量声明

创建作用域链

确定this的指向

执行阶段

变量赋值 执行代码

回收阶段

执行上下文出栈 ,回收变量

示例:

function foo() {
  let name = "duoduo";
  function getName() {
    return name;
  }
  return getName
}
let func = foo();
let name = func();
console.log(name)

调用foo创建函数执行上下文,创建name变量 、声明getName函数 ,返回getName的引用

在执行完let func = foo()后 foo创建的执行上下文出栈 ,一般变量也会随之销毁(name),但getName引用了name变量,变量不会销毁 相当于封装了一个私有变量

如果私有变量使用不当,会造成内存泄漏

使用完后,对func=null;回收name变量

定时器打印输出


for (var i = 0; i < 5; i++){
  setTimeout(() => {
    console.log(i)
  },i*1000)
}

输出 5 5 5 5 5

i是var声明的,是全局变量,不能生成块级作用域,每一次循环都会覆盖上一次i的值

使用函数创建作用域


for (var i = 0; i < 5; i++){
(function(i){
setTimeout(() => {
    console.log(i)
  },i*1000)
})(i)
  
}

立即执行函数生成函数作用域 保留上一次循环生成的变量i

函数作为参数

var a = 'duoduo'
function foo(){
    var a = 'foo'
    function fo(){
        console.log(a)
    }
    return fo
}

function f(p){
    var a = 'f'
    p()
}
f(foo())//foo

a是全局变量,

  1. 调用f函数,
  2. 调用foo函数 foo: 创建a变量 ,声明函数fo,返回fo的引用

f: 创建a变量,执行p函数,即执行fo函数,因为fo函数引用了一个私有变量 a ='foo',输出foo,f执行上下文出栈

防抖

//多次点击,最后一次生效
function debounce(fn, delay) {
  let timer = null;
  return function() {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => { fn.apply(this, arg) },delay)
  }
 }

节流

//有效时间内,第一次触发的有效
function throttle(fn, delay) {
  let canRun = true;
  return function () {
    if (!canRun) return;
    canRun = false;
    setTimeout(() => {
      fn.apply(this,arguments)
    },delay)
  }
 }

闭包作用:

  • 保护函数的私有变量不受外部的干扰。形成不销毁的栈内存。
  • 保存,把一些函数内的值保存下来。闭包可以实现方法和属性的私有化

参考

闭包