闭包和多个实例

时间:2014-03-28 02:16:01

标签: javascript

我喜欢闭包,因为你可以从他们那里制作一个API,但是你不能拥有多个实例。

http://jsfiddle.net/LxCJe/1/

var Person = (function () {

    // private properties and methods
    var Constr, name;

    // public API
    Constr = function (n) {
        name = n;
    };

    Constr.prototype.sayName = function(){return name;};

    return Constr;
}());


var person1 = new Person('Foo');
var person2 = new Person('Bar'); //New values will overwrite the name because of the closure.

console.log(person1.sayName()); //Bar
console.log(person2.sayName()); //Bar

是否有其他方法可以使用原型来访问私有成员并创建不同的实例?

3 个答案:

答案 0 :(得分:2)

如果你真的想将构造函数和成员用作私有,那么你可以这样做

var Person = function(my_name) {

    // private properties and methods
    var Constr, name;

    // public API
    Constr = function(n) {
        name = n;
    };

    Constr.prototype.sayName = function() {
        return name;
    };

    return new Constr(my_name);
};

注意:

  1. 但这效率不高,因为我们每次创建Constr的对象时都必须创建Person构造函数。

  2. 这使得从Constr / Person继承不可能,因为Constr无法从外部访问,Person的原型为空。

    console.log(Person.prototype); // {}
    
  3. 我认为,并非所有变量都是私有的。所以,你可以拥有私人会员,比如这个

    var Person = function(my_name) {
    
        // private properties and methods
        var name = my_name;
    
        // public API
        this.getName = function() {
            return name;
        }
    
        this.setName = function(newName) {
            name = newName;
        }
    };
    
    Person.prototype.printName = function() {
        console.log(this.getName());
    }
    
    var person1 = new Person('Foo');
    var person2 = new Person('Bar');
    
    console.log(person1.getName()); // Foo
    console.log(person2.getName()); // Bar
    console.log(Person.prototype);  // { printName: [Function] }
    person1.printName();
    person2.printName();
    

答案 1 :(得分:1)

我认为未来的方式是Object.defineProperties,它与通常与HTML5兼容的浏览器兼容(IE9 +,最值得注意的是;请参阅es5-shim以获得最佳的回填功能)。

有了这个,你可以定义看起来像属性(而不是函数)的只读getter,并且不要每次都填充原型继承或创建一个新的构造函数:(JSFiddle here

// name is read-only, but only modern browsers (ie 9+)
function Person(attributes) {
    Object.defineProperties(this, {
        name: {value: attributes.name}
    })
}

person1 = new Person({name: 'Foo'});
person2 = new Person({name: 'Bar'});

console.log(person1.name) // Foo
console.log(person2.name) // Bar

或者,与其他人评论的内容类似,您可以执行以下操作以获得更好的浏览器兼容性,同时保持原型正确性和只读API:

// read-only-ish, but better browser compatibility
function Person(attributes) {
    this._name = attributes.name
}
Person.prototype.name = function() { return this._name }

person1 = new Person({name: 'Foo'});
person2 = new Person({name: 'Bar'});

console.log(person1.name()) // Foo
console.log(person2.name()) // Bar

答案 2 :(得分:0)

您可以在此处减少构造函数的数量,并在每次调用new Person(name)时创建一个新的公共接口:

function Person(name)
{
    // return public api that closes over 'name'
    return {
        sayName: function() {
            return name;
        }
    };
}

您返回的公共界面将不再是Person的实例,请注意这一特定方法。