一、什么是提升(Hosting)?
// 引擎会在解释JavaScript代码之前首先对其进行编译,
**// 编译过程中的一部分工作就是找到所有的声明,**
**// 并用合适的作用域将他们关联起来,这也正是词法作用域的核心内容。**
**// 简单说就是在js代码执行前引擎会先进行预编译,**
**// 预编译期间会将变量声明与函数声明提升至其对应作用域的最顶端。**
二、变量提升
a = 2;
var a;
console.log(a)
console.log(a);
var a = 2
**// 按照JS代码的执行顺序应该是从上到下一行行的执行的,真的是这样吗??其实这不是完全正确的。**
**// 正确的思路是,包括变量,函数在内的所有声明都会在任何代码在执行前首先被处理。**
**// 当你看到var a = 2 时你可能会理解成这是一个声明,**
**// 但JS在执行时实际上会将其看成两个声明 var a 和 a = 2**
**// 第一个var a 是在代码的编译阶段执行的。**
**// 第二个赋值声明 a = 2 会被留在原地等待执行阶段来执行**
在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),
只有全局作用域和函数作用域。变量提升即将变量声明提升到它所在作用域的最开始的部分。
console.log(good); // undefined
var good = 'good';
console.log(good); // good
// function fn() {
// console.log(a); // undefined
// var a = 'aaa';
// console.log(a); // aaa
// }
// fn()
之所以会是以上的打印结果,
是由于js的变量提升,实际上上面的代码是按照以下来执行的:
var good; // 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(good); // undefined
good= 'good
console.log(good); // 打印出good
function fn() {
var a; // 变量提升,函数作用域范围内
console.log(a);
a = 'aaa';
console.log(a);
}
fn();
三、函数提升
**// js中创建函数有两种方式:函数声明式和函数字面量式。**
**// 只有函数声明才存在函数提升!注意:使用匿名函数的方式不存在函数提升,**
**// 因为函数名称使用变量表示的,只存在变量提升。**
例一
console.log(f1); // function f1() {}
console.log(f2); // undefined
function f1() { }//
var f2 = function () { }//函数表达式,匿名函数
// 之所以会有以上的打印结果,
// 是由于js中的函数提升导致代码实际上是按照以下来执行的:
function f1() { } // 函数提升,整个代码块提升到文件的最开始
console.log(f1);
console.log(f2);
var f2 = function () { }
**例二:**
foo();
function foo(){
console.log("aaa");
}
结果输出: aaa 原理:函数声明提升 (函数声明提升直接把整个函数提到执行环境的最顶端)
相当于:
function foo(){
console.log("aaa");
}
foo();
变量提升只提升函数名 而函数提升会提升整个函数 注意:函数提升在变量提升上面。
**例三:**
foo();
var foo = function(){
console.log("aaa");
}
运行结果是: foo is not a function
相当于;
var foo;
console.log(foo); //undefined
foo(); //foo is not a function
foo = function(){
console.log("aaa");
}
上面代码输出undefined 是因为变量提升后并没有赋值因此输出undefined
输出foo is not a function 原因是:js解析遇到 foo()时会默认当做函数来解析
**例四:**
console.log(foo);
var foo=10;
console.log(foo);
function foo(){
console.log(10);
}
console.log(foo);
输出为:
相当于:
function foo(){
console.log(10);
}
var foo;
console.log(foo);
foo=10;
console.log(foo);
console.log(foo);
函数提升在变量提升上面,第一个console.log(foo);为什么会输出函数题呢,原因在于 var foo; 并未有赋值只是声明,因此他会调用上面的值
总结:关于变量提升,一定要注意细心思考一下,还有就是要牢记,函数提升在变量提升之上