JavaScript百炼成仙 函数七重关之三(参数传递)

简介: JavaScript百炼成仙 函数七重关之三(参数传递)

“所谓的参数,就是当函数调用的时候会传进来的值,也就是说,我们在定义参数的时候,并不知道调用的过程中会有什么样的值传过来。”接着,叶小凡随手打出一段绚丽的代码流。


function add(a,b,c){
        var sum = a + b + c;
        console.log(sum);
}
add(1,2,3);


代码运行,结果是6。


“这就是一个最简单的函数调用,配上参数传递的例子。一般来说呢,函数的名字定义就要让人一看就知道是什么意思。比如我这个例子中,add函数,别人一看就能够明白,哦,我这个函数的目的是做加法。调用函数的时候,传进去三个参数,分别是1,2,3,这三个参数分别对应add函数中圆括号,也就是参数列表内的a、b、c三个变量。在我定义这个函数的时候,a、b、c三个变量的变量名是随便取的,当然,能够见名知意最好。”


“在刚才的例子中,add函数的调用需要三个参数,分别是a、b、c。换句话说,如果你要调用add函数,就必须要传入三个参数,就像这样。”


add(1,2,3);


“函数的调用就是函数名字加上一对圆括号,这样就会去执行函数里面的代码体了,也就是这个部分。”


function add(a,b,c){
        var sum = a + b + c;
        console.log(sum);
}


“函数的代码体一般都是用花括号扩起来的,里面就是正常写JavaScript代码便可以了。没写完一句就要打一个分号,这是JavaScript代码的编写规范。现在我们来看一下这个函数的函数体里面都做了些什么事情,首先是第一行。”


var sum = a + b + c;


“sum是一个新定义的变量,注意了,这个变量是定义在add函数的函数体内部的,根据作用域的范围限定,这个变量是定义在函数作用域里面的,函数作用域是一个相对封闭的空间,也就是说,外面的全局作用域是没有办法直接访问函数作用域里面的这个sum变量的。所以说,这个sum变量只能在这个函数的函数体内被访问到,它也被叫做局部变量。好,继续看,接下来就是一个简单的加法和赋值了。从代码的字面上也可以看出来,就是把a、b、c三个变量相加之后得到一个总量,然后把这个总量用等号(赋值运算符)赋给局部变量sum的。下面一句是一个打印语句,就是把sum变量在控制台上打印出来罢了。'”


“那如果我在调用函数的时候,就传了一个参数咋办?”对面弟子问到。


“嗯,你说的这个问题,我想,可以把它单独拆分出来看。比如,我定义一个函数,设置了一个参数,但是传参的时候却一个参数都没有传。像这样的情况,和你的问题是类似的。”


“哦?那你说说看。”


“好的。”叶小凡想了一下,便打出一段代码。


function fun(a){
    console.log(a);
}


“这是一个简单的函数,函数名字是我随便取的,就叫它fun吧。这个函数是有设置参数的,参数名字是a,当然了,这个a到底是什么,是没有限定的,它可以是一个字符串,也可以是一个数字,甚至可以是一个对象,哪怕,是另一个函数,都可以。因为只是测试,所以我只是在这个函数的函数体中写了一条打印语句而已。接下来,我试着要去调用这个函数,而且,故意不写参数,就像这样。”


fun();


“这是一个非常古怪的例子,因为fun函数明明是要求填写一个参数的,那就是a。可是,在调用函数的时候,却偏偏没有参数传递进来。那么,这按理说是不被允许的,可是当这种情况真的发生了,会怎样呢?也就是说,没有参数传进来,那么函数中已经设置好的参数等于什么呢?试一下,便知。”叶小凡故意卖个关子,然后执行了代码。


结果显示:undefined


“没错了,结果就是undefined。其实,对于函数传参到底是怎么回事,可以把这个例子再次细分。刚才的函数中有一个参数a,那么这个参数自然也是属于函数作用域里面的,就相当于这样。”


function fun(){
        var a;
        console.log(a);
}


“为了方便理解,在关键的地方不犯糊涂。函数的参数,可以简单看成是在函数体,也就是花括号扩起来的地方,里面的第一行,定义了一个变量。因为我们并没有给这个变量赋值,所以这个局部变量就是undefined。可以这么说,任何变量在被赋予真正的值之前,在编译阶段都是undefined。或者说,任何变量,不管最终的值是什么,都曾经是undefined。这些函数的参数可以理解为一种预备变量。接下来说说正常的情况,比如我调用fun函数,传递一个参数18。那么传参的过程,就相当于是给预备变量赋值的过程。如果没有传参,那么预备变量自然还是undefined了。再回到刚开始的例子,如果我直传一个参数。”


function add(a,b,c){
        var sum = a + b + c;
        console.log(sum);
}
add(1);


“这种情况,a的值是1,b和c的值就是undefined,那么数字1和两个undefined相加会是多少呢,真是有意思的问题。结果是NaN,代表无法计算。没错,如果真的那样做,那么就是没有任何意义了。最起码,在这个函数中,那样的做法是毫无意义的。”


“好吧,那如果我多传一个参数会怎样呢?”对面弟子又来一个问题,大有一副不把叶小凡问道誓不罢休的意思。然后,令他没有想到的是,叶小凡立刻就有了回答。


“你说的这个问题,其实也可以单独拆解出来。就好比我定义了一个函数fun,没有参数,但是如果我在调用fun函数的时候,故意给它加了一个参数,会发生什么?比如,像这样。”


function fun(){
}
fun(10);

“结果是可想而知的,自然是什么都不会发生啦。再回到刚才的例子中去,就算你强行加了第四个参数,对结果自然也不会有什么影响的。”


function add(a,b,c){
        var sum = a + b + c;
        console.log(sum);
}
add(1,2,3,4);


“如果我一定要在函数里面访问到额外的参数咋办?”对面弟子一副问到你山穷水尽的气势,就连场外的某些弟子都看不下去了,心想这种问题实在是有些欺负人了。可是林元青在听到这个问题后,却不动声色地望向叶小凡,眼神中隐约流露出一份期待。


“这是可以办到的,其实所有的参数都会被装载到函数内部,一个叫做arguments的数组里面。比如这个add函数,虽然参数设置了abc三个,但是在函数的内部还维护了一个arguments数组。我可以用代码来验证。”


function add(a,b,c){
        console.log(arguments);
        var sum = a + b + c;
        console.log(sum);
}
add(1,2,3,4);


代码运行,结果是


微信截图_20230504210543.png


“可以看到,你传过来四个参数,其实就放进了这个默认的arguments数组里面。换句话说,参数列表里面的a、b、c也是根据这个数组来赋值的。现在,我把代码改写一下,就看的更清楚了。”


function add(a,b,c){
        console.log(arguments);
        a = arguments[0];
        b = arguments[1];
        c = arguments[2];
        var sum = a + b + c;
        console.log(sum);
}
add(1,2,3,4);


“嗯,根据这个特性,可以完成一些有趣的功能,比如,我可以编写一个函数,参数个数任意写,实现数字的累加。说得简单一些,就比方说,我调用add函数的时候,传入3个数字,那么就进行三个数字的累加。如果传入5个数字,就进行5个数字的累加。也就是说,不管你传入多少数字,我都可以给你实现一个累加。这便是一个非常灵活的累加器了。”说完,叶小凡一遍思考,一边开始写代码。


“因为实现我并不知道会有几个参数传进来,所以干脆就不设置任何参数了。”


function add(){
}


“这样,我先假设调用add函数的时候,最起码会有一个参数传进来。那么,先用arguments数组获取一下第一个位置的元素。如果第一个位置的元素都不存在,那么就返回0。”


function add(){
        if(!arguments[0]){
        return 0;
}
}


“接下来,因为不知道究竟会有多少个参数,也就是说arguments数组的长度也许是未知的。但是,arguments既然是一个数组,那么就会有length属性,这个属性里面放的就是arguments数组的内部元素个数了。这样看来,虽然我不知道会有多少个参数传进来。但是我们在函数的函数体中却可以通过arguments数组的length属性预知未来传入参数的个数。这样的话,我就只需要做一个简单的数组循环,就可以了。然后,将所有的数据累加起来,像这样。”


function add(){
        if(!arguments[0]){
        return 0;
}
for(var i = 1;i < arguments.length;i++){
        arguments[0] = arguments[0] + arguments[i];
}
        console.log(arguments[0]);
}
add(1,2,3,4);


“这种写法的思路就是,从数组的第二个元素开始,往后所有的元素全部累加到第一个元素上去,就得到了数组中所有元素的和。当然,我也可以在函数内定义一个局部变量sum,全部累加到sum变量上,比如这样。”


function add(){
        var sum = 0;
        for(var i = 0;i < arguments.length;i++){
                sum = sum + arguments[i];
        }
        console.log(sum);
}
add(1,2,3,4);


“这样的话,数组的循环就可以从下标为0的地方开始。因为如果第一个元素都不存在,那么arguments数组的length就是0,也就是说,for循环连1次都不会进去的。函数的结果就是sum依然是0,还是符合预期。”


“最后,再说一下函数的返回值。就好像之前的例子,sum变量虽然是所有参数的总和,但是这个sum变量毕竟只是在函数的内部。根据作用域的关系,外面是没有办法访问函数作用域里面的sum变量的,可是既然这是一个累加函数,那么外面调用这个函数的目的自然就是要获取累加之后的值。因此,将局部变量sum暴露出去是非常有必要的。那么,怎么才可以实现这一点呢,方法就是用return关键字,将函数中的某一个数据返回出去。比如这样。”


function add(){
        var sum = 0;
        for(var i = 0;i < arguments.length;i++){
                sum = sum + arguments[i];
        }
return sum;
}


“把sum变量return出去,那么调用函数之后,函数就返回了一个sum出去,也就是说,函数的调用结果就成了sum变量,外面的全局作用域就可以获取函数内部的数据了。比如这样。”


var sum = add(1,2,3);
console.log(sum);

“这便是函数七重关之第三重关了。”听完叶小凡的讲述,就连林元青也点了点头,表示认同,对面弟子也再也挑不出刺来了。


相关文章
|
2月前
|
JavaScript 前端开发 Java
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
本文介绍了JavaScript中常用的函数和方法,包括通用函数、Global对象函数以及数组相关函数。详细列出了每个函数的参数、返回值及使用说明,并提供了示例代码。文章强调了函数的学习应结合源码和实践,适合JavaScript初学者和进阶开发者参考。
50 2
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
|
2月前
|
前端开发 JavaScript 开发者
除了 Generator 函数,还有哪些 JavaScript 异步编程解决方案?
【10月更文挑战第30天】开发者可以根据具体的项目情况选择合适的方式来处理异步操作,以实现高效、可读和易于维护的代码。
|
3月前
|
JavaScript 前端开发
JavaScript 函数语法
JavaScript 函数是使用 `function` 关键词定义的代码块,可在调用时执行特定任务。函数可以无参或带参,参数用于传递值并在函数内部使用。函数调用可在事件触发时进行,如用户点击按钮。JavaScript 对大小写敏感,函数名和关键词必须严格匹配。示例中展示了如何通过不同参数调用函数以生成不同的输出。
|
3月前
|
存储 JavaScript 前端开发
JS函数提升 变量提升
【10月更文挑战第6天】函数提升和变量提升是 JavaScript 语言的重要特性,但它们也可能带来一些困惑和潜在的问题。通过深入理解和掌握它们的原理和表现,开发者可以更好地编写和维护 JavaScript 代码,避免因不了解这些机制而导致的错误和不一致。同时,不断提高对执行上下文等相关概念的认识,将有助于提升对 JavaScript 语言的整体理解和运用能力。
|
3月前
|
JavaScript 前端开发
js教程——函数
js教程——函数
62 4
|
3月前
|
存储 JavaScript 前端开发
js中函数、方法、对象的区别
js中函数、方法、对象的区别
38 2
|
3月前
|
JavaScript 前端开发 Java
【javaScript数组,函数】的基础知识点
【javaScript数组,函数】的基础知识点
38 5
|
3月前
|
JavaScript 前端开发
Node.js 函数
10月更文挑战第5天
30 3
|
3月前
|
前端开发 JavaScript
探索JavaScript函数基础
探索JavaScript函数基础
27 3
|
3月前
|
存储 JavaScript 前端开发
JavaScript数据类型全解:编写通用函数,精准判断各种数据类型
JavaScript数据类型全解:编写通用函数,精准判断各种数据类型
75 0