关于JS中变量、函数声明提升优先级问题的实验

在复习JS-函数时遇到函数声明提升,回想起之前的变量声明的提升,加上JS无重载一说,若出现同名函数,则后者会覆盖前者。想搞清楚既然变量、函数都能提升,那他们之间的优先级是什么,遂做个小实验验证一下。

其实我是被自己写的一题给绕晕了

1
2
3
4
5
6
7
8
9
10
11
12
console.log(a); 
var a = 100;

var a = function() {
console.log("a");
}
console.log(a);

function a() {
console.log("aa");
}
console.log(a);

结论

  • 变量声明、函数声明都会提升执行顺序
  • 优先级:函数声明 > 变量声明

验证过程如下:

预备知识

变量声明的提升

直接看代码:

1
2
3
console.log(a);
var a = 100;
//结果为控制台打印 undefined

等价于:

1
2
3
var a;
console.log(a);
a=100;

这就是变量声明提升–JS中,变量的声明会在其作用域内的最先运行。

函数声明提升

直接看代码:

1
2
3
console.log(a);
function a () {}
//结果为控制台打印该函数

等价于:

1
2
function a () {}
console.log(a);

函数表达式声明

函数声明提升不适用于函数表达式,但在判断优先级时可作为很强的干扰项,看代码:

1
2
3
console.log(a);
var a = function () {}
//结果为控制台打印 undefined

其实这个就是变量声明的提升。。。等价于:

1
2
3
var a;
console.log(a);
a = function () {}

实验过程

运行环境

  • Chrome 63.0.3239.132 (正式版) (64位)

变量声明与函数表达式声明

看代码:

1
2
3
4
console.log(a);
var a = 100;
var a = function () {}
console.log(a);

结果为控制台打印如下内容:

1
2
undefined //变量声明提升
function () {} //后者覆盖前者

变量声明与函数声明

看代码:

1
2
3
4
console.log(a);
var a = 100;
function a () {}
console.log(a);

结果为控制台打印如下内容:

1
2
function a () {} //函数声明提升
100

代码等价于:

1
2
3
4
5
var a;//变量声明提升
function a () {}//函数声明提升
console.log(a);
a = 100;
console.log(a);

这里有个疑问,到底是var a;变量声明提升在前,还是function a 函数声明在前。验证了一下,不管谁在前,运行结果都一样。

个人开始认为应该是 变量 (全局) 声明在前,函数声明提升在后,后者覆盖前者,所以第一个 console.log(a); 打印函数a。

验证:

1
2
3
4
5
6
7
console.log(window);
//控制台打印出window对象
console.log(a);
var a = 100;

function a() {}
console.log(a);

后查阅《You Don’t Know JS:Scope & Closures》的第四章关于声明提升的说法是,function 声明 优先于 var 声明,尽管 var 写在前,但 function 声明优先,var 声明被忽略了。

被忽略了??

emmmm…

函数声明与函数表达式声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
haha();

var haha = function () {
console.log("●");
}

function haha(){
console.log("□");
}

haha();

//结果为:
// □ 函数声明的优先级高于表达式声明
// ● 优先级低的覆盖前者

这或许是要看JS引擎源码才能知道答案吧…

所以,

开头那题的答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
console.log(a); //function a () {console.log("aa")}  函数声明提升至最前

var a = 100;

console.log(a); //100 变量声明并赋值后覆盖了前者

var a = function() {

console.log("a");

}

console.log(a);//function () {console("a")} 函数表达式声明覆盖了前者

function a() {

console.log("aa");

}

console.log(a);//function () {console("a")} 无新赋值了。

参考

本文完。

© 2019 lvbin's Blog All Rights Reserved.
Theme by hiero