在前一章中讲了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了。 文章链接
发表评论