Javascript高级程序设计学习笔记(七)


函数
法一
函数声明
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   alert(i);
}
alert(i);//计数
}
//变量i定义在outpNumbers()的活动对象中的,因此从它有定义开始,就可以在函数内部随处访问他
function outpNumbers(count){
 for(var i=0; i   alert(i);
}
var i;//重新声明变量
alert(i);//计数
}//依然会计数,结果与上例相同。

用块级作用域的匿名函数的语法

法一
(function(){
//这里是块级作用域
}){};
法二
var someF=function(){
//这里是块级作用域
};
someF();
法三
(function(){
//这里是块级作用域
})();

临时需要一些变量可以使用私有作用域,例如
function outpNumbers(count){
(function(){
 for(var i=0; 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;
}();

你可能感兴趣的:(Javascript高级程序设计学习笔记(七))