从运行时聊javascript做用域

什么是做用域

做用域是指程序源代码中定义变量的区域。它规定了程序执行时对该变量的访问权限。javascript

js中的做用域有什么特色

前面咱们聊了什么是做用域,那javascript中做用域都有哪些特色呢?接下来咱们就聊聊这个java

动态做用域和静态做用域

在讨论这个问题以前先看一段以下代码:bash

var a = 1
function f1 () {
    console.log(a)
}
function f2 () {
    var a = 2
    f1()
}
f2()
复制代码

上述代码会打印1。这就很好的说明了,在javascript中,其做用域是静态做用域也就是词法做用域。通俗点来说,函数的做用域在定义的时候就已经定了。套用做用域的概念就是函数f1在定义的时候,就规定了访问的变量a是全局变量中的a,所以当在函数f2中执行的时候,函数f1没有访问函数f2中的局部变量a的权限。函数

全局做用域、局部做用域及块做用域

  • 全局做用域:变量在全局声明就拥有了全局做用域
  • 局部做用域:在函数内声明的变量,至于在函数体内有定义,他们是局部变量,做用域是局部性的,所以其权限就是局部做用域。特别注意:函数参数也是局部变量
  • 块级做用域:在一些类c语言中,花括号内的每一段代码都具备各自的做用域,变量在声明他们的代码块外是不可见的,咱们称之为块级做用域。在ECMAScript6以前,javascript中是没有块级做用域的概念的。
    这几个做用域从优先级上来讲,块级做用域 > 函数做用域 > 全局做用域 咱们来看下面一段代码:
var scope = 'global'
function checkscope () {
    var scope = 'local'
    let i = 10
    {
        let i = 8
        console.log(i) // => 8
    }
    return scope
}
checkscope() // => 'local'
复制代码

变量提高

在以下代码中咱们定义了变量a,b,c,他们都在同一个做用域内。ui

function test (d) {
    console.log(a) // => undefined
    console.log(b) // => undefined
    console.log(c) // => undefined
    var a = 1
    if (d > 0) {
        var b = 2
        for (var c = 0; c < 10; c ++) {
            console.log(c) // =>0 - 9
        }
        console.log(c) // =>10
    }
    console.log(b) // =>2
}
test(1)
复制代码

咱们发现javascript函数做用域在整个函数体内始终可见,即使是在判断语句和循环语句中也没有收到影响。这意味着变量在声明前就已经可用。javascript的这个特性就称为声明提早也叫变量提高。spa

做用域链

到底全局做用域跟局部做用域什么关系呢?还有你们可能会疑惑,咱们再聊javascript静态做用域的时候函数f1是怎样访问到全局变量a的呢?code

  • 做用域链 每一段javascript代码(全局或者函数)都有一个与之关联的做用域链,这个做用域链是一个对象列表或者链表,这组对象定义了这段代码"做用域中"的变量。当javascript须要查找变量a的时候,他会沿着这条链查找第一个对象看它有没有a变量,若是没有就查找第二个对象,若是尚未就接着查找下一个,一次类推,直到找到,若做用域链上没有一个对象含有a属性,那么就认为这段做用域链上不存在该属性,最终或抛出一个引用异常错误。
  • 在javascript的最顶层代码中(不包含任何函数定义的代码),做用域链由一个全局对象组成。在不包含嵌套的函数体中,做用域链上有两个对象,第一个是定义函数参数和函数对象的对象,第二个就是全局对象。

今天咱们聊了一聊javascript中的做用域,可能你们已经发现啦我说了半天做用域好像跟javascript运行时没有什么关系啊,别着急,后续还会在接着聊。对象

相关文章
相关标签/搜索