JS中的声明提前,变量声明提前,函数声明提前,以及声明提前的顺序
首先来看以下一段代码:
console.log(a)//?
a();//?
var a ;
function a(){
console.log(10);
}
console.log(a);//?
a = 6;
a();//?
四个输出分别是什么呢?我们来调试一下,
执行到 a= 6时输出如下:
最后一个a();报错。
接下来我们来分析一下原因
一、什么是变量声明提前?
变量在声明它们的函数体以及这个函数体嵌套的任意函数体内始终可见。说直白点,在声明一个变量的前后,你都可以直接使用它,并不会报错。举个例子:
(function test() {
console.log(name);
var name = 'zhangsan';
console.log(name);
})()
打印结果:
因为以上代码等同于
(function test() {
var name
console.log(name);
name = 'zhangsan';
console.log(name);
})()
2.什么是函数声明提前?
函数声明提前的原理与变量声明提前情况类似,需要提醒的是,只有函数声明格式的函数才会存在函数声明提前,比如函数表达式,构造函数,都不存在函数声明提前。
函数创建的三种写法:
a.函数声明:function fun(a){console.log(a)};(只有这个存在函数声明提前)
b.函数表达式:var fun = function(a){console.log(a)};
c.构造函数:var fun = new Function(“a”,console.log(a));
test()
function test() {
console.log(1);
}
此代码等同于
function test() {
console.log(1);
}
test()
再来看看函数表达式
test() //报错
console.log(test) //undefined
var test = function () {
console.log(1);
}
test() //输出 1
这里的test被当做变量处理,相当于先声明一个变量,再将function赋值给这个变量就,即等同于:
var test
test() //此时函数未声明 所以报错
console.log(test) //已声明 只是未赋值
test = function(){
console.log(1)
}
test() //函数已声明 可以使用
3.变量提升的顺序
既然函数声明和变量声明都会提前,那么到底函数先提升还是变量先提升呢?
先来看一段简单的代码:
console.log(test)
function test() {
console.log(1)
}
var test
为了公平起见我们把变量的位置和函数的位置换一下
console.log(test)
var test
function test() {
console.log(1)
}
结果:
我们可以看到,两次打印的结果都是function,也就是说函数的声明提前会高于变量的声明提前。
最后让我们回到
console.log(a)//?
a();//?
var a ;
function a(){
console.log(10);
}
console.log(a);//?
a = 6;
a();//?
此代码等同于:
function a(){
console.log(10)
}
var a;
console.log(a); //funtion 因为函数的提前的优先级更高
a(); //函数已声明 所以输出是10
console.log(a); // function 这里和上一个一样 都是输出function
a = 6;
a(); //报错 因为 已经把6赋值了 a 了,此时a不再是函数
----------------------------- 最后再来看一个例子 ----------------------------
(学习的时候阴差阳错打出来的代码,想半天给不出解释,最后问老师才得以解决)
console.log(test()) //???
function test() {
console.log('test')
}
var test
先来看看输出吧
这里很容易造成一个误区,执行test()时打印test,然后变成变成console.log(test)所以打印undefined???
前面说过了函数声明优先变量声明,打印结果不应该为function吗???
然后我们试着把 var test删除,
console.log(test()) //???
function test() {
console.log('test')
}
打印结果却不变,所以问题肯定出在了函数上面。
其实很简单
test()运行的结果应该是函数的一个返回值,而console.log中打印的test并不是这个函数执行返回的结果,也就是说console.log(test())打印的应该是函数的返回值。
console.log(test())
function test() {
console.log('test')
return 111
}
而我们之前并没有这个返回值
我的理解是:函数体本身就声明了返回值 而我们并没有给这个返回值赋值,所以返回值是undefined。