js中,函数的闭包、做用域跟[[Scopes]]的关系

[[Scopes]]是函数的内部属性,是没法访问的,可是咱们能够经过Chrome的开发者工具看到它的样子。数组

d

  1. 咱们如今声明个函数foo
  2. 须要查看foo的原型对象才能看到[[scopes]]属性,由于foo.prototype.constructorfoo指向同一个函数,因此点开constructor选项。
  3. 如今咱们终于看到了[[Scopes]]属性。

能够清楚的看到它是一个 数组,只有一个元素 Global也就是全局对象,通过我目测这个 Global应该和 window对象是同一个对象。

// 定义一个全局的变量
var a = 'global property'

function foo () {
    console.log(a)
}

foo() // 此时会输出global property
复制代码

如上代码所示,此时咱们再看foo[[Scopes]]属性bash

会发现 Global对象里增长了一个 a属性,这和 window对象表现一致。事实上在函数 foo里面执行 console.log(a)的时候,变量 a就是从这个 Global对象内读取的。

function outer () {
    var a = 'property of outer scope'
    
    return function inner () {
        console.log(a)
    }
}

var inner = outer() 
inner() // 如你们所料,会输出property of outer scope
复制代码

此时咱们再看一下inner[[Scopes]]属性闭包

会发现 [[Scopes]]数组的前面新添加了一个叫 Closure的对象,从字面上看这不就是 闭包的意思吗,咱们展开看一下

果真有咱们 闭包里的属性 a,其实 inner函数里的 console.log(a)中的 a就是从设个 Closure对象里面读取的。咱们再来看一个例子

function outer () {
    var a = 1
    
    function inner () {
        var b = 2
        
        return function innermost () {
            console.log(a, b)
        }
    }
    
    return inner()
}

var innermost = outer()
innermost() // 此时输出的值是1 2
复制代码

看一下innermost[[Scopes]]属性,以下图函数

会发如今 Scopes数组的开头又增长了一个闭包,是按照从内到外的顺序排列的,让咱们点开看一下

果真,这里的两个 闭包对象分别包含了 innermost须要访问的全部变量。这就是做用域链的概念,当一个函数被调用的时候,函数内部访问的对象会先从函数本身的做用域内部进行查找,若是没找到对应的变量,就会从 [[Scopes]]数组的第一项 闭包对象进行查找,若是还没找到就继续到下一个 闭包对象查找,以此类推。

完。

相关文章
相关标签/搜索