美文网首页
2023-01-12

2023-01-12

作者: royluck | 来源:发表于2023-01-14 15:35 被阅读0次
  • 变量提升
  • 调用栈
  • 块级作用域
  • 作用域链和闭包

闭包 => 作用域链(词法作用域) => 调用栈(栈溢出) => 上下文(全局,函数)(变量环境,词法环境,可执行代码,外部引用outer)=> 块级作用域(词法环境)

背景:

代码块1:

// 调用栈顺序
var a = 2
function add(b,c){
  return b+c
}
function addAll(b,c){
  var d = 10
  result = add(b,c)
  return  a+result+d
}

addAll(3,6)

代码块2:

// 变量提升
var myname = "极客时间"
function showName(){
  console.log(myname); // undefined
  if(0){
   var myname = "极客邦"
  }
  console.log(myname); // undefined
}
showName()

代码块3:

// 变量提升,变量i没有销毁
function foo(){
  for (var i = 0; i < 7; i++) {
  }
  console.log(i); 
}
foo()

代码块4:

// ES6 是如何做到既要支持变量提升的特性,又要支持块级作用域的呢?
function foo(){
    var a = 1
    let b = 2
    {
      let b = 3
      var c = 4
      let d = 5
      console.log(a)
      console.log(b)
    }
    console.log(b) 
    console.log(c)
    console.log(d)
}   
foo()

代码块5:

// 作用域链:(词法作用域链)
function bar() {
    console.log(myName) // 极客时间
}
function foo() {
    var myName = "极客邦"
    bar()
}
var myName = "极客时间"
foo()

代码块6:

// 其实在每个执行上下文的变量环境中,都包含了一个外部引用,
// 用来指向外部的执行上下文,我们把这个外部引用称为 outer
function bar() {
    var myName = "极客世界"
    let test1 = 100
    if (1) {
        let myName = "Chrome浏览器"
        console.log(test) // 1
    }
}
function foo() {
    var myName = "极客邦"
    let test = 2
    {
        let test = 3
        bar()
    }
}
var myName = "极客时间"
let myAge = 10
let test = 1
foo()

代码块7:

function foo() {
    var myName = "极客时间"
    let test1 = 1
    const test2 = 2
    var innerBar = {
        getName:function(){
            console.log(test1)
            return myName
        },
        setName:function(newName){
            myName = newName
        }
    }
    return innerBar
}
var bar = foo()
bar.setName("极客邦")
bar.getName()
console.log(bar.getName())
WeChat06c38c6f237ee19bee668ed1febe23eb.png
变量提升 :

变量定义由 变量声明变量赋值组成
如:var myname = '极客时间'
相当于:
var myname // 声明部分
myname = '极客时间' // 赋值部分

  • 变量声明:
var myname    // 声明部分
  • 函数声明:
function foo(){
  console.log('foo')
}
  • 所谓的变量提升,是指在 JavaScript 代码执行过程中,JavaScript 引擎把变量的声明部分和函数的声明部分提升到代码开头的“行为”。变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的 undefined。

  • 从概念的字面意义上来看,“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,正如我们所模拟的那样。但,并不准确。实际上变量和函数声明在代码里的位置是不会改变的,而且是在编译阶段被 JavaScript 引擎放入内存中。

JavaScript 代码的执行流程:

一段 JavaScript 代码在执行之前需要被 JavaScript 引擎编译,编译完成之后,才会进入执行阶段。大致流程你可以参考下图:


JavaScript 代码的执行流程
  1. 编译阶段


    一段代码,经过编译后,会生成两部分内容:执行上下文(Execution context)和 可执行代码。
  2. 执行阶段
    JavaScript 引擎开始执行“可执行代码”,按照顺序一行一行地执行。

调用栈 :

JavaScript 引擎是利用栈的这种结构来管理执行上下文的。在执行上下文创建好后,JavaScript 引擎会将执行上下文压入栈中,通常把这种用来管理执行上下文的栈称为执行上下文栈,又称调用栈。

image.png
块级作用域 :

作用域 是指在程序中定义变量的区域,该位置决定了变量的生命周期。通俗地理解,作用域就是变量与函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。

在 ES6 之前,ES 的作用域只有两种:全局作用域和函数作用域。

变量提升所带来的问题:

1、变量容易在不被察觉的情况下被覆盖掉;
2、本应销毁的变量没有被销毁;

image.png
image.png

其实,在词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出,这就是词法环境的结构。


作用域链和闭包:
作用域链:

词法作用域就是指作用域是由代码中函数声明的位置来决定的,所以词法作用域是静态的作用域,通过它就能够预测代码在执行过程中如何查找标识符。

闭包:

在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。比如外部函数是 foo,那么这些变量的集合就称为 foo 函数的闭包。

代码块7

相关文章

  • PaddleNLP开源UTC通用文本分类技术,斩获ZeroCLU

    飞桨PaddlePaddle 2023-01-12 20:02 发表于湖北 针对产业级分类场景中任务多样、数据稀缺...

  • 认识自我的三个层次

    中原焦点团队 坚持分享1638天 2023-01-12 在孩子成长过程中,培养孩子认识自我非常重要。那么,我们...

  • 马拉松会议

    2023-01-12 阴雨 周四 这世上最无语的事情应该就是开会了,尤其是那种马拉松式的会议。今天我就...

  • 【日更105】读《如何阅读一本书》之辅助阅读

    2023-01-12 “内在阅读”,是指阅读书籍本身 “外在阅读”,是指借助其他一些书籍来阅读一本书。任何辅助阅读...

  • 和孩子的对话

    幸福日志2023-01-12 周四 阴霾 睡前夜谈,和恩仔谈起进退,有时候我会对他说“退一步海阔天空”,有时候又必...

  • 2023-01-12

    “好好沟通”是一句有道理的废话,虽然都知道可以用它来解决许多问题,但如何利用好它,本身就是一个难题。 假如我和她之...

  • 2023-01-12

    1、不要失望,甚至对你并不感到失望这一点也不要失望,恰恰在似乎一切都完了的时候,新的力量来临,给你以支柱,而这正表...

  • 2023-01-12

    今天开车出去办事,在两个红绿灯处都堵车,原因是前面撞车了。 岁末年尾,人们事情多,开车急急忙忙,事...

  • 2023-01-12

    今天休息,但定了早晨七点半的闹钟,因为要代boss去参加“万象汇2022年度租户大会暨颁奖典礼”,九点开始。 心里...

  • 2023-01-12

    人一辈子都在高潮——低潮中浮沉,惟有庸碌的人,生活才如死水一般;或者要有极高的修养,才能廓然无果,真正的解脱。只要...

网友评论

      本文标题:2023-01-12

      本文链接:https://www.haomeiwen.com/subject/uzwbcdtx.html