在前一章中讲了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

console.log(arguments[i])

}

}

fun2(11,22,33,44)

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

function fun_sum(a,b){

var totle=0;

for (i=0;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了。

文章链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。