JavaScript入门学习之二——函数

在前一章中讲了JavaScript的入门语法,在这一章要看看函数的使用。

函数的定义

JavaScript中的函数和Python中的非常类似,只不过定义的方式有些不同,下面看看是怎么定义的

//定义普通函数
function f1(){
    console.log('hello world!')
}

//定义带参数的函数
function f2(a,b){
    console.log(a)
    console.log(b)
}

//定义带返回值的函数
function f3(a,b){
    return a+b
}

//定义匿名函数
var sum = function(a,b){
    return a+b
}

//定义立即执行函数
(function(a){
    console.log('立即执行函数')
})(a)

立即执行函数其实有些像python里的lambda方法,的用法应该注意一下:因为在我们在全局内定义了一个变量,在定义函数的过程是无法调用这个变量的。

(function(a,b){
    console.log(a+b);
    console.log('函数中')
})(123,456)

这个方法可以让外部访问不到函数中的变量,防止函数污染全局变量。

函数的调用

这里要将一个JavaScript里比较随意的一点(也可以说是一个坑),我们看一看下面的函数

function fun(a,b){
    console.log(a+b);
}

fun(12,34)

这样没啥问题,因为形参和函数调用的时候的实参数量是一致的。那么我们改一下实参的状态,会怎么样?

fun(12,34,56)
//打印值为46
fun(12)
//打印值为NaN

arguments的使用

这里就要讲到arguments的使用了,类似Python中的*args,arguments表达了函数的形参(但是是可以不用在声明函数中明确的写出来的)

所以在JS的函数里不管是多传参数或少传参数都是不会报错的,我们可以这样看看

function fun2(a,b){
    console.log(arguments)
    for (i=0;i<arguments.length;i++){
        console.log(arguments[i])
    }
}

fun2(11,22,33,44)

而我们想要算一下传入参数的累加值,就要按下面的方法了

function fun_sum(a,b){
    var totle=0;
    for (i=0;i<arguments.length;i++){
        totle += arguments[i]
    }
    return totle
}

console.log(fun_sum(1,2,3,4,5))
 函数的全局变量和局部变量

局部变量

在JavaScript内部声明的变量(var)是局部变量,所以只能在函数内部访问,就是说这个变量的作用域只有函数内部。只要函数运行完毕,改变量就会被删除。

全局变量

在函数外部声明的变量是全局变量,网页上所有的脚本和函数都能访问。

var test = 'test'

console.log('声明函数前',test)
function fun(){
    console.log('开始声明函数',test);
    var test = 'in func';
    console.log('函数声明完成',test);
}

console.log('调用函数前',test);
fun();
console.log('调用函数后',test);

//////////输出//////////
声明函数前 test
调用函数前 test
开始声明函数 undefined
函数声明完成 in func
调用函数后 test

注意这里还有个非常坑的点:

我们在定义函数前有个变量test,如果在函数内部没有对这个test进行赋值,那么这个变量是正常的,但是一旦有了赋值操作,在操作前就成了underfined了(上面的例子就是有了赋值操作),在看看下面的

var test2 = 123;
function fun2(){
    console.log(test2)
}

fun2()

//////////输出//////////
123

变量生存周期

JavaScript的变量生命期从他们被声明的时候开始,

局部变量是在函数运行结束的时候被删除,而全局变量是在页面被关闭的时候删除。

作用域

还是要看看这几个例子:

 例子1

var city = 'beijing';
function fun(){
    var city = 'shanghai';
    function inner(){
        var city = 'shenzhen';
        console.log(city);
    }
    inner();
}

fun()
////////输出////////
shenzhen

例子2

var city = 'beijing';
function fun(){
    console.log(city);
}

function fun2(){
    var city = 'shanghai';
    return fun;
}

var ret = fun2();
ret();
//////////输出//////////
beijing

案例3.闭包

var city = 'beijing';
function f(){
    var city = 'shanghai';
    function inner(){
        console.log(city);
    }
    return inner;
}

var ret = f();
ret()

//////////输出//////////
shanghai

在上面的例子中,ret对应的函数就是inner(),也就是闭包的用法。

所以,函数的调用一定要往回找函数的定义过程。

首先,在函数内部找->再往外部找,最后找全局作用域。

词法分析

JavaScript在调用函数的一瞬间,会先进行词法分析,大致过程是这样的:

函数调用的前一个瞬间,回显形成一个激活对象:Active Object(AO),并会进行下面3个方面的分析

  函数参数——如果有参数,则将此参数赋值给AO,且值为underfined;如果没有,则不做任何操作。

  函数局部变量——如果AO上右同名的值,则不做任何操作,如果没有,则将此变量赋值给AO,并且值为underfined。

  函数声明——如果AO上有,则会将AO上的对象覆盖,如果没有则不做任何操作。

  综上所述,函数内部无论是使用参数还是使用局部变量都会到AO上找。

再看看下面的例子:

var name = 'xiaoming';
var age =12;
function fun(){
    console.log(age);
    var age = 30;
    console.log(age)
}

fun()

//////////输出//////////
underfined
30

这也就是讲了上面的那个坑是怎么导致的。

 1 var age =12;
 2 function fun(){
 3     console.log(age);
 4     var age = 22
 5     console.log(age)
 6     function age(){
 7         console.log('inner func');
 8     }
 9     console.log(age)
10 }
11 fun()
12 //////////输出//////////
13 ƒ age(){
14         console.log('inner func');
15     }
16 22
17 22

结合前面的规则看看是怎么执行的。

首先是分析过程:

  1.检查函数内是否有参数——没有

  2.检查函数内是否有局部变量——第4行的代码,定义了age局部变量,然后使AO.age=underfined

  3.检查函数内是否有内置函数——第6行的代码定义了局部函数age,然后覆盖原AO.age=fun()

然后是执行阶段

  1.要记得,所有的值都是从AO里找的,第3行的打印就是打印的AO.age,实际值应为fun().

  2.第4行的代码是AO.age值赋值为22,后面再打印就是22了。

原文地址:https://www.cnblogs.com/yinsedeyinse/p/12083357.html