一,函数定义调用
Function(函数)类型实际上是对象。每个函数都是Function类型的实例,而且都与其他引用类型一样具备属性和方法,由于函数是对象,因此函数名实际上也是一个指向函数对象的指针。
(1)典型的函数声明
function slide(arguments){
//...code
}
(2)以函数表达式的形式定义函数
var slide = function(arguments){
//...code
}
虽然上面两种方式逻辑上是等价的,但是还是有点小区别:
区别一:例一中的函数会在代码执行以前被加载到作用域中,而例二则是在代码执行到那一行的时候才会有定 义
例子
代码如下 | 复制代码 |
var loveddde = function(num1,num2){ //使用变量初始化 return num1+num2; } alert(loveddde(1,2)); function box(num1, num2){//普通函数声明 retrun num1+num2; } var box = new Function('num1','b', 'return num1+b'); |
//使用new的构造函数声明,函数是对象,函数名是指针。
函数调用自身,使用arguments.callee,实现递归
window是一个对象,而且是JS里面最大的对象,是最外围的对象
alert(typeof window); window是对象,类型是对象,window表示全局
alert(this); [object window] this目前表示的是window,因为在window的范围下
alert(typeof this)和window一模一样,所以this就是window
代码如下 | 复制代码 |
function sum(num){ if(num <=1){ return 1; }else{ return num*arguments.callee(num - 1); }} alert(sum(4)); 4! |
函数属性和方法
box.length
prototype属性
两个方法,apply()和call(),每个函数都包含这两种非继承而来的方法
代码如下 | 复制代码 |
function box(num1, num2){ return num1+num2;} function sum(num1,num2){ return box.apply(this, [num1, num2]); function sum2(num1, num2){ return box.apply(this,arguments);} function sum3(num1, num2){ return box.call(this,num1,num2);} var color = '红色的'; var box = { color=’蓝色的';}; function sayColor(){ alert(this.color);} sayColor.call(box); //蓝色的 |
函数参数设置默认值
代码如下 | 复制代码 |
function simue (){ var a = arguments[0] ? arguments[0] : 1; var b = arguments[1] ? arguments[1] : 2; return a+b; } alert( simue() ); //输出3 alert( simue(10) ); //输出12 alert( simue(10,20) ); //输出30 |
二、函数调用
1:方法调用模式。
代码如下 | 复制代码 |
请注意this此时指向myobject。 /*方法调用模式*/ var myobject={ value:0, inc:function(){ alert(this.value) } } myobject.inc() |
2:函数调用模式
请注意this此时指向window
代码如下 | 复制代码 |
/*函数调用模式*/ var add=function(a,b){ alert(this)//this被绑顶到window return a+b; } var sum=add(3,4); alert(sum) |
3:构造器调用模式
javascript语言精粹一书建议摒弃这中方式。因为有更好的方式。这里先不介绍。下次发表博文的时候贴出来。
会在这里加一个连接。
代码如下 | 复制代码 |
/*构造器调用模式 摒弃*/ var quo=function(string){ this.status=string; } quo.prototype.get_status=function(){ return this.status; } var qq=new quo("aaa"); alert(qq.get_status()); |
4:apply调用模式
==我们可以来看一个更有用的apply实例。看最下面的代码。
代码如下 | 复制代码 |
/*apply*/ //注意使用了上面的sum函数 //与myobject //这中调用方式的优点在于可以指向this指向的对象。 //apply的第一个参数就是this指针要指向的对象 var arr=[10,20]; var sum=add.apply(myobject,arr); alert(sum); |
看这个apply真正应用。bind这是一个绑定时间的函数
代码如下 | 复制代码 |
var bind=function(object,type,fn){ if(object.attachEvent){//IE浏览器 object.attachEvent("on"+type,(function(){ return function(event){ window.event.cancelBubble=true;//停止时间冒泡 object.attachEvent=[fn.apply(object)];//----这里我要讲的是这里 //在IE里用attachEvent添加一个时间绑定以后。 //this的指向不是到object对象本身所以。我们绑定的function里的this.id是无法正常工作的。 //但是如果我们用fn.apply(object) //这里可以看出我们是把apply的第一个对象也就是this的指向变更给了object所以this.id就变成了 //object.id 可以正常工作了。 } })(object),false); }else if(object.addEventListener){//其他浏览器 object.addEventListener(type,function(event){ event.stopPropagation();//停止时间冒泡 fn.apply(this) }); } } bind(document.getElementById("aaa"),"click",function(){alert(this.id)}); |
三、匿名函数
函数关键字(function )语句:
代码如下 | 复制代码 |
function fnMethodName(x) { alert(x); } |
函数字面量(Function Literals):
代码如下 | 复制代码 |
var fnMethodName = function (x) { alert(x); } |
Function()构造函数:var fnMethodName = new Function('x', 'alert(x);')
上面三种方法定义了同一个方法函数fnMethodName,第1种就是最常用的方法,后两种都是把一个函数复制给变量fnMethodName,而这个函数是没有名字的,即匿名函数。实际上,相当多的语言都有匿名函数。
四、函数字面量和Function()构造函数的区别
虽然函数字面量是一个匿名函数,但语法允许为其指定任意一个函数名,当写递归函数时可以调用它自己,使用Function()构造函数则不行。
代码如下 | 复制代码 |
var f = function fact(x) { if (x < = 1) return 1; else return x * fact(x - 1); }; |
Function()构造函数允许运行时Javascript代码动态的创建和编译。在这个方式上它类似全局函数eval()。
Function()构造函数每次执行时都解析函数主体,并创建一个新的函数对象。所以当在一个循环或者频繁执行的函数中调用Function()构造函数的效率是非常低的。相反,函数字面量却不是每次遇到都重新编译的。
用Function()构造函数创建一个函数时并不遵循典型的作用域,它一直把它当作是顶级函数来执行。var y = "global";
代码如下 | 复制代码 |
function constructFunction() { var y = "local"; return new Function("return y"); // 无法获取局部变量}alert(constructFunction()()); // 输出 "global" |
和函数关键字定义相比Function()构造器有自己的特点且要难以使用的多,所以这项技术通常很少使用。而函数字面量表达式和函数关键字定义非常接近。考虑前面的区别,虽然有消息说字面量的匿名函数在OS X 10.4.3下的某些webkit的引擎下有bug,但我们平常所说的匿名函数均指采用函数字面量形式的匿名函数。更多详细内容可以阅读《JavaScript : The Definitive Guide,
5th Edition》的Functions那章。
五、匿名函数的代码模式
昨天hedger wang在他的blog介绍了几种匿名函数的代码模式:
错误模式:其无法工作,浏览器会报语法错。
代码如下 | 复制代码 |
function () { alert(1); } (); |
函数字面量:首先声明一个函数对象,然后执行它
代码如下 | 复制代码 |
。(function () { alert(1); })(); |
优先表达式:由于Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数
代码如下 | 复制代码 |
。(function () { alert(2); } ()); |
Void操作符:用void操作符去执行一个没有用圆括号包围的一个单独操作数。
代码如下 | 复制代码 |
void function () { alert(3); } () |
这三种方式是等同的,hedger wang因为个人原因比较喜欢第3种,而在实际应用中我看到的和使用的都是第1种