目录
一、概念理解
变量提升:在当前作用于中,js代码自上而下执行之前,浏览器会把所有带var/function关键字进行提前声明或定义。带var的关键字只是提前声明一下,带function的关键字在变量提升阶段把定义和声明都完成了。
1.变量声明提升
通过 var 定义(声明)的变量,在定义语句之前就可以访问到
值:undefined,只是当时的值是undefined
2.函数声明提升(又叫函数提升)
通过 function 声明的函数,在声明语句之前就可以直接调用
值:函数定义(对象)
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() {}
console.log(global); // undefined
var global = 'global';
console.log(global); // global
function fn () {
console.log(a); // undefined
var = 'abc';
console.log(a); // abc
}
fn();
var global; // 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(global); // undefined
global = 'global'; // 此时才赋值
console.log(global); // 打印出global
function fn () {
var a; // 变量提升,函数作用域范围内
console.log(a);
a = 'abc';
console.log(a);
}
fn();
变量提升和函数提升的优先级
在函数与变量之间,函数首先会被提升,然后才是变量。
console.log(xy) //function xy(){console.log('hello')}
var xy;
var z = 'def'
function xy (){
console.log(z) //undefined
var z = 'abc';
console.log(z) //abc
}
xy();
函数提升优先级比变量提升要高,且不会被变量声明覆盖,但是会被变量赋值覆盖。
console.log(xy) //function xy(){console.log('hello')}
var xy = 5;
var z = 'def'
function xy (){
console.log(z) //undefined
var z = 'abc';
console.log(z) //abc
}
xy(); // 报错Uncaught TypeError: xy is not a function 因为被变量赋值覆盖了
函数内部变量提升优先级高于函数外部变量提升(这里还涉及到作用域的问题)
var z = 'def'
function xy (){
console.log(z) //undefined
var z = 'abc';
console.log(z) //abc
}
xy();
---------------------------------------------------------
var z = 'def'
function xy (){
console.log(z) // def
// var z = 'abc';
console.log(z) //def
}
xy();
小结:
函数提升优先级比变量提升要高,且不会被变量声明覆盖,但是会被变量赋值覆盖。
在js中变量和函数的声明会提升到最顶部执行
函数的提升高于变量的提升
函数内部如果用 var 声明了相同名称的外部变量,函数将不再向上寻找。
匿名函数不会提升。