[JavaScript] 模拟块级作用域、私有变量/函数
JavaScript没有块级作用域的概念。
function outputNumbers(count){
for (var i=0; i < count; i++){
alert(i);
}
alert(i); //计数
}
①块语句中定义的变量,实际是在包含函数中而非语句中创建的。即变量i的作用域是它的包含函数outputNumber(),而不是for语句。
在java、C++等语言中,变量i只会在for语句块中定义,循环结束后就被销毁。
②甚至在outputNumber()函数中可以重新声明同一个变量,JavaScript会忽略后续的声明但会执行声明中的初始化。
function outputNumbers(count){
for (var i=0; i < count; i++){
alert(i);
}
var i; //JavaScript不会提示重复声明了一个变量
alert(i); //count
}
1、私有作用域
使用匿名函数 模拟块级作用域(私有作用域) 语法:
(function(){
//这里就是块级作用域
})();
①调用并立即调用一个匿名函数。由于函数声明后面是不能加圆括号,故需要用圆括号将函数声明包围起来,使其转换为函数表达式
②临时需要一些变量时,可以使用私有作用域。
function outputNumbers(count){
(function () {
for (var i=0; i < count; i++){
alert(i);
}
})();
alert(i); //导致一个错误
}
③在匿名函数中的任何变量在执行结束后会被销毁,故变量i只能在for循环语句中被使用,使用后即被销毁。匿名函数是闭包,可访问count参数。
④优点:可避免过多的全局变量而导致的命名冲突。
同时,也有利于减少闭包占用内存问题,因为没有指向匿名函数的引用,匿名函数的作用域链在代码执行后销毁。
2、私有变量
严格来讲,JavaScript没有私有成员的概念,所有对象属性都是公有的。但有一个私有变量的概念。
任何在函数中定义的变量,都可以认为是私有变量。私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。
2-1.特权方法(privileged method)
指有权访问私有变量和私有函数的公有方法。有2种创建方法:在构造函数中定义特权方法、在私有作用域中定义私有变量或函数。
2-1-1.实例变量(在构造函数中定义特权方法)
function MyObj(){
//私有变量
var privateVar = 10;
//私有函数
function privateFunc(){
return false;
};
//特权方法
this.publicMethod = function(){
privateVar++;
return privateFunc();
};
}
①外界无法访问MyObj()函数内的私有变量和私有函数,但由于特权方法是闭包 而可以通过它访问包含函数中的私有变量和私有函数。
②在创建MyObj实例后,除了通过publicMethod()这一个途径,没有其他方法能直接访问privateVar和privateFunc()。
③利用私有和特权成员,可以隐藏那些不应该被直接修改的数据。
缺点:使用构造函数模式后,每个实例都会创建同样一组新方法。
即每次都要重新创建特权方法,故之前的数据无法重用。使用第二种创建方法可解决。
2-1-2.静态私有变量(在私有作用域中定义私有变量或函数+原型模式)
(function(){
//私有变量
var privateVar = 10;
//私有函数
function privateFunc(){
return false;
};
//构造函数
MyObj = function(){
};
//公有/特权方法
MyObj.prototype.publicMethod = function(){
privateVar++;
return privateFunc();
};
})();
①此模式,将所有私有变量、私有函数和特权方法等 都定义在一个私有作用域中。
②构建函数中,没使用函数声明,因为函数声明只能创建局部函数。
变量MyObj没有用var关键字声明,因为初始化为经声明的变量,都会创建一个全局变量。(在严格模式给为声明的变量赋值会出错)
③特权方法是在原型(prototype)上定义的,原型模式定义函数时不用函数声明,而是使用函数表达式,才能创建全局函数。
区别:使用此模式,私有变量和函数都是由实例共享的,由于特权方法是在原型创建的,所以实例都用同一个特权方法。
因此,当在一个实例中调用该特权方法修改私有变量时,所有实例都会被影响,所有实例中引用的私有变量对应着改变。
优点:创建静态私有变量因为使用了原型而增进代码复用。
缺点:所有实例都没有自己的私有变量和函数(都引用同一个)。
(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"