理解JavaScript私有作用域

私有作用域:跟外界的变量方法毫不冲突,豪无关系

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());//a
people.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());//a
people1.setName("b");  
console.log(people1.getName());//b
var 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  
原文地址:https://www.cnblogs.com/goloving/p/7092220.html