你的位置:首页 > Java教程

[Java教程]javascript中的函数Function


[1]三种函数定义的方式
[1.1]函数声明:使用function关键字,后跟一组参数以及函数体
[注意]函数的形参之间用逗号分割,因为是声明多个变量,不是多个语句,所以用逗号分隔,而不是分号
function sun(num1,num2){
  return num1+num2;
}
[1.2]函数表达式
var sum = function(num1,num2){
  return num1+num2
}
[1.3]Function构造函数
var sum = new Function('num1','num2','return num1 + num2');
//[不推荐]会导致解析两次代码,第一次解析常规ECMAScript代码,第二次解析传入构造函数中的字符串,影响性能

[tips]函数声明与函数表达式的区别:
[a1]解析器会率先读取函数声明,并使其在执行任何代码之前可用
[a2]至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行
[b]如果将函数表达式放在对函数的引用语句之后,会弹出"unexpected identifier"意外标识符错误
[c]除了什么时候可以通过变量访问函数这一点区别之外,函数声明与函数表达式的语法其实是等价的

 

[2]函数参数
[2.1]函数参数在内部是用一个数组来表示的,在函数内部可以通过arguments对象来访问这个参数数组
[2.2]形参只提供便利,但不是必须的
[2.3]开发人员可以利用argument.length属性让函数能够接收任意个参数分别实现适当的功能
[2.4]没有传递值的形参默认为undefined
[2.5]函数参数也被当作变量来对待,因此其访问规则与执行环境中的其他变量相同
[2.6]arguments对象可以和形参一起使用,它的值与对应形参的值保持一致。但形参数组和arguments对象并不指向同一内存空间,它们的内存空间是独立的,但值会同步。
e.g. function doAdd(num1,num2){
  arguments[1] = 10;
  //[注意1]若未传入num2,num2 == undefined,并不会被赋值为10,而arguments[1] == 10
  //[注意2]若传入num2,则 num2 == arguments[1] == 10,二者都等于10
  //[注意3]在严格模式下,不允许为arguments赋值,但允许为arguments[n]赋值
  alert(arguments[0] + num2);
}
doAdd(1,2);//11
doAdd(1);//NaN 因为 1 + Number(undefined) == 1 + NaN == NaN

[2.7]所有参数传递的都是值,不可能通过引用传递参数

function setName(obj){  obj.name = 'Nicholas';  obj = new Object();  obj.name = 'greg';}var person = new Object();setName(person);alert(person.name);//'Nicholas'

[tips]严格模式的限制

[a]不能把函数命名为eval或arguments
[b]不能把函数参数命名为eval或arguments
[c]不能出现两个命名参数同名的情况

[3]函数返回值:通过return语句后跟要返回的值来实现返回值,未指定返回值的函数则默认返回undefined
  [注意]位于return语句之后的任何代码都永远不会执行

 

[4]函数重载:ECMAScript函数没有重载,不存在函数签名的特性,因为其函数参数是以一个包含零或多个值的数组的形式传递的。
  [注意]通过检查传入函数中参数的类型和数量并作出不同的反应,可以模仿方法的重载。


[5]函数的属性
[5.1]this:引用的是函数据以执行的环境对象,当在网页全局作用域中调用函数时,this对象引用的是window
  [注意]在严格模式下,未指定环境对象而调用函数,则this值不会转型为window,除非明确把函数添加到某个对象或者调用apply()或call(),否则this值将是undefined
[5.2]arguments:一个类数组对象,包含着传入函数中的所有参数
[5.2.1]arguments下有一个名为callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数
  [注意]当函数在严格模式下运行时,访问arguments.callee会导致错误
  [tips]阶乘函数

function factorial(num){  if(num <=1){    return 1;  }else{    return num* factorial(num-1);  }}    

若使用arguments.callee可以消除函数解耦

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

[5.3]length:表示函数希望接收的命名参数的个数
[5.4]prototype:在ECMAScript5中,prototype属性是不可枚举的,因此使用for-in无法发现
[5.5]caller(ECMAScript5):除了Opera的早期版本不支持,其他浏览器都支持ECMAScript3并没有定义的属性。这个属性保存着调用当前函数的函数的引用。如果是在全局作用域中调用当前函数,它的值为null
  [注意1]ECMAScript5还定义了arguments.caller属性,在严格模式下访问它也会导致错误,而在非严格模式下这个属性始终是undefined,定义这个属性是为了分清arguments.caller和函数的caller属性
  [注意2]严格模式还有一个限制:不能为函数的caller属性赋值,否则会导致错误

window.color = 'red';var o = {color: 'blue'};function sayColor(){  alert(this.color);}sayColor();//'red'o.say = sayColor;o.say();//'blue'

function outer(){  inner();}function inner(){  alert(inner.caller);}outer();//弹出function outer(){inner()};//为了更松散的耦合,可以改为这样:function outer(){  inner();}function inner(){  alert(arguments.callee.caller);}outer();

 

[6]函数的方法:apply和call这两个方法都是用于在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。最大的好处是对象不需要与方法有任何耦合关系,这两个方法的强大地方在于能够扩充函数的作用域。

[6.1]apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。第二个参数可以是Array()的实例,也可以是arguments对象。
[6.2]call()方法与apply()方法相同,区别仅仅在于接受参数的方式不同,在使用call()方法时,传递给函数的参数必须逐个列举出来,而apply方法接收arguments对象或一个数组
[6.3]bind()(ECMAScript5):创建一个函数的实例,其this值会被绑定到传给bind()函数的值

function sum(num1,num2){  return num1+num2;}function callSum1(num1,num2){  return sum.apply(this,arguments);}function callSum2(num1,num2){  return sum.apply(this,[num1,num2]);}function callSum00(num1,num2){  return sum.call(this,num1,num2);}function callSum01(num1,num2){  return sum.bind(this,num1,num2)();}alert(callSum00(10,10));//20alert(callSum01(10,10));//20alert(callSum1(10,10));//20alert(callSum2(10,10));//20

var color = 'red';var o = {color: 'blue'};function sayColor(){  alert(this.color);}sayColor();//redsayColor.call(this);//redsayColor.apply(this);//redsayColor.bind(this)();//redsayColor.call(window);//redsayColor.apply(window);//redsayColor.bind(window)();//redsayColor.call(o);//bluesayColor.apply(o);//bluesayColor.bind(o)();//blue

 

[7]继承的方法:始终返回函数代码(因浏览器而异,有的返回的代码与源代码中的函数代码一样。有的删除了注释并对某些代码做了改动)
  [a]toLocaleString()
  [b]toString()
  [c]valueOf()

 

[8]函数的应用
[8.1]函数成为参数
function callSomeFunction(someFunction,someArgument){
  return someFunction(someArgument);
}
[8.2]从一个函数返回另一个函数
  [tips]根据属性名创建比较函数

function createComparisonFunction(propertyName){  return function (object1,object2){    var value1 = object1[propertyName];    var value2 = object2[propertyName];    if(value1 < value2){      return -1;    }else if(value1 > value2){      return 1;    }else{      return 0;    }  };}  

[8.3]为函数形参添加默认值 

function G(id){  var id = id || 'div1';//为函数形参添加默认值来替代undefined  document.getElementById('id').innerHTML = '内容1'}