• js作用域 吴小明


    js的概念:

      js是解释性语言。解释性:逐行解析,逐行执行

    js的组成:

      语法核心ECMAScript

      文档对象模型DOM

      浏览器对象模型BOM

    所谓的渲染页面,就是返回一堆html,html和DOM的区别?

      html是一段字符串,浏览器解析html生成一个树型结构的文档对象,以方便js操作,这个就是DOM

    js的特点:

      单线程,同一时间只能做同一事情。

      作为浏览器脚本语言,js的主要用途是与用户交互和操作DOM,这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,js有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,此时浏览器该以哪个线程为准?

    js执行过程:

      语法解析

      预编译

      解释执行

    预编译:

      在内存中开辟一块空间,用来存放变量和函数。

      作用:消除一些歧义

      预编译发生在函数执行前,也就是说,函数执行时预编译已经结束

    全局对象(Global Object):

      在浏览器环境中,js引擎会整合script标签中的内容,产生window对象,这个window对象就是全局对象

        啥叫整合?

        

      在node环境中,会产生global对象

    全局变量:

      在script中声明的变量为全局变量,全局变量(由var声明的)会挂载到window对象上,作为window对象的一个属性存在

        

    全局函数:

      在script中声明的函数为全局函数,全局函数会作为window对象的方法存在

        

    活动对象(Activation Object):

      也叫激活对象,在函数被调用时产生,用来保存当前函数内部的执行环境(执行期上下文)

        

      在函数调用结束时销毁

        

    局部变量:

      在函数内部声明的变量是局部变量,局部变量作为ao对象的属性存在

        

      如何理解局部:

        在函数a的外部不能访问变量i,变量i只能在函数a内部使用,这就是作用域的由来

        如果不执行函数,就不会产生ao对象,就不会存在属性i

        如果执行函数,就会产生ao对象,并将变量i作为ao对象的属性

        函数执行完后,ao对象被销毁,属性i随之被销毁

    局部函数:

      在函数内部声明的函数叫局部函数,局部函数作为ao对象的方法存在

        

    全局预编译:

      流程:

        查找变量声明,作为GO对象的属性名,值为undefined

        查找函数声明,作为GO对象的方法名,值为function

      变量声明:

          var a // 变量声明
          var b = 100 // 变量声明+变量赋值

      函数声明:

          function a() {} // 函数声明
          var b = function() {} // 函数表达式,不是函数声明

      全局预编译的过程:

          console.log(a)
          var a = 100
          console.log(a)
          function a() {
            console.log(100)
          }
          console.log(a)
          a()
          /*
            全局预编译的过程:
              1、js引擎整合所有的script标签,产生window对象
              2、查找变量的声明,将变量a作为window的属性名,属性值为undefined
              3、查找函数的声明,将函数a作为window的属性名,属性值为function
    
            全局预编译结束后,代码从上到下依次执行
          */

      结论:如果存在同名的变量和函数,函数的优先级更高

    函数预编译:

      流程:

        在函数被调用时,为当前函数产生AO对象

        查找形参和变量作为AO对象的属性名,值为undefined

        使用实参的值改变形参的值

        查找函数声明作为AO对象的属性名,值为function

      全局预编译与函数预编译的过程:

          function a(test) {
            var i = 100
            function b() {
              console.log(200)
            }
            b()
          }
          a('test')
          /*
            全局预编译的过程:
              1、js引擎整合所有的script标签,产生window对象
              GO:
                (1)查找变量的声明,这里没有声明全局变量
                (2)查找函数的声明,将函数a作为window对象的属性名,值为undefined
            全局预编译结束,自上而下执行代码
    
            调用函数a,产生函数a的AO对象,开始函数预编译:
              AO:
                (1)查找形参test、变量i作为AO对象的属性名,值为undefined
                (2)实参'test'赋值给test
                (3)查找局部函数b,b作为AO对象的属性名,值为undefined
              函数a的预编译结束(函数b也会产生b的AO,这里省略不做研究),函数a内自上而下执行代码
              i = 100
          */

        

    优先级:局部函数>实参>形参/局部变量

          // 形参和局部变量重名,以实参为准
          function a(i) {
            var i
            console.log(i) // 100
          }
          a(100)
    
          // 形参和局部函数重名,以局部函数为准
          function b(i) {
            console.log(i) // function
            function i() {}
          }
          b(100)

    作用域和作用域链:

    作用域:

      全局作用域:

        编写在script标签中的js代码,都是全局作用域。或者是单独的js文件中的代码

        全局作用域在页面打开时创建,在页面关闭时销毁

        全局作用域中有一个全局对象window,代表一个浏览器窗口,由浏览器创建,可以直接使用

      局部作用域(函数作用域):

        在函数内部的就是局部作用域

        函数被调用时创建局部作用域,函数执行完毕后,局部作用域被销毁(闭包除外)

        每调用一次函数就会创建一个新的局部作用域,它们之间是相互独立的

     作用域链:

      在js中,函数存在一个隐式属性[[Scopes]],这个属性用来保存当前函数执行时的上下文,由于在数据结构上是链式的,也被称作为作用域链。可以将它理解为一个数组

       [[Scopes]]:

        在函数声明时产生,在函数调用时更新

        记录当前函数的执行环境

        在函数被调用时,将该函数的AO对象压入到[[Scopes]]中

          function a() {
            console.dir(a)
            function b() {
              console.dir(b)
              function c() {
                console.dir(c)
              }
              c()
            }
            b()
          }
          a()

        

         

    作用域链的作用:

      在访问变量或函数时,会在作用域链上向上查找,最直观的表现是:内部函数可以使用外部函数声明的变量

    简单数据类型和复杂数据类型在内存中的存储方式:

      

    栈内存:

      1、提供一个供js代码自上而下执行的环境,代码都是在栈中执行的

      2、由于基本数据类型值比较简单,它们都是直接在栈内存中开辟一个位置把值直接存储进去。当栈内存被销毁,存储的那些值也都跟着销毁了

    堆内存:

      1、引用值对应的空间,用来存储引用类型的值,对象以键值对形式,函数以代码字符串形式。当前堆内存被销毁,那么这个引用值彻底没了

        堆内存的释放:

          当堆内存中没有被任何变量所使用,垃圾回收机制就会将不被占用的内存销毁

          xxx = null  通过空对象指针,可以让原始变量谁都不指向,那么原来被占用的堆内存就空下来了

    写var和不写的区别:

          /*
            通过var声明的变量,其实就是为window对象添加了一个不可以配置的属性
            不加var声明的变量,其实就是为window对象添加了一个可以配置的属性
          */
          var logo = 'volvo'
          console.log(logo)
          console.log(window.logo)
          console.log('logo' in window) // true,用var声明变量实际上就是给window对象添加了一个属性
    
          delete window.logo // delete删除不了那些可配置属性为false的属性,当logo使用var声明时,这句代码无效
          console.log(window.logo) // volvo

      1、局部作用域中变量声明加var时,函数内读取的logo是函数中的logo

          var logo = 'volvo'
          function test() {
            console.log(logo) // 找到自己的logo,预编译机制将logo变量提升,这里打印undefined
            console.log(window.logo) // 全局作用域下logo为volvo
            var logo = '未知品牌' // 声明变量并赋值为“未知变量”
          }
          test()
          console.log(logo) // volvo

      2、局部作用域操作变量不加var时,此时函数中读取的logo是全局作用域下的logo,函数中对logo赋值是对全局中的log进行赋值

          var logo = 'volvo'
          function test() {
            console.log(logo) // 函数执行时,向上查找,logo为volvo
            console.log(window.logo) // volvo
            logo = '未知品牌' // 对window.logo重新赋值
          }
          test()
          console.log(logo) // 未知品牌

      3、严格模式下,对未声明的变量进行赋值会报错

      4、var a = b = 10  写var会进行预编译,提前访问值为undefined。不写var不会进行预编译,提前访问会报错。如果访问window.a和window.b都是undefined,因为访问一个对象上不存在的属性时值都为undefined

          console.log(a) // undefined
          console.log(b) // 报错
          var a = b = 10 // 等价于var a = 10; b = 10
  • 相关阅读:
    查看windows下指定的端口是否开放
    网易云音乐评论爬虫:爬取歌曲的全部评论
    用 Python 玩转 GitHub 的贡献板
    用python实现linux口令破解
    Python 音频数据扩充的技巧
    教你使用python+Opencv完成人脸解锁
    opencv+Python特征检测及K-最近邻匹配
    opencv+python 统计及绘制直方图
    学会用这个工具做分析,1年积累3年工作经验
    15分钟,教你用Python爬网站数据,并用BI可视化分析!
  • 原文地址:https://www.cnblogs.com/wuqilang/p/15866253.html
Copyright © 2020-2023  润新知