JavaScript高设读书笔记
几乎每个语言中都有函数这个概念,封装一个代码块,然后可以在任意地方进行调用,那么在JavaScript中的函数,首先在命名上我们要遵循的有以下规则:
- 不能把函数名命名为eval或者arguments
- 不能把参数命名为eval或者arguments
- 不能出现两个命名参数同名的情况.
函数声明和函数表达式的不同
解析器在向执行环境中在家数据时,对函数声明和函数表达式并非一视同仁,解析器会率先读取函数声明,并使其在执行任何代码之前可用,至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行.
即在代码执行前,解析器会通过一个名为函数声明提升的过程,读取并将函数声明添加到执行环境中.
###有人的地方就有江湖,有函数的地方就有参数:
ECMAScript函数的参数与大多数其他语言中函数的参数有所不同,ECMAScript函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型,原因是ECMAScript中的参数在内部是由一个数组来表示的,函数接受到的永远就是一个数组,而不关心数组中包含哪些参数,这个数组中不包含任何元素的话,也无所谓,如果包含多个元素,也没有问题,这个数组就是arguments.
事实上,arguments对象只是与数组类似,它并不是Array的实例,命名的参数只是提供便利,但不是必须的,
ECMAScript中的函数没有重载,不能像Java那样实现函数的重载,也是因为它的传入的参数是一个类数组有关,如果在js中定义了两个名字相同的函数,则函数会被重写,其函数会以最后一个函数体为准.
有了函数,有了参数,我们需要的就是在调用时给函数传递值了,那么传递值的时候,是值传递?还是引用传递呢?我们先看一下呢JavaScript中的变量
ECMAScript变量包含两种不同数据类型的值,基本类型值和引用类型值,基本类型值指的是简单的数据段,而引用数据类型值的那些可能由多个值构成的对象.
引用数据类型的值是保存在内存中的对象,与其他语言不同的是,JavaScript不允许直接访问内存中的位置,也就是不能直接操作对象的内存空间,在操作对象是,实际上是操作对象的引用而不是实际的对象,为此,引用类型的值是按引用访问的.在很多对象中,字符串以对象的形式来表示,因此被认为是引用数据类型,ECMAScript放弃了这一传统.对于引用类型的值,我们可以为其添加属性和方法,也可以改变和删除其属性和方法,1
2
3var person = new Object();
person.name = "xxx";
alert(person.name); //xxx
###那么JavaScript函数中的参数传递是怎么传递的呢?
*首先我们需要再次明白的是:函数就是一个对象,而函数名就是这个对象的地址引用
ECMAScript中所有函数的参数都是按值传递的,也就是说,把函数外部的值赋值给函数内部的参数,就像把值从一个变量赋值到另一个变量一样,在函数中参数的传递只能是按值出传递,在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量,在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化不会反应在外部,
例如:1
2
3
4
5
6
7
8function addTen(num){
num+= 10;
return num;
}
var count = 20;
var retuslt = addTen(count);
alert(count); //20
alert(result); //30
这里的函数addTen()有一个参数num,而参数实际上是函数的局部变量,在调用这个函数时,变量count作为参数被传递为函数,这个变量的值为20,于是,数值20被赋值给num来给addTen使用,在函数内部,给num+10这一操作不会影响到count,这是很容易理解的,因为我们的传递就是值传递.
但如果我们传递的是对象呢?1
2
3
4
5
6function setName(obj){
obj.name = "blackgan";
}
var person = new Object();
setName(person);
alert(person.name); //blackgan
以上代码中创建一个对象,并将其保存在了变量person中呢 ,然后,这个对象被传递到了setName()函数中,之后被复制给了obj,在这个函数内部,obj和person引用的是同一个对象,换句话说,即使这个对象是按值传递的,obj也会按引用来访问同一个对象,于是,当在函数内部为obj添加name属性后,函数外部也有了反应,因为person在堆栈中指定的对象只有一个,而且是全局对象,但这很容易就让我们理解成:在函数的局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的,那么为了证明这种说法是否正确,我们来在看一个例子1
2
3
4
5
6
7
8function setName(obj){
obj.name = "nic";
obj = new Object();
obj.name = "grag";
}
var person = new Object();
setName(person);
alert(person.name); //"nic"
这个例子与前一个例子的唯一区别,就是在setName()函数中添加了两行代码:
先为obj重新定义了一个对象,另一行代码为该对象定义了一个带有不同值的name属性,在把person传递给setName()后,其name属性被设置为了”nic”;如果person是按引用传递的,那么person就自动会被修改为指向其name属性值为”grag”的新对象,但是当我们再次返回person.name时,显示的值是nic,所以可以看得出来参数的传递是按值传递的;