函数作用域[[scope]]

每个 javascript 函数都是一个对象,对象中有的属性可以访问,有的不能,这些属性仅供 javascript 引擎存取,如[[scope]]。

[[scope]]就是函数的作用域,其中存储了执行期上下文的集合。

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

作用域链

[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们称这种链式链接为作用域链。查找变量时,要从作用域链的顶部开始查找。Activation Object(AO)到 Global Object(GO)。

function a定义 a run b define b run

作用域相关问题

下面的代码打印什么内容,为什么?

var b = 10;
var c = function b() {
  b = 20;
  console.log(b)
}
c()

// 打印:
ƒ b() {
  b = 20;
  console.log(b)
}

b 函数(函数表达式定义函数)是一个相当于用 const 定义的常量,内部无法进行重新赋值,如果在严格模式下,会报错"Uncaught TypeError: Assignment to constant variable."

简单改造下面的代码,使之分别打印 10 和 20

var b = 10
;(function b() {
  b = 20
  console.log(b)
})()

打印 10:

var b = 10
;(function b(b) {
  window.b = 20
  console.log(b)
})(b)
var b = 10
;(function b() {
  b.b = 20
  console.log(window.b)
})()

打印 20:

var b = 10
;(function b(b) {
  b = 20
  console.log(b)
})()
var b = 10
;(function b() {
  var b = 20
  console.log(b)
})()

下面代码输出什么

var a = 10
;(function () {
  console.log(a)
  a = 5
  console.log(window.a)
  var a = 20
  console.log(a)
})()

依次输出:undefined -> 10 -> 20

解析:

在立即执行函数中,var a = 20; 语句定义了一个局部变量 a,由于 js 的变量声明提升机制,局部变量 a 的声明会被提升至立即执行函数的函数体最上方,且由于这样的提升并不包括赋值,因此第一条打印语句会打印 undefined,最后一条语句会打印 20。

由于全局的 var 会挂载到 window 对象下,并且立即执行函数里面有变量提示。 ‘a = 5;’这条语句执行时,局部的变量 a 已经声明,因此它产生的效果是对局部的变量 a 赋值,此时 window.a 依旧是最开始赋值的 10

var 变量定义提升

var name = 'Tom'
;(function () {
  if (typeof name == 'undefined') {
    var name = 'Jack'
    console.log('Goodbye ' + name)
  } else {
    console.log('Hello ' + name)
  }
})()

输出: 'Goodbye Jack'

results matching ""

    No results matching ""