私有作用域:跟外界的变量方法毫不冲突,豪无关系
var str ="javascript"; (function(){ alert(str); //undefined var str = "hello world"; alert(str);//hello world})(); alert(str);//javascript
语法解析:函数自执行里面可以当做块级作用域
(function(){ //块级作用域 })();
私有变量:
function Person(name){ this.setName = function(value){ name = value; } this.getName = function(){ return name; } } var people = new Person('a'); alert(people.getName());//apeople.setName('小明'); alert(people.getName());//小明alert(people.name);//undefined
这个例子就很好的阐明了私有变量的好处,以及常用的方式。目的是让私有的变量不能被外部访问到,只能有特定的方法调用。
如此一来我们有发现问题了,这里的参数name都是每一个实例单独拥有的,我如果想得到一个所有实例共享的私有变量呢?如果你有java或者其他面向对象语言的基础的话,你会发现我们要的其实就是静态私有变量,没有这些基础也没关系,你了解他的用途也是一样的,我们看下面的一段代码:
静态私有变量:所有实例共享的私有变量
(function(){ var name = ""; Person = function(value){ name = value; }; Person.prototype.setName = function(value){ name = value; }; Person.prototype.getName = function(){ return name; }; })(); var people1 = new Person("a"); console.log(people1.getName());//apeople1.setName("b"); console.log(people1.getName());//bvar people2 = new Person("小明"); console.log(people1.getName(),people2.getName());//小明 小明
通过打印出来的值发现他们是共用同一个变量name。而由于是私有作用域我们只能通过实例化的对象调用特定的方法getName才能得到name的值。
模块模式:
前面的私有变量属于模块模式,但是还有一种模式,那就是为单例创建的私有变量和特权方法。所谓的单例,就是说只有一个实例对象,共享相同的属性,我们前面的静态私有变量是多个实例对象共享相同的属性。
先给一个简单的例子体会一下单例:
var person = { name:"小明", method:function(){ //具体方法 } };
就是指大家都用的是同一个对象person。继续看看我们说的单例私有变量:
var person = function(){ var privateName = '小明'; function callName(){ alert(privateName); } return { publicShowName : function(){ callName(); } } }(); person.publicShowName();//小明
这个就是能够用一个对象共享相同的方法,同时私有变量name不包含在公众视野之下,只能通过特定方法publicShowName()访问。至于为什么要使用自执行函数var fun = function(){}(); 其实跟我们上面私有变量一样,需要通过私有作用域隐藏私有变量,而且不需要实例化。 下面我们来写一个函数注册组件的例子吧:
function baseComponent(){ } function otherComponent(){ } //定义两个组件 var app = 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); } } }; }(); alert(app.constructor);//function Object(){} alert(app.getComponentCount());//1 app.registerComponent(new otherComponent()); alert(app.getComponentCount());//2
这是一个注册组件的例子,他只提供了注册和访问有多少个组件的方法。这里我们最后返回的对象都是Object,我们可能需要更加面向对象一些,我们可能需要返回的是特有的对象,同样是上面的例子,我们可以这样做
function Component(){ } function baseComponent(){ } function otherComponent(){ } //定义两个组件 var application = function(){ var components = new Array(); components.push(new baseComponent()); var app = new Component(); app.getComponentCount = function(){ return components.length; }; app.registerComponent = function(component){ if(typeof component == 'object'){ components.push(component); } } return app; }(); alert(application.constructor);//function Component() {} alert(application.getComponentCount());//1 application.registerComponent(new otherComponent()); alert(application.getComponentCount());//2