Appearance
函数底层运行机制
函数每次执行都会形成一个全新的私有上下文
初始化作用域链,<自己的上下文,上级上下文>
- 函数定义时上级上下文就已经指定好了,当前函数是在哪个作用域下定义的,那么函数执行时 的上级上下文就是那个作用域,和函数在哪执行没关系,只和定义的地方有关系。
初始化this
初始化arguments
形参赋值
变量提升
代码执行,进栈执行 EC(FN),私有上下文中有一个存放未来它声明的私有变量的地方,AO(FN) 私有变量对象,只有两种变量会存储到 AO(FN) 中,一是形参变量,二是函数体中声明过的变 量,私有上下文中代码执行时,遇到一个变量,首先看是否为自己上下文中的私有变量,如果是 私有的,则接下来所有操作都是操作自己的变量,和外面的变量没有直接关系。如果不是自己的 私有变量,按照作用域链,查找是否为其上级上下文中的变量,如果找到了,之后操作的都是上级 上下文中的变量。如果上级上下文中也没有这个变量,则沿着作用域链继续向上级查找,直到全局 上下文为止,如果全局上下文也没有, 再去 GO 找, 还没找到,如果获取变量值就是报错,如果 设置变量值就是给 window 设置的属性。
出栈释放
函数执行形成的私有上下文会保护里面的私有变量,不受外面干扰,避免了全局变量污染,这种保 护机制就是闭包。
特殊:匿名函数具名化,参考下一篇文章
js
// example1
var n = 1
function fn () {
var n = 2
function f () {
n--
console.log(n)
}
f()
return f
}
var x = fn()
x()
console.log(n)
// example2
var i = 0
function A () {
var i = 10
function X () {
console.log(i)
}
return X
}
var y = A()
y()
function B () {
var i = 20
y()
}
B()
// example3
console.log(a, b, c)
var a = 12,
b = 13,
c = 14
var fn = function (c) {
console.log(a, b, c)
var a = b = c = 20
console.log(a, b, c)
}
fn(10)
console.log(a, b, c)
// example
var obj = {
a: '包子',
b: '面条'
}
var a = 'name'
function fn (obj) {
console.log(obj)
obj[a] = '珠峰'
obj.b = '馒头'
obj = {}
obj[1] = 1
console.log(obj)
}
fn(obj)
console.log(obj)
// example
var foo = 'hello'
~(function (foo) {
console.log(foo)
var foo = foo || 'world'
console.log(foo)
})(foo)
console.log(foo)
// example
var a = 9
function fn () {
a = 0
return function (b) {
return b + a++
}
}
var f = fn()
console.log(f(5))
console.log(fn()(5))
console.log(f(5))
console.log(a)