提升
问:先有🐓(赋值)还是先有🥚(声明)?
答:先有蛋。只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。
- 函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量
foo(); // 1
var foo; // 变量声明
function foo() { // 函数声明
console.log( 1 );
}
foo = function() {
console.log( 2 );
};
会输出 1 而不是 2 !这个代码片段会被引擎理解为如下形式:
function foo() {
console.log( 1 );
}foo(); // 1
foo = function() {
console.log( 2 );
};
var foo 尽管出现在 function foo()… 的声明之前,但它是重复的声明(因此被忽 略了),因为函数声明会被提升到普通变量之前。
尽管重复的 var 声明会被忽略掉,但出现在后面的函数声明还是可以覆盖前面的:
foo(); // 3
function foo() {
console.log( 1 );
}
var foo = function() {
console.log( 2 );
};
function foo() {
console.log( 3 );
}
作用域闭包
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo(); baz();
函数 bar() 的词法作用域能够访问 foo() 的内部作用域,将 bar() 函数本身当作 一个值类型进行传递。由于看上去 foo() 的内容不会再被使用,所以很 自然地会考虑对其进行回收,闭包的“神奇”之处是可以阻止这件事情的发生。事实上内部作用域依然存在,是 bar() 本身在使用,因此没有被回收。
这个函数在定义时的词法作用域以外的地方被调用。闭包使得函数可以继续访问定义时的 词法作用域。
无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都可以观察到闭包。
「未完…」