Appearance
JS 中的变量提升和函数提升
变量提升
- 在作用域中,javascript 从下往上依次执行,会把
var/function
关键字进行提前声明或定义
,var 关键字只会声明,function 声明和定义一起完成
var 变量声明
- 使用 var 关键字声明的会进行变量提升
- 在定义之前访问结果是 undefined
js
console.log(a); // undefined
var a = 10;
function 变量声明
- 因为 function 声明和定义一起完成,所以在当前的作用域任何位置都可以访问到
js
console.log(a); // a() {}
function a() {}
函数声明 Vs 变量声明
- 函数声明的优先级高于变量声明,并且不会被变量声明覆盖掉
- 虽然提升不会被覆盖,但是赋值会被覆盖掉
js
// 函数声明的优先级高于变量声明,并且不会被变量声明覆盖掉
console.log(a); // a() {}
var a;
function a() {}
// ---------------
//虽然提升不会被覆盖,但是赋值会被覆盖掉
var a = 10;
console.log(a); // 10
function a() {}
if代码块函数
- if代码块中的函数,会提前声明
- if代码块中修改定义的函数,不会影响到全局
- if代码块中,不能同时var、function声明同样的变量
js
console.log(a) // undefined
if (true) {
console.log(a) // ƒ a () {}
function a () {}
}
console.log(a) // ƒ a () {}
验证if代码块中的函数,会提前声明
- 如果if代码块的函数被注释,直接会报错为定义的变量a
- 如果取消注释,打印的就是undefined
js
// 注释
console.log(a) // Uncaught ReferenceError: a is not defined
if (true) {
// function a () {}
}
// 取消注释
console.log(a) // undefined
if (true) {
function a () {}
}
验证if代码块中修改定义的函数,不会影响到全局
js
console.log(a) // undefined
var a;
if (true) {
console.log(a) // // ƒ a () {}
a = 10
function a () {}
// 只会影响if代码块内部的
a = 20
console.log(a) // 20
}
console.log(a) // 10
验证if代码块中,不能同时var、function声明同样的变量
js
// Uncaught SyntaxError: Identifier 'a' has already been declared
if (true) {
function a () {}
var a
}
立即执行函数表达式(IIFE)
js
var a = 10;
(function a() {
// 内部作用域,去查找变量声明,发现有了具明函数a
// 因为IIFE中的函数是不能修改的,所以a=20,无效
a = 20;
console.log(a); // [Function a]
})();
console.log(a); // 10
let 变量
- let 关键字声明的
不会
进行变量提升,提前访问会出异常
js
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a = 10
var变量提升和函数提升案例
- var只会提前提示声明,function声明定义一起完成
- 这里function同一个函数多次声明,后面的会覆盖前面的
- 当代码执行到var时,会覆盖函数的定义
js
fn(); // 5
function fn () { console.log( 1 ); }
fn(); // 5
function fn () { console.log( 2 ); }
fn(); // 5
var fn = function () { console.log( 3 ); }
fn(); // 3
function fn () { console.log( 4 ); } // 执行到这里,因为函数已经提前声明定义了,这里并不会有操作
fn(); // 3
function fn () { console.log( 5 ); }
fn(); // 3
函数调用变量提升(形参)
js
console.log(a, b, c); // undefined undefined undefined
var a = 12,
b = 13,
c = 14;
function fn(a) {
// 形参相当于var a = 10(私有)
console.log(a, b, c); // 10 13 14
a = 100;
c = 200;
console.log(a, b, c); // 100 13 200
}
b = fn(10); // 函数没有返回值undefined
console.log(a, b, c); // 12 undefined 200
函数调用变量提升(形参,函数)
- 函数声明和定义都是一起的,并且优先级比var声明的要高
js
function fn(a) {
// 函数声明优先级高
console.log(a);
// 形参相当于var a = 1(私有)
var a = 2;
function a(){}
}
fn(1); // [Function: a]
函数参数为函数
js
var x =100
function func(x,y=function(){x=10}){
x= 3; // 私有
y() // 找上级作用域,修改x=10
console.log(x) // 10
}
func()
console.log(x) // 100
函数参数arguments
js
function func(a,b,c){
console.log(c) // 3
arguments[2] = 100
console.log(c) // 100
}
func(1,2,3)
// 函数调用只传了2个参数,arguments=[a,b]
function func(a,b,c){
console.log(c) // undefined
arguments[2] = 100
console.log(c) // undefined
}
func(1,2)