标签:style blog http color io 使用 ar java strong
定义函数的方法:
函数声明:
function functionName(arg0, arg1, arg2){
//函数体
}
Firefox、Safari、Chrome和Opera给函数定义了name属性,其值等于function关键字后面的标识符。
函数提升:执行代码前先读取函数声明。
使用函数表达式:
var functonName = function (arg0, arg1, arg2){
//函数体
}
创建的函数叫匿名函数,name属性为空字符串。
函数表达式在使用前必须先赋值。
一个函数通过名字调用自身的情况下构成的。
var anotherFactorial = factorial; factorial = null; alert(anotherFactorial(4)); //error!
调用anotherFactorial时,由于必须执行factorial,而factorial不是函数而出错。
arguements.callee是一个指向正在运行的函数的指针,可以用来实现对函数的递归调用。
严格模式下不能通过脚本访问arguements.callee,但可以通过命名函数表达式来实现。
闭包:有权访问另一个函数作用域里的变量的函数。
创建闭包最常见的方法是在一个函数内部再创建一个函数。
function compare(value1, value2){ if (value1 < value2){ return -1; } if (value1 > value2){ return 1; } else { return 0; } }
当调用compare()时,会创建一个包含arguemnets,value1,value2的活动对象。后台的每个执行环境都有一个表示变量的对象——变量对象。全局环境的变量对象始终存在,compare()函数的局部环境的变量对象只在函执行的过程存在。创建compare()函数时,会预先创建一个包含全局变量对象的作用域链,它被保存在内部的[[Scope]]中。调用compare时,会为函数创建一个执行环境,通过复制函数的[[Scope]]属性的对象构建执行环境的作用域链。作用域链本质是一个指向变量对象的指针,只引用不实际包含变量对象。
createComparisonFunction()函数在执行完毕以后,其活动对象不会被销毁,因为匿名函数的作用域链仍然在引用它,匿名函数被销毁后, createComparisonFunction()的活动对象才会被销毁。
//创建函数 var compare = createComparisonFunction("name"); //调用函数 var result = compare({ name : "Nicholas"}, { name : "Greg"}); //解除对匿名函数的调用 compare = null;
闭包只能取得包含函数中任意变量的最后一个值。闭包保存的是整个变量对象,
function createFunctions(){ var result = new Array(); for (var i=0; i < 10; i++){ result[i] = function(){ return i; }; } return result; }
每个函数的作用域链都保存着createFunctions()函数的活动对象,它们引用的是同一个变量i,当createFunction()函数返回时,变量i的值是10,每个函数都引用着保存变量i的同一个变量对象。
for (var i=0; i < 10; i++){ result[i] = function(num){ return function(){ return num; }; }(i); }
创建一个匿名函数,将立即执行该匿名函数的结果赋值给数组。由于函数参数按值传递,i变量的当值复制给num,在匿名函数内部又创建并返回一个访问num的闭包。
匿名函数的执行环境有全局性,其this对象通常指向window。
内部函数在搜索this和arguements时只会搜索到其活动对象为止,不可能直接访问外部函数的这两个变量。
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } };
把外部作用域的this对象保存在一个闭包能访问的变量里,就能让闭包访问该对象了。即使在函数返回后,that也引用着object。
getNameFunc : function(){ var that = this; return function(){ return that.name; }; }
如果闭包的作用域链保存着一个HTML元素,该元素将无法销毁。
通过把element.id的一个副本存在一个变量,并且在闭包中引用该变量消除了循环引用。还有必要把element变量设置为null。
在块语句中定义的变量是在包含函数中而非语句中创建的。
javascript中多次声明同一个变量,会对后续声明的视而不见。
私有作用域的匿名函数:
(function(){ //块级作用域 })();
将函数声明包含在圆括号内,表示它实际是一个函数表达式,后面的另一对圆括号会立即调用这个函数。
function(){ }(); //出错
javascript把function关键字作为一个函数声明的开始,函数声明后面不能有圆括号。而函数表达式后面可以有圆括号。
只要临时要一些变量,就能使用私有作用域。
function outputNumbers(count){ (function () { for (var i=0; i < count; i++){ alert(i); } })(); alert(i); //出错 }
在匿名函数定义的任何变量,在执行结束时被销毁。私有作用域能访问count是因为这个匿名函数是一个闭包,能访问包含作用域的所有变量。
这种技术经常用在全局作用域中被用在函数外部,限制向全局作用域添加过多变量和函数。
任何在函数定义的变量,都可认为是私有变量。私有变量包括函数的参数、局部变量和函数内部定义的其他函数。
特权方法:有权访问私有变量和私有函数的公有方法。
在构造函数定义:
function MyObject() { //私有变量和私有函数 var privateVariable = 10; function privateFunction() { return false; } //特权方法 this.publicMethod = function () { privateVariable++; return privateFunction(); } }
特权方法作为闭包有权访问构造函数中的所有变量和函数。
function Person(name){ this.getName = function(){ return name; };
//特权方法
this.setName = function (value) { name = value; }; } var person = new Person("Nicholas"); alert(person.getName()); //"Nicholas" person.setName("Greg"); alert(person.getName()); //"Greg"
通过私有作用域中定义私有变量或函数创建特权方法。
(function(){ var name = ""; Person = function(value){ name = value; }; Person.prototype.getName = function(){ return name; }; Person.prototype.setName = function (value){ name = value; }; })();
name成为静态的、由所有实例共享的属性。在一个实例上调用setName()会影响所有实例。创建一个Person实例或调用setName()都会赋予name实例一个新值。
前面的模式用于自定义类型创建私有变量和特权方法的。
模块模式为单例创建私有变量和特权方法。
单例:只有一个实例的对象。
这种模式在需要对单例进行某些初始化,同时又需要维护其私有变量时是非常有用的。
function BaseComponent(){ } function OtherComponent(){ } var application = function(){ //私有变量和函数 var components = new Array(); //初始化 components.push(new BaseComponent()); //公共 return { getComponentCount : function(){ return components.length; }, registerComponent : function(component){ if (typeof component == "object"){ components.push(component); } } }; }(); application.registerComponent(new OtherComponent()); alert(application.getComponentCount()); //2
这里创建一个用来管理组件的对象。返回对象的getComponentCount方法和registerComponent方法都有权访问components的特权方法。
如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有变量数据的方法,可以用模块模式,这样创建的每个单例都是Object的实例,因为要用对象字面量来表示。
这种增强的模块模式适合那些单例必须是某种类型的实例,同时还必须添加某些属性和(或)方法对其加以增强的情况。
var application = function(){ //私有变量和函数 var components = new Array(); //初始化 components.push(new BaseComponent()); //创建application的一个局部副本 var app = new BaseComponent(); //公共接口 app.getComponentCount = function(){ return components.length; }; app.registerComponent = function(component){ if (typeof component == "object"){ components.push(component); } }; //返回这个副本 return app; }();
标签:style blog http color io 使用 ar java strong
原文地址:http://www.cnblogs.com/surahe/p/3994214.html