奇妙的JavaScript函数
四、参数
在JavaScript中调用一个函数,允许传入的实参与形参不符。具体说就是:不检查参数的个数和类型,所以JavaScript中函数的使用非常的灵活。
1.不检查实参列表
function sum(a,b) { return a+b; } var result = sum(2,3); console.log("result="+result);//5 result = sum(2,3,4); console.log("result="+result);//5 result = sum(2); console.log("result="+result);//NaN表示这个结果不是一个数字,但不报错 result = sum("a","b"); console.log("result="+result);//ab |
2.可变参数
由于JavaScript不检查实参列表,所以JavaScript中的函数天生就支持可变参数,我们可以利用这一点实现非常高效的代码编写。
①形参个数
函数名.length可以返回函数声明时指定了几个形参
function sum(a,b,c) { return a+b+c; } var argumentArr = []; for(var i = 0; i < sum.length; i++) { argumentArr[i] = i+5; } var result = sum(argumentArr[0], argumentArr[1], argumentArr[2]); console.log("result="+result); |
执行结果: |
result=18 |
②实参数组
在JavaScript函数内部有一个arguments对象可以直接使用,严格来说这个对象并不是数组,但可以当做数组来用,所以通常称为伪数组。这个数组中包含了调用函数时传入的全部实参。
function superSum() { var count = 0; for(var i = 0; i < arguments.length; i++) { var number = arguments[i]; count = count + number; } return count; }
result = superSum(1,2); console.log("superSum(1,2)="+result);
result = superSum(1,2,3); console.log("superSum(1,2,3)="+result); |
五、call()和apply()
在Java中,一个函数是不可能被任何一个对象调用的,但在JavaScript中就可以。借助函数对象自身的call()和apply()函数,函数可以被任意对象调用。
1.call()
call()函数的用法是:函数对象.call(目标对象,参数列表)
var wuDa = { name : "武大", showName : function(doWhat) { //函数中的this引用的是调用这个函数的对象 console.log(this.name + "和潘金莲"+doWhat); } }; wuDa.showName("卖炊饼");
var xiMen = { name : "西门" }; //在JavaScript中,函数可以被其他对象调用 //函数引用.call(调用函数的对象,函数执行时需要的参数); wuDa.showName.call(xiMen, "去马尔代夫看星星"); |
2.apply()
和call()的区别仅仅是要求传入参数要求是数组类型
var wuDa = { name : "武大", showName : function (wife){ console.log(this.name + "和" + wife); } }; var xiMen = { name : "西门" }; //函数对象的apply()方法,与call()函数的区别是传入的参数要求是数组类型 wuDa.showName.apply(xiMen, ["小潘潘~~~"]); |
3.实际意义
call()和apply()在JavaScript中非常广泛的用途。
①遍历数组
/* 自定义的遍历数组的函数 arr参数:要遍历的数组 callBack:让每一个数组元素都调用的回调函数 */ function myEach(arr,callBack) { for(var i = 0; i < arr.length; i++) { //遍历得到数组元素 var ele = arr[i]; //让数组元素调用回调函数 callBack.call(ele); } } |
②参与实现继承
JavaScript中并没有类的概念,所以面向对象程序设计中的很多概念都只能模拟而没有直接的支持,“继承”就是如此。
function Person(name,age) { this.name = name; this.age = age; } //如何借助已有的Person函数简化Student函数中的重复代码? function Student(name,age,subject) { //this.name = name; //this.age = age; //借助call()函数,让Student对象调用Person()函数,这样Person()函数内部的this引用的就是Student对象 Person.call(this,name,age); this.subject = subject; } //合并“子类”和“父类”的原型对象,让Student的对象是Person的实例 Student.prototype = Person.prototype; |