JS之 函数模仿块级作用域,私有变量,模块模式

模仿块级作用域

Javascript没有块级作用域的概念,意味着在块级语句中定义的变量,实际上是在包含函数中而非语句中创建的,看下面例子:

function a() {
            for (var i = 0; i < 2; i++) {
                alert(i);// 0,1
            }
            alert(i);  //2
        }

在c#中,上述 i的作用域仅在 for循环之内,在之外 调用该变量将会报错.但是 javascript中却不会,它从来不会告诉你是否多次声明

同一个变量,它只会对后续的声明视而不见,但是 会执行后续声明中的初始化.看下面例子:

function a() {
            for (var i = 0; i < 2; i++) {
                alert(i);// 0,1
            }
            var i = 10;
            alert(i);  //10
        }

 

匿名函数可以 用来模仿块级作用域(私有作用域) 并且避免上述问题. 下面看个例子:

(function a() { (function () { for (var i = 0; i < 2; i++) { alert(i);// 0,1 } })(); alert(i); //导致一个错误 })();

整个重写了a()函数,在for循环中插入一个私有作用域,在匿名函数中定义的变量,在执行完毕后,将会被销毁.

因此,变量i只能在for循环中 被访问.

私有变量

严格来讲,javascript中 没有私有成员的概念所有对象属性都是公有的.倒是有私有变量的概念.

任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问它们. 私有变量包括:参数,局部变量,

和在函数内部定义的其它函数.

我们可以利用闭包,创建 用于访问私有变量的公有方法.因为闭包可以通过 作用域链来访问 函数内部的所有变量.

把有权访问私有变量的公有方法 承做 特权方法 ,有两种在对象上创建特权方法的模式的方法:

1:

function object() { var privateVarible = 10; //私有变量 function privateFunction() { //私有方法 return privateVarible; }; //特权方法 this.publicMethod = function () { privateVarible++; return privateFunction(); } } var o = new object(); alert(o.privateVarible); //undefined alert(o.privateFunction()); //报错 alert(o.publicMethod()); //11

 

2: 可以利用私有和特权成员,来隐藏那些不应该被直接修改的成员:代码如下:

function person(name) { this.getName = function () { return name }; this.setName = function (value) { name = value }; } var p = new person("gao"); alert(p.name); //undefined alert(p.getName()); //gao p.setName("newgao"); alert(p.getName()); //newgao

在构造函数中定义 特权方法,有一个不好的地方就是,每次实例化的时候,都会同样创建一组新方法, 那么就可以使用

静态私有变量来实现特权方法.

静态私有变量

通过在私有作用域中定义私有变量或函数,同样也可以创建特权方法,基本模式如下:

(function () { //私有变量和私有函数 var privateVarible = 10; function privateFunction() { return false; } //构造函数 myObject = function () { }; //没使用var因为 要创建一个全部变量,而不是局部变量,这个外界才能调到构造函数 //公有/特权方法 myObject.prototype.publicMethod = function () { privateVarible++; return privateFunction(); } })(); var o = new myObject(); alert(o.publicMethod()); //false

这特权方法定义在 原型上,是典型的原型模式. 这样每个实例就可以共享这个 特权函数,而不必,没新建一个实例,

就实例化一个 特权函数对象.但是也有一个问题,就是 每个实例都共享函数和属性,那么每个实例就没有了自己独有的属性,看例子:

(function () { var name = ""; Person = function (value) { //定义构造函数 name = value; }; //定义特权方法 Person.prototype.getName = function () { return name; }; //闭包总是保存着包含作用域的引用 Person.prototype.setName = function (value) { name = value; }; })(); var p = new Person("gao"); alert(p.getName()); //gao var p2 = new Person("gao2"); alert(p.getName()); //gao2 p.setName("gao3"); alert(p2.getName()); //gao3

无论是新实例化对象,修改已有对象的name属性,都会导致  所有实例的name属性发生变化.这就是原型模式的不足之处.

posted @ 2012-06-08 14:44  高捍得  阅读(541)  评论(0编辑  收藏  举报