Javascript笔记 - javascript中的函数

C语言中函数是顶级的实体,而Java中函数时被对象包装起来的。

在Javascript中,函数本身也是一个对象。

在Javascript中,函数的使用方式如下:

① 赋值给一个变量 ② 作为一个对象的属性 ③ 作为函数的一个参数 ④ 作为函数的返回结果 ⑤ 用字面量来创建

1、函数对象:

1.1、创建函数的方法:

1.1.1、通过Function构造器创建函数:

var funcName = new Function( [argname1, [… argnameN,]] body );

参数列表中可以任意多个参数,参数列表后面是函数体。

var add = new Function(“a”,”b”,”return(a+b)”);
alert(add(1,2));

1.1.2、通过function字面量来创建函数:

var add = function(a, b){
return a + b
}

其实这里的function关键字实际上会调用Function来创建一个对象,跟第一种创建方式本质上是一样的,只是书写方式方便了。

在Javascript中创建方法的本质是,举上面的例子来说,就是为全局对象添加额一个属性,该属性的名字为add,而属性的值是一个对象。

本质上很创建字符串是没什么区别的,都是给全局对象动态的增加一个新的 属性而已:

var message =”Hello World!!!”;

下面通过一个给函数添加属性的例子来说明函数也是一个独立的对象:

var add = function(a, b){
return a + b
}
var message =”Hello World!!!”;
//函数既对象
function add(a, b){
return a + b;
}
add.message = “add method!”;
alert(add);
alert(add.message);
alert(add(1,2));

1.2、函数的参数:

在Javascript中,你可以传递给任意多个参数传递给一个函数,既使这个函数声明时并没有制定形式参数:

function addMethod(a, b, c){
alert(c); //输出为undefined
return a + b + c;
}
alert(addMethod(1 ,2)); //输出为NaN

上面的例子中,形式参数为3个,而我们传递了2个参数,结果可见,第三个参数为undefined。事实上,Javascript在处理函数的参数时,与其他的编译型语言不一样,解释器传递的是一个类似于数组的内部值arguments,这个在函数对象生成的时候就被初始化为了,数组的每个元素都初始化为undefined。这样才可以在函数中处理那些没有被传进来的参数(都初始化为了undefined),从而实现可以处理任意个数的参数。

现在我们在上面的addMethod(a, b, c);方法中传入多余的参数,也是可以的:

alert(addMethod(1 ,2 ,3,4)); //输出为6

下面是一个统计的例子,在函数中通过arguments获得传入进来的参数数组:

//函数的参数的例子
function sum(){
var result = 0;
for(var i=0; i < arguments.length; i++){
if(isNaN(arguments[i])){
alert(“输入了非法的参数!”);
return;
} else {
result += arguments[i];
}
}
return result;
}
alert(sum(“a”,2,3));

1.3、函数的作用域:

Javascript中的变量的作用于是函数体内有效而无块作用域,这点要与其他的面向对象的语言区分开来。

下面展示了在块中定义的一个变量在块之外还可以访问的例子:

function printInfo(){
for(var i=0; i<10; i++){

}
alert(i);

}
printInfo();

在for循环执行后,外部仍然可以访问for循环中的i变量,只因为它们都在同一个函数中。

Javascript的函数是在局部作用域内运行的,在函数的局部作用域内可以访问函数体外部的变量和函数。

Javascript的作用域为词法作用域:在定义时(词法分析时)就确定下来了,而不是在执行时确定的,如下例:

//词法作用域
var testCon = “arthinking”;
function testScope(){
alert(testCon); //输出undefined
var testCon = “Jason”;
alert(testCon); //输出Jason
}
testScope();

在上面的例子中,词法分析结束后,在构造作用域链时,会将函数内定义的var变量testCon放入该作用域链,所以在testScope()函数内testCon变量都是可见的。由于在函数作用域中,第一行时testCon是未定义的,所以输出了undefined。

如果不在testScope中重新定义testCon变量,则第一个输出为”arthinking”:

var testCon = “arthinking”;
function testScope(){
alert(testCon); //输出arthinking
testCon = “Jason”;
alert(testCon); //输出Jason
}
testScope();

1.4、函数上下文:

与传统的面向对象编程不一样,一般的面向对象编程如Java,方法只能依赖于某个存在的类,所以方法的上下文总是在某个类中的。

而在Javascript中,函数也是一种对象。理解这一点对于理解函数式编程尤为重要,即在函数式编程中,函数被认为是处于第一级位置的。

而在Javascript等函数式编程中,函数内的this指针式可以变化的。函数可以作为一个对象的方法,也可以作为另一个对象的方法,也就是函数本身是独立的。

可以使用Function对象的call或者apply函数来修改函数的上下文:

使用call和apply修改函数上下文:

下面是一个例子:

//函数的上下文
var user1 = {
name : “arthinking”
}
var user2 = {
name : “Jason”
}
function getUsername(){
return this.name;
}
alert(getUsername.call(user1));
alert(getUsername.apply(user2));

传递多个参数的例子:

如果有需要改变this的函数需要传入多个参数,call方法需要在传入的对象之后跟若干个参数,以逗号分隔。apply方法则是在传入的对象之后跟一个参数数组,下面是使用例子:

var user1 = {
name : “arthinking”
}
var user2 = {
name : “Jason”
}
function getUsername(){
return this.name;
}
function setUsername(firstName, lastName){
this.name = firstName + “ “ + lastName;
}
setUsername.apply(user1, [“arthinking”, “Peng”]);
setUsername.call(user2, “Jason”, “Peng”);
alert(getUsername.call(user1));
alert(getUsername.apply(user2));

2、使用函数:

在Javascript中,函数的使用方式如下:

2.1、赋值给一个变量

//赋值给一个变量
function add(a, b){
return a + b;
}

var a = add;
var result = a(1, 2);
alert(result);

这里a引用了add,也就是a的值是一个函数对象(一个可执行的代码块)。

2.2、作为一个对象的属性

//赋值给一个函数属性
function add(a, b){
return a + b;
}
var obj = {
name : “An Object”
}
obj.func = add;
alert(obj.func(1, 2));

该例子和上一个例子实际上是一样的,第一个例子中的变量a其实也就是全局对象window中的一个属性。

2.3、 作为函数的一个参数

//作为函数的参数来传递
function processor1(str){
return “arthinking: “ + str;
}
function processor2(str){
return “Jason: “ + str;
}
function speek(str, handler){
alert(handler(str));
}

speek(“Good Job!”, processor1);
speek(“Good Job!!!”, processor2);

可见,可以通过函数名来传递函数。

2.4、作为函数的返回结果

//作为函数的返回结果
function sing(){
alert(“想唱就唱,要唱的响亮。”);
}
function getLRC(){
return function(){
alert(“想唱就唱,要唱的响亮。”);
}
}
getLRC()();

注意,这里由于使用了匿名函数,返回的只是这个函数的字面值,如果想要返回该匿名函数的执行结果,则需要按照上面的形式书写:getLRC()(); 第一个括号表示调用getLRC本身,此时返回值为函数,第二个括号表示调用这个返回的函数。相当于这样:

//作为函数的返回结果
function sing(){
alert(“想唱就唱,要唱的响亮。”);
}
function getLRC(){
return sing;
}
getLRC()();

当然,如果不是匿名函数,也可以在返回的时候写括号:

//作为函数的返回结果
function sing(){
alert(“想唱就唱,要唱的响亮。”);
}
function getLRC(){
return sing();
}
getLRC();

arthinking wechat
欢迎关注itzhai公众号