js设计模式-模拟私有变量

//假设有一个人的类,一般的写法:                       
function Person(name,age){
    this.name = name;
    this.age = age;
};
Person.prototype={
    born:function(){
        return this;
    },
    say:function(word){
        var $this = this;
        console.log($this.name);
    }
}

//我们规定这个类创建的对象,其name属性必须小于4个字符
//那么可以这样:
function Person(name,age){
    if(name.length>4) throw new Error('name too long');
    this.name = name;
    this.age = age;
};
Person.prototype={
    born:function(){
        return this;
    },
    say:function(word){
        var $this = this;
        console.log($this.name);
    }
}
//这样的话我们可以在创建对象之初限制对象的属性
var person1 = new Person('Zacarh',23);//这样会报错
//但是有个弊端,程序员创建了符合规定的对象,但是他仍可以修改对象的属性成为不符合规则的值
var person2 = new Person('Tom',22);//成功创建
person2.name = 'Zacarh';//成功修改为不符合规则的值
console.log(person2.name);//Zacarh

//于是就有了私有变量的由来,我们采用闭包模拟私有变量
function Person(){
    var name,age;//这里的变量外部访问不到,可以看成私有变量
    this.setName=function(nameArgument){//这个是特权方法,可以访问私有变量
        if(nameArgument.length>4) throw new Error('name too long');
        name = nameArgument;//特权方法内却可以访问到外部变量。js函数作用域是在定义的时候确定的,不是在执行的时候确定的
    };
    this.say = function(){
        console.log(name);//这里就不用this.name了
    }
}
var person1 = new Person();
// person1.setName('Zacarh');//报错,字符长度大于4
person1.setName('Tom');//可以
person1.say();//输出Tom,而且此时你无法直接更改name的值了,必须要通过setName函数才可以。

//上面那种做法的弊端就是,每创建一个对象,特权函数也会创建一次,这样会耗费更多的内存,不像用prototype那样所有对象共用prototype上面的方法。