- 定义
- 函数字面量
var funcObj = function(param1, param2, ...){ // some code here }
- 方法
// 函数作为对象的属性时,称为方法 var obj = { methodOne: function(){ // some code here } }
- 普通函数
// 为了表示函数用于方法调用,命名使用小驼峰表示法 function funcOne(){ // some code here }
- 构造函数
// 为了表示函数用于构造对象,命名使用大驼峰表示法 function ObjectConstructor(constrParam1, constrParam2, ,...){ this.constrParam1 = constrParam1; this.constrParam2 = constrParam2; this.methodOne = function(param1, param2,,...){ // some code here } }
- 调用
- 方法调用模式
// 方法被调用时,方法的this绑定到该对象 obj.methodOne(value1, value2, ...);
- 函数调用模式
// 函数被调用时,函数的this绑定到全局对象 funcOne(value1, value2, ...);
- 构造器调用模式
// 构造器通过new操作符来创建对象,创建出来的对象带有构造器定义的属性 obj = new ObjectConstructor(constrValue1, constrValue2, ...); obj.methodOne(param1, param2, ...);
- apply调用模式
apply 方法有两个参数:- 需要绑定给this的值
- 一个类似于数组的参数arugments(用于保存函数的参数值)
// 不需要访问this,用null来代替 Math.max.apply(null, [1,2,3]); // 需要访问this function Que(string){ this.attr1 = string; } Que.prototype.getAttr1 = function(){ return this.attr1; } var obj = { attr1: objAttr1 } Que.prototype.getAttr1.apply(objAttr1); // 由于在调用时把方法Que.prototype.getAttr1中的this的值替换成了obj对象,所以方法的return this.attr1返回了obj的attr1属性,这是为什么可以使用apply“借用”其它对象的方法的原因。
注意:this的指向只有调用方法时改变,并不意味着之后Que的this一直指向obj,obj不会因此而拥有了Que的属性
- call调用模式
call方法和apply方法类似,第一个参数也是赋给this的值,之后是传递给“借用方法”的实参(可以用多个)
Math.max.apply(null, 1, 2, 3, ...);
- 匿名函数自调用
下面代码会自动执行
(function(param1, param2, ...){ // some code here })(value1, value2, ...);
值得注意的是:不过何种调用模式,调用时实参不一定要对应方法的参数个数,可以小于函数的参数个数,没有传递实参的形参值为undefined
-
返回值
函数一定有返回值,如果没有return语句,那么返回值为undefined -
扩充方法
- 将方法扩展给特定的对象
/** 用于扩展Function公共方法的方法 @name {string} 扩展方法的名称 @func {function} 扩展方法的函数体 */ Function.prototype.method = function(name, func){ if(!this.prototype[name]){ this.prototype[name] = func; } return this; } // 使用扩展方法为Number扩展一个方法 /** 当数值小于0时向上取整,当数值大于等于0时向下取整 说明:当使用Number调用该integer方法时,this指向这个Number */ Number.method('integer', function(){ return Math[this < 0 ? 'ceil' : 'floor'](this); });
- 将方法扩展给所有对象(包括全局对象如window)
/** 用于扩展Object公共方法的方法 @name {string} 扩展方法的名称 @func {function} 扩展方法的函数体 */ Object.prototype.method = function(name, func){ // 不能使用this,this.prototype不一定是Object.prototype if(!Object.prototype[name]){ Object.prototype[name] = func; } return this; } // 直接扩展一个printType的方法到Object.prototype method('printType', function(value){ console.log("类型是" + typeof(value)); });
-
递归
函数自调用称为递归,递归函数可以高效地操纵树形结构
汉诺塔问题:var hanoi = function(disc, src, aux, dst){ if(disc > 0){ hanoi(disc-1, src, dst, aux); document.writeIn('Move disc ' + disc + ' from ' + src + 'to' + dst); hanoi(disc-1, aux, src, dst); } } hanoi(3, 'Src', 'Aux', 'Dst')
-
闭包
定义:闭包就是能够读取其他函数内部变量的函数,可以理解成“定义在一个函数内部的函数“
闭包的好处可以访问定义它们的外部函数的参数和变量(除了this和arguments)var myObject = (function(){ var value = 0; return { increment: function(){ value += typeof inc === 'number' ? inc : 1; }, getValue: function(){ return value; } } })();
上面代码中的myObject函数字面量调用后会返回一个匿名对象,匿名对象含有increment和getValue两个方法。这两个方法中的value都是使用了myObject中的value变量,这个变量外部不能访问,而该匿名对象中的方法可以调用,所以该匿名函数的方法都叫做闭包。
错误的使用方式:var add_the_handlers = function(nodes){ var i; for(i = 0; i < nodes.length; i+=1){ nodes[i].onclick = function(e){ alert(i); }; } }
改良:
// 避免在循环中创建函数,helper是辅助函数 var add_the_handlers = function(nodes){ var helper = function(i){ return function(e){ alert(i); }; } var i; for(i = 0; i < nodes.length; i++){ nodes[i].onclick = helper(i); } }
-
回调函数
处理服务器响应的自然方法是:request = prepare_the_request(); // 设置请求 response = send_request_synchronously(request); // 发送请求获取响应 display(response); // 处理响应
但是,这样响应会很慢,所以现在一般使用异步请求,这是需要回调函数
request = prepare_the_request(); send_request_synchronously(request, function(response){ display(response); });
这样,一旦接受到响应会自动调用display,don't call me, i'will call you。
网友评论