今天来谈谈函数的参数。参数是函数的重要组成部分,函数有四大组成部分。1:定义函数的关键字 :function ;2:函数名(也是函数的空间地址的指针,当然匿名函数除外);3:参数;4:函数的执行语句(也是函数体)。其中参数占很大比重。可以这么说,理解了参数,就理解了函数。
参数分为形参和实参。我们知道,函数是我们封装好的一个随时拿来用的工具,解决问题。解决问题,我们需要解决问题的材料,这些材料,刚开始,我们并不知道是什么具体的材料,只知道用几个材料,所以,我们用变量来表示,写在函数名的小括号内,也就是放在函数的内存地址里。所以,我们可以这样理解参数,也是函数的局部变量。参数也是存放数据的。也是我们来参与程序计算逻辑运行用的。
在js当中,参数的含义和其他的编程语言不一样,不介意传递进来多少参数。也不介意传递的参数是什么类型的。因为js是一门弱类型语言。在js函数的参数内部有一个重要的属性,就是arguments属性。它是数组(Array)的同胞胎兄弟,但不是数组的实例。它有length属性,可以通过访问数组元素的方式来访问传递参数的具体值和个数。(也就是通过下标的方式【index】),当然,js的函数也可以没有参数,也就是无参的情况。也可以传递很多参数,因为参数有数组中的属性。可以自动根据具体的元素的个数来自动加载。比如,我们可以这样写:
function sayHi () {
alert("Hello" +arguments[0]+","+arguments[1]); // 这样就是来表示函数的参数。但是我们一般不这样写。
}
function sayHi() {
alert("Hello Word"+arguments[0]+","+arguments[1]);
}
sayHi("name","age");
function howmaneyArs () {
alert(arguments.length);
}
howmaneyArs("string",45);
howmaneyArs();
howmaneyArs(12);
我们可以利用这个特点来让函数能够接受任意个参数并分别实现适当的功能。
function doAdd(num1,num2) {
if (arguments.length==1) {
alert(num1+10);
}else if(arguments.length == 2) {
alert(arguments[0]+num2);
}
}
doAdd(10);
关于arguments的行为,还有一点比较有意思。那就是它的值永远与对应的命名参数的值保持同步。还要注意一点:arguments的长度是有传入的参数的个数决定的。不是你定义的参数个数决定的。
我们在传参时,要注意很多方面。第一是:我们要在形参和实参上个数保持一致性。第二是:我们在传参时,要注意参数的数据类型。要符合语法要求。传参变量,要注意变量是否保存值。要不,转化为其它类型的数据类型。比如是字符串。
我们来具体的谈谈的传递参数的理解。
1:复制变量值。
基本类型的值和引用类型的值。
我们为一个变量赋值的时候,要注意的是:是基本类型的值还是引用类型的值。这很关键。
基本类型的值是按值访问的。因为可以保存实际的值。不能给基本类型的数据动态的添加属性和方法。不然,系统会报错。只能按值来访问。
引用类型的值是按照引用访问的。因为引用的值是保存在内存对象中的。与其它语言不同的是,js不允许直接访问内存中的位置。也就是说,不能直接操作对象的内存空间。在面向对象的系统中,我们为对象添加属性和方法是动态的,我们可以通过对象点属性名可以访问属性值的。访问方法的时候,略有区别。因为对象的方法是函数类型的(function)的,所以,和调函数的方法是一样的。对象点函数名+小括号就可以了。这就是动态的含义。可以直接访问,添加,删除等的操作。这是引用类型的保存值与基本类型的保存值不同的地方。
在一个变量向另一个变量复制基本类型值和引用类型的值,也存在不同的地方。我们来看看一个变量向另一个变量复制基本类型的值的情况,
var num1 = 5;
var num2 = num1; // 会在变量对象上创建一个新的值。然后把该复制到新变量分配的位置上了。也就是说,每个var 的变量的声明就是开辟一个新的空间,在操作上互不干涉的。
我们来看看引用类型的在一个变量向另一个变量的复制的情况。
//在引用类型的复制情况。
var obj1 = new Object(); // 创建一个对象。
var obj2 = obj1; //同样是复制到一份副本到为新的对象分配新的空间。但是不同的是,这个值是个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用一个对象。因此,改变其中一个的值,就会影响其中另外的一个值。
obj1.name = "Nicholas";
obj2.name = "lee";
alert(obj1.name); // 所以,改变其中一个值,就会改变另个的值。所以是:“lee”;
我们清楚这个知识点的时候,就在函数中,传参的时候,就明白在所有的函数中是按值传递的,即使函数(function)是引用类型的。传参的时候都是按照值传递。也就是说,参数(也是局部变量)的相关操作是不会影响函数外部的变量(也就是全局变量);
函数内部的属性:
在函数内部,有两个特殊的对象:arguments 和this 上一章,我们介绍了arguments的概念。它是个类数组对象。包含着传入函数中的所有参数,虽然arguments的主要用途是保存函数的参数。但是这个对象有一个名叫做callee的属性。我们来看一下阶乘函数经典案例。
function factorial (num) {
if(num<=1){
return 1;
}else {
return num*arguments.callee(num-1); // arguments.callee 来代替函数执行的时候与函数名 紧紧媾合的弊端。为的是将来再调用函数名的时候,能够正常的进行计算。这个一般不常用,我们主要是用的比较多是this.
}
}
我们来谈谈this的理解。写在下一章了。