[TOC]javascript
argument.callee:一个指向正在执行函数的指针,严格模式下会出错 命名函数表达式,严格和非严格都不会出错java
var factorial = (function f(num){ if (num <= 1){ return 1; }else { return num * f(num - 1); } });
闭包是指有权访问另外一个函数做用域中变量的函数 建立闭包的常见方式:在一个函数内部建立另外一个函数 过分使用闭包会致使内存占用过多,要慎重使用闭包
闭包只能取得包含函数中任何变量的最后一个值app
function createFunctions(){ var result = new Array(); for (var i=0; i < 10; i++){ result[i] = function(){ return i; }; } return result; }
表面看每一个函数都返回本身的索引值,实际上每一个函数都返回10 由于每一个函数的做用域链中都保存着createFunctions()函数的活动对象,它们引用同一变量 能够建立另外一个匿名函数让闭包行为符合预期函数
function createFunctions(){ var result = new Array(); for (var i=0; i < 10; i++){ result[i] = function(num){ return function(){ return num; }; }(i); } return result; }
匿名函数的执行环境具备全局性,this对象一般指向windowthis
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()); //"The Window"
把外部做用域中的this对象保存到闭包可以访问到的变量中prototype
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()()); //"MyObject"
若是闭包的做用域链保存着一个HTML元素意味着该元素将没法被销毁指针
function assignHandler(){ var element = document.getElementById("someElement"); element.onclick = function(){ alert(element.id); }; }
匿名函数对assignHandler()活动对象的引用,element引用次数最少是1,占用内存没法被回收 修改代码解决内存泄漏问题code
function assignHandler(){ var element = document.getElementById("someElement"); var id = element.id; element.onclick = function(){ alert(id); }; element = null; }
(function(){ //这里是块级做用域 })();
匿名函数中定义的变量执行后销毁 不会搞乱全局做用域component
私有变量包括函数的参数,局部变量和函数内部定义的其余函数 特权方法:有权访问私有变量和私有函数的公有方法成为特权方法
静态的,由全部实例共享的属性
(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"
模块模式:为单例建立私有变量和特权方法 单例:只有一个实例的对象 JavaScript中用对象字面量的方式建立单例对象 若是建立一个对象并以某些数据对其初始化,同时还要公开一些访问私有数据的方法,就能够用模块模式
function BaseComponent(){ } function OtherComponent(){ } var application = function(){ //private variables and functions var components = new Array(); //initialization components.push(new BaseComponent()); //public interface return { getComponentCount : function(){ return components.length; }, registerComponent : function(component){ if (typeof component == "object"){ components.push(component); } } }; }(); application.registerComponent(new OtherComponent()); alert(application.getComponentCount()); //2
返回对象以前加入对其加强的代码 适合单例必须是某种类型的实例,同时还必须添加某些属性和方法对其加以加强的状况
function BaseComponent(){ } function OtherComponent(){ } var application = function(){ //private variables and functions var components = new Array(); //initialization components.push(new BaseComponent()); //create a local copy of application var app = new BaseComponent(); //public interface app.getComponentCount = function(){ return components.length; }; app.registerComponent = function(component){ if (typeof component == "object"){ components.push(component); } }; //return it return app; }(); alert(application instanceof BaseComponent); application.registerComponent(new OtherComponent()); alert(application.getComponentCount()); //2