不一样的JavaScript(4)——函数参数
来源:互联网 发布:微信公众号假数据推广 编辑:程序博客网 时间:2024/06/05 09:14
1. 在Javascript中,如果函数申明时的参数个数和函数调用时的参数个数不相等,并不会引起语法错误。
1.1 如果函数声明时的参数个数多于函数调用时的参数个数,在调用时没有设置的参数会被自动设为undefined。
function divide(num1, num2) { if (num2 == undefined) { num2 = 2; } return num1 / num2;}console.log(divide(12, 4)); // 3console.log(divide(12)); // 6
在上述代码中,我们声明一个有两个参数num1和num2的函数divide。当我们用参数12和4调用函数divide时,这两个值分别赋予num1和num2。当我们只设置一个参数12时,这个数值被赋予参数num1,而num2被设为undefined。
上述代码相当于把函数divide的第二个参数num2设置了一个缺省值2。当在函数调用的时候没有给num2传递一个数值,那么就将使用缺省值2。下面的C++代码和它的功能类似:
int divide(int num1, int num2=2) { return num1 / num2;}
1.2 如果函数声明是的参数个数少于函数调用时的参数个数,我们可以通过arguments得到函数的所有的参数。argument是存在于每个函数体内的一个数组,用来存储函数调用时传递的参数。
function sum() { var total = 0; for (var i = 0; i < arguments.length; ++i) { total += arguments[i]; } return total;}console.log(sum(1, 2, 3)); // 6console.log(sum(1, 2, 3, 4)); // 10
上述代码在声明函数sum的时候,参数列表中没有一个参数,但在函数体内用argument得到在函数调用时实际传递的参数,在累加所有参数并返回它们的和。所以当传入三个参数1、2、3时,得到它们的和6;当传入4个参数1、2、3、4时,得到它们的和10。
1.3 由于Javascript能给函数传入不同数目的参数,因此在Javascript不能和很多语言一样实现多态(定义多个函数名相同但是参数的数目或者类型不同的函数)。在Javascript,如果一个函数名被定义多次,最后一次将覆盖前面的定义。例如:
function add(num1, num2, num3) { console.log(num1 + num2 + num3);}function add(num1, num2) { console.log(num1 + num2);}add(1, 2, 3);在上述代码中,我们定义了两个叫add的函数。第二个(只有两个参数)函数的定义会覆盖前面一个定义。因此当我们用三个参数调用函数add的时候,第三个参数会被抛弃。因此最终的输出结果是3。
2. argument有个属性叫callee,它指向拥有argument的函数。这个属性经常用在递归函数之中。
我们先来看一个递归函数:
function power(base, exponent) { if (exponent == 1) { return base } return base * power(base, exponent - 1);}console.log(power(2, 3)); // 8
在上述代码中,函数power用来用求base的exponent次方。当我们在其他地方不再使用名字power去定义其他函数和变量的时候,上述代码是没有问题的。但我们也要注意到,这个递归函数的功能和power这个名字是紧密耦合在一起的。一旦我们重新定义power这个名字的意义,就有可能导致问题。
解决这个问题的方法就是用argument的callee属性去解耦。上面的代码可以改写成如下代码:
function power(base, exponent) { if (exponent == 1) { return base; } return base * arguments.callee(base, exponent - 1);}var realPower = power;power = function (num1, num2) { return num1 + num2;}console.log(realPower(2, 3)); // 8console.log(power(2, 3)); // 5
在修改之后的代码中,我们用argument.callee递归定义函数power。在定义一个新的变量realPower指向该函数之后,我们让power指向新的函数。这样即使函数power的功能已经发生改变,但乘方的功能仍然得以保全。
另外一个需要用到argument.callee的场景,就是我们需要在一个匿名函数体的内部需要调用函数自身。由于函数是匿名的,我们不能在代码中通过指明函数名来调用该函数。这个时候,我们可以使用argument.callee。比如如下代码:
var numbers = [1, 2, 3, 4, 5];setTimeout(function () { console.log(numbers.shift()); // if there are some elements left, set another timer if (numbers.length > 0) { setTimeout(arguments.callee, 100); } else { console.log("finished"); }}, 100);
上述代码的作用是每隔100毫秒打印出数组中剩余数字的第一个。
在第一个调用setTimeOut函数的地方,我们定义了一个匿名函数作为setTimeOut的参数。当数组中还剩余数字是,我们需要重新调用setTimeOut以便打印下一个数字。在第二次调用setTimeOut的时候,它的第一个参数应该是和第一次调用时的参数是同一个函数。但由于我们为setTimeOut函数定义的参数是一个匿名函数,我们不知道它的名字。这个时候我们可以通过argument.callee来指定这个函数。
- 不一样的JavaScript(4)——函数参数
- 不一样的JavaScript(6)——函数调用
- 不一样的Javascript(10)——函数嵌套
- 不一样的Javascript(11)——函数与对象
- 不一样的JavaScript(1)——循环
- 不一样的JavaScript(2)——属性
- 不一样的JavaScript(3)——比较
- 不一样的JavaScript(5)——变量作用域
- 不一样的JavaScript(7)——数组
- 不一样的Javascript(8)——基本语法
- 不一样的Javascript(9)——基本类型
- 不一样的Javascript(12)——prototype
- 不一样的Javascript(14)——继承
- 不一样的Python(7)——函数
- 4、不一样的C++系列--函数的默认参数和占位参数
- 不一样的Javascript(13)——模块化与命名空间
- JavaScript不一样的语法
- javascript不一样的写法
- magento后台进入错误-----未完待续……
- 数据结构学习笔记(3.线性表之静态链表及柔性数组)
- 致学弟学妹们的一封信
- USACO 4.2.2 stall4
- 解决Ubuntu在laptop-mode(电池供电模式)下USB鼠标失效问题
- 不一样的JavaScript(4)——函数参数
- socket.io房间订阅功能
- C++类访问控制(public/protected/private)
- UIView你知道多少
- linux下安装项目管理工具redmine
- C++11右值引用
- iBatis入门
- 黑马程序员_22 交通灯管理系统
- Android XML文件读写