js作用域、作用域链、闭包

作用域

1.javascript局部作用域

变量在函数内部声明,变量为局部作用域.

//局部变量:只能在函数内部访问
function test(){
   var name='zdb'
}
console.log(name) //undefined

2.javascript全局变量

//全局变量:函数内部外部都可以访问
var name='zdb'
function test(){
  console.log(name) //zdb
}
test()

3.隐式声明

//函数内部没有使用var 声明的变量 会默认认为是全局变量
function test(){
   name='zdb'
}
console.log(name) //zdb

[[scope]]作用域

每个javascript函数都是一个对象,对象中有的属性可以访问,有的属性仅供javascript引擎存取[[scope]]就是其中一个,指的是作用域,其中存储了运行期上下文集合.

运行期上下文

当函数执行时,会创建一个称为执行期上下文的内部对象.一个执行期上下文定义了一个执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的上下文被销毁.

  • 代码示例
var  glob=1000
function test(){
   console.log('test')
}

1.test函数声明时,scope[0]里指向全局GO对象

image.png
var  glob=1000
function test(){
   var  b=123
   console.log(b) //123
}
test()

2.test函数执行时会创建一个独一无二的执行期上下文AO,形成作用域链,AO会默认排到作用域链的最顶端.

image.png
  1. test执行完毕会默认销毁自己的执行上下文AO,回到初始定义状态.
image.png
  • 代码示例
function a(){
    function b(){
        var bb=234
        aa=0
    }
    var aa=123;
    b();
    console.log(aa) //0
}
a()

1.a定义状态,scope[0]里指向全局GO对象

image.png

2.a函数执行创建自己的AO,会将自己的AO排到作用域链的最顶端,a执行的时候,定义b函数,b函数定义会自带a函数的AO、GO ,b函数与a函数,指向的是同一个AO.

image.png

3.a函数执行过程中,b函数定义被执行,b函数执行创建自己的AO,执行完毕销毁自己的AO,b函数里面查找aa变量统一在作用域链依次由上向下查找,自己的AO里没有找到aa变量,修改的变量aa是a函数AO对象的值.这时aa已被改为0,再次读取aa变量 值为0.

image.png

4.b函数执行完毕会销毁自己的AO回到初始状态,其次a函数执行完毕会销毁自己的AO回到初始状态.

  • 闭包

一个内层函数中访问到其外层函数的作用域.

  • 代码示例
function a(){
    function b(){
        var bbb=234;
        console.log(aaa) //123
    }
    var aaa=123;
    return b;
}
var glob=100;
var demo=a();
demo()

1.a被执行,b被定义时 并将b保存出到函数外部.

image.png

2.b函数执行时a函数已执行完毕,a函数会取消指向自己AO的引用,但是b函数还指向a函数的AO引用,b函数在自己执行时会创建自己的AO会默认排到作用域链的最顶端[0]位,b函数读取aaa变量默认会从作用域顶端依次向下查找,这时自己AO没有aaa,a函数的AO里有aaa所以查找结果为123

image.png
  • 立即执行函数

可以让函数在创建后立即执行.

  • 写法一
(function(){
    console.log(1)
}())
  • 写法二
(function(){
    console.log(2)
})()
  • 被执行符号执行的表达式,函数名没有意义
//此处函数名没有意义
(function test(){console.log(1)}())
console.log(test)  // test is not defined

let test=function demo(){
    console.log(11111)
}()
console.log(demo)// demo is not defined
  • 只有执行表达式才能被执行符号执行
function test(){
    console.log(1111)
}() //error:Unexpected token ')'

//执行符号 * /例外
+ function test(){
    console.log(1111)
}()  //1111

- function test(){
    console.log(1111)
}()  //1111

! function test(){
    console.log(1111)
}()  //1111
  • 如果调用传参不会执行,也不会报错
function test(a,b){
    console.log(a+b)
}(1,4)

//系统会识别成
function test(a,b){
    console.log(a+b)
}
(1,4)
  • 立即执行函数应用场景
//可以套用作用域链,梳理逻辑
function test(){
    var arr=[];
    for(var i=0;i<10;i++){
        arr[i]=function(){
            console.log(i) //10个10
        }
    }
    return arr
}
let myArr=test();
for(var i=0;i

你可能感兴趣的:(js作用域、作用域链、闭包)