七
函数
法一
函数声明
function functionName(arg0,arg1,arg2){
//函数体
}
alert(functionName.name);//functionName,只在Firefox,safri,Chrome和Opero有效
函数声明提升,在执行代码前先读取函数声明
sayHi();
function sayHi(){
alert("Hi");
}
//不会抛出错误,在代码执行前会先读取函数声明
法二
使用创建函数的方式使用函数表达式
var functionName=function(arg0,arg1,arg2){
// 函数体
}
//函数表达式和其他表达式一样,在使用前必须赋值。
sayHi();//错误,函数不存在
var sayHi=function(){
alert("Hi!");
};
递归;
递归函数是在一个函数通过名字调用自身的情况下构成的
function factorial(num){
if(num<=1){
return 1;
}else{
return num*factorial(num-1);
}
}
使用argument.callee是一个指向正在执行的函数的指针,因此可以用他来实现对函数的递归调用
function factorial(num){
if(num<=1){
return 1;
}else{
return num*arguments.calee(num-1);
}
}
在严格模式下使用这种方式进行递归调用最为规范
var factorial=(function f(num){
if(num<=1){
return 1;
}else{
return num*f(num-1);
}
});
//即便把函数值赋给另一个变量,函数的名字f仍然有效。
闭包
闭包是指有权限访问另一个函数作用域的变量的函数,
创建闭包的常见方式就是在一个函数内部创建另一个函数,
就是内部函数,
function createFunctions(){
var result=new Array();
for(var i=0;i<10;i++){
result[i]=function(){
return i;
};
}
return result;
}
//每个函数都会返回10,因为每个函数的作用域链中
都保存着createfunctions()函数的活动对象。所以他们引用的都是同一个变量i.
当createfunctions()函数返回后,变量i的值是10;
//使用匿名函数强制让闭包的行为符合预期
function createFunctions(){
var result=new Array();
for(var i=0;i<10;i++){
result[i]=function(num){
return function(){
return num;
};
}(i);
return result;
}
//返回0,1,2,3,4,5,6,7,8,9
关于this对象;
this对象是在基于函数的执行环境绑定的,在全局函数中,this等于window,
而当函数被作为某个对象的方法调用时,
this等于那个对象。匿名函数的执行具有全局性,因此其this对象通常指向window.
例如
var name="The window";
var object={
name:"My Object",
getNameFunc:function(){
return function(){
return this.name;
};
}
};
alert(Object.getNameFunc()());//"The window"
下例中把this对象赋给了that变量。that变量按照作用域链便会返回My Object
var name="The Window";
var object={
name:"My Object",
getNameFunc:function(){
var that=this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());//My Object;
在几种特殊的情况下,this的只会意外的改变
var name="The window";
var object={
name: "my object".
getName:function()(
return this.name;
)
};
object.getName{};//"My Object"
{object.getName}{}//"My Object"
内存泄漏
function assignHandler(){
var element=document.getElementById("SE");
element.οnclick=function(){
alert(id);
};
element=null;
}
//如果闭包的作用域链中保存着一个HTML元素,则意味着该元素无法被销毁。(此代码中已销毁)
//闭包会引用包含函数的整个活动对象,其中包含着
element.即使闭包不直接引用element,包含函数的活动对象中
也仍然会保存一个引用。因此,有必要把element变量设置为null.
这样就能解除对DOM对象的引用,确保正常回收其占用的内存。
模仿块级作用域
function outpNumbers(count){
for(var i=0; i<count;i++){
alert(i);
}
alert(i);//计数
}
//变量i定义在outpNumbers()的活动对象中的,因此从它有定义开始,就可以在函数内部随处访问他
function outpNumbers(count){
for(var i=0; i<count;i++){
alert(i);
}
var i;//重新声明变量
alert(i);//计数
}//依然会计数,结果与上例相同。
用块级作用域的匿名函数的语法
法一
(function(){
//这里是块级作用域
}){};
法二
var someF=function(){
//这里是块级作用域
};
someF();
法三
(function(){
//这里是块级作用域
})();
临时需要一些变量可以使用私有作用域,例如
function outpNumbers(count){
(function(){
for(var i=0; i<count;i++){
alert(i);
}
})();
alert(i);//导致有一个错误
}
//在匿名函数中定义的任何变量,都会在执行结束时被销毁。(可以减少闭包占用的内存问题,只要函数执行完毕,就可以立即销毁其作用域了)
私有变量
私有变量包括函数的参数,局部变量和函数内部定义的函数
function add(num1,num2){
var sum=num1+num2;
return sum;
}
//sum num1,num2都是私有变量。
有权访问私有变量和私有函数的工有方法称为特权方法。
法一:在构造函数中定义特权方法
function myObject(){
var private=10;
functon pFunction(){
return false;
}
//特权方法
this.pM=function(){
private++;
return pFunction();
};
}
用私有和特权成员可以隐藏那些不应该被直接修改的数据
function Per(name){
this.getName=function(){
return name;
};
this.setName=function(value){
name=value
};
}
var per=new Per("Nicholas");
alert(per.getName());//"Nicholas"
person.setName("Greg");
alert(per.getName());//"Greg"
//构造函数缺点:每个实例都会创建同样一组新方法
静态私有变量
1.函数声明只能创建局部函数。
通过在私有作用域中定义私有变量或函数,创建特权方法
使用函数表达式的方式
(function(){
//私有变量和私有函数
var private=10;
function privateFunction(){
return false;
}
//构造函数
MyObject=function(){
};
//公有/特权方法
MyObject.prototype.publicMethod=founction(){
private++;
return privateFunction();
};
})();
//初始化未经声明的变量,总是会创建一个全局变量
故MyObject就成了一个全局变量。能够在私有作用域外被
访问到。
(function(){
var name="";
Person=function(value){
name=value;
};
Person.prototype.getName=function(){
return name;
};
Person.prototype.setName=function(value){
name=value;
};
})();
var person1=new Person("Nicholas");
alert(person1.getName());//"Nicholas"
person1.setName("Greg");
alert(person1.getName());//"Greg"
var person2=new Person("Michael");
alert(person1.getName());//"Michael"
alert(person2.getName());//"Michael"
模块模式
为单例创建私有变量和特权方法
var singleton=function(){
//私有变量和私有函数
var privateVariable=10;
function privateFunction(){
return false;
}
//特权/公有方法和属性
return{
publicProperty:true;
publicMethod:function(){
privateVariable++;
return privateFunction();
}
};
}();
//将一个对象字面量作为函数的值返回,返回的对象字面量中只包含可以公开的的属性和方法。因此他的公有方法有权访问私有变量和函数,由于这个对象是在匿名函数内部定义的,
从本质上来讲,这个对象字面量定义的是单例的公共接口。
对模式在需要单例进行某些初始化,同时又需要维护其私有变量是非常有用的
var application=function(){
//私有变量和函数
var components=new Array();
//初始化
components.push(new BaseCompent());
//公共
return {
getComponentCount:function(){
return components.length;
},//返回注册的组件数目
registerComponent:function(component){
if(typeof component=="object"){
components.push(component);
}
}//注册新组件
};
}();
//即:如果必须创建一个对象并以某些数据对其初始化,同时还要公开一些
能够访问这些私有数据的方法。
增强的模块模式
//增强的模块模式适合那些单例必须是某种类型的实例,同时还必须
添加某些属性和(或)方法对其加入以增强的情况。
var singleton=function(){
//私有变量和私有函数
var privateVariable=10;
function privateFunction(){
return false;
}
//创建对象
var object=new CustomType();
//添加特权/公有属性和方法
object.publicProperty=true;
object.pubicMethod=function(){
privateVariable++;
return privateFunction();
};
//返回这个对象
return object;
}();