犀牛书学习笔记(3):函数

所谓过程式编程(或函数式编程),最重要的语法就是函数,js虽然号称OOP语言,但实际上函式编程是更为常用且大家熟悉的编程方式。这里就几个重要概念进行说明。

总结来说,函数是js语言的第一类对象,可以被调用、赋值、传递....

函数定义

function 函数名(参数1,参数2,参数3...){

  函数体语句

  renturn 返回值;

}

说明:

1、函数体return关键字指定返回值,因为是弱对象语言,因此不需要在定义中指定函数返回值,也可以没有return语句,返回值是undefined;

2、参数不用指定类型,如果类型很重要,需要使用typeof方法进行检测。参数个数可变,且调用时个数可以不和参数个数匹配。

在函数内定义函数,叫嵌套函数。

用函数直接量定义函数,函数直接量是表达式,可以定义匿名函数。

function f(x){ return x*x;}
var f = function(x){ return x*x;};
//第一行是常规定义方式,第二行匿名函数量的方式定义函数。

虽然直接量匿名定义函数,也可以对函数命名,这在递归编程中非常有用。

var f = function fact(x){
  if (x<-1) return 1;
  else return x*fact(x-1);  
};

函数参数

函数可以以任意数目的参数来调用,而不管函数定义中参数多少,向任何函数传递任意类型的参数都是合法的。

1、可选参数

当调用函数时,参数少于申明的参数个数的时候,其他参数的值是undefined。因此希望编写某些参数可选的安全的函数,方法是为能够忽略的参数分配一个合理的默认值。但参数的顺序是必须的,因此可选参数应放在最后。

function copyPropertyNamesToArray(o,/* optional */ a){
  if(!a) a=[]; //如果undefined 或者 null,使用空数组
  for(var property in o ) a.push(property);
  return a;
}

var a = copyPropertyNamesToArray(o);
//不使用可选的参数a

copyPropertyNamesToArray(p,a);
//使用两个参数

2、Arguments对象

在函数体内,可以用arguments标示符引用auguments对象,arguments对象是一个类似数组的对象,可按照数目获取传递给函数的参数值,并定义了callee属性。

arguments.length属性返回参数个数,arguments[0]返回第一个参数的值,使用数组下标方式获取参数值。

属性callee用来引用当前正在执行的函数,可用来对未命名的函数递归调用自身。

function(x){
  if(x<=1) return 1;
  return x*arguments.callee(x-1);    
}

如何不用记住参数顺序调用参数?

前面讲到,调用函数参数个数虽然不限,但参数顺序是必须保证的,这比较麻烦。让参数以键名/值对的方式传递参数,是一个好办法。实现方法是定义一个对象,用对象属性名/值作为函数参数。

function arrayCopy(/*array*/ from,/*index*/from_start,/*array*/ to,/*index*/to_start,/*integer*/ length)
{

  // 方法代码,数组from从from_start位置开始复制长度为length的数据到到数组to从to_start位置开始,长度为length;

}

function easyCopy(args){
  arrayCopy(args.from,
                   args.from_start||0,
                   args.to,
                   args.to_start||0,
                   args.length);
}

var a=[1,2,3,4];
var b=new Array(4);
easyCopy({from:a,to:b,length:4});

函数可以作为数据赋值给变量。

function square(x) { return x*x;}
var a=square(4);    //a=16
var b=square;        //b引用到square
var c=b(5);             //c=25

函数可以复制给对象的属性,称为方法。方法其实不过是存储在对象属性中的并且通过对象来调用的函数,不过和通常函数不同的是,对象会默认给方法赋值一个对象实例,标示符是this。

var o=new Object;
o.square=function(x){ return x*x;}
y=o.square(16);

还可以复制给数组元素。

var a=new Array(3);
a[0]=function(x){ return x*x; }
a[1]=20;
a[2]=a[0](a[1]);    //a[2]=400

函数还可以作为参数传递给其他函数。

函数的属性和方法

函数是js对象的一种特殊类型,也具有属性和方法。

length属性:只读属性,返回参数个数;

prototype属性:预定义的原型对象;

函数自定义属性:可以在函数内部定义变量作为函数的属性;

apply()和call()方法:该方法可以像调用其他对象的方法一样调用函数。第一个参数是要调用的函数的值,在函数体内这个参数是关键字this,剩余参数是要传递给要调用的函数的值。

f.call(o,1,2);

等同于:
o.m=f;
o.m(1,2);
delete o.m;

函数作用域和闭包

调用对象

当js解释器调用一个函数,它首先将作用域设置为定义函数的时候起作用的那个作用域链。接下来,在作用域链前面添加一个新的对象,叫做调用对象。调用对象用arguments属性调用函数的Arguments对象,函数的命名的参数和var语句的局部变量添加到调用对象的后面。

闭包

子函数可以使用父函数中的局部变量,这种行为就叫做闭包!按照js作用域链原理,嵌入函数总是能够访问外部函数的所有参数和变量。因此,所有函数都是闭包的,嵌入函数可作为闭包使用。

原文地址:https://www.cnblogs.com/laohoo/p/3416287.html