函数声明之function与var

时间:2022-09-19 22:33:06

    纸上得来终觉浅,绝知此事要躬行。

    软件这行业,很多东西还是要靠敲代码敲出来的,你以为看书看的很通透,例子也能做出来的东西,一需要深入混合运用顿时觉得懵逼了。关键还是在于一知半解,不够深入。

    今天我就总结一下近段时间遇到并纠结过的一些知识。

    老规矩,由浅入深,用发散性思维思考每个知识点。


一、声明一个函数 function与var

1.function

aaa();    //先调用
function aaa(){ //后声明
//code
}

js是按顺序执行,但是这里却可以先调用再声明

其原因是,js解析器都是找到function声明,然后开始上下文执行,

所以函数已经提前被声明,只是我们代码顺序显示在后

要点,此时需要声明与调用在同一作用域(作用域不同时请看后文)


2.var

var aaa = function(){    //先声明
//code //后调用
};

这里就是通常的解析过程,当解析器开始执行上下文之前,aaa是undefind(并未声明),

只有上下文执行到var aaa = function。。。这句话时,aaa才被声明并且当场赋值


例子1

function something() { 
return 'hello';
}

alert(something()); //??这里会返回什么

function something() {
return 'world';
}
分析一下,首先js解析器会先找到functioin声明,然后根据js特性后面会覆盖前面,

再执行上下文,所以这里会输出    world


例子2

var something = function() { 
return 'hello';
}

alert(something()); //??这里会返回什么

function something() {
return 'world';
}
分析过程,

1.找到function声明,function something(){}

2.执行上下文,var something;

3.执行上下文,赋值给something,成功覆盖前面的something

4.输出    hello


    剩下一些var function的位置自行脑补然后按以上思路解决,

    记住,虽然内部解析有这样的小差别,但是在外部看是一样的,如果你用typeof测试something(),两种返回的都是function

    然后我们再往深入思考,要是function声明时,与调用不在一个作用域时,what happened?


这种情况只要抓住一条重点,看作用域链

例子3

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

顺着作用链,f先被声明,然后执行上下文,scope赋值,接着执行函数a,a调用已声明函数f,

f调用同一用域链外部变量scope,所以输出    global


例子4

var ga = 'global';
var func = function() {
var la = 'local';
return function() {
return function()
{
return function()
{
alert(la);alert(ga);
}
}
}

}
a = func()()()();
根据 作用域链,层层调用,所以输出    

local

global


然后就在弄清这些知识点时,我又发现另一个不曾注意的新知识点:

变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的

请看一下两段代码:

var scope="global";  
function f(){
console.log(scope);
var scope="local";
console.log(scope);
}
f();

输出:

undefind

local


var scope="global";  
function f(){
console.log(scope);
scope="local";
console.log(scope);
}
f();

输出

global

local


第一段代码比第二段多了一个var,结果大大不同

简单点理解,就是上面讲解var的时候,解析器先把var声明成undefind

所以第一段代码可以写为

var scope="global";  
function f(){
var scope;
console.log(scope);
scope="local";
console.log(scope);
}
f();