Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/458.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 闭包和多个实例_Javascript - Fatal编程技术网

Javascript 闭包和多个实例

Javascript 闭包和多个实例,javascript,Javascript,我喜欢闭包,因为可以从闭包中生成API,但不能有多个实例,这很糟糕 是否有其他方法可以使用原型访问私有成员并创建不同的实例?如果您真的想将构造函数和成员用作私有成员,那么您可以这样做 var Person = function(my_name) { // private properties and methods var Constr, name; // public API Constr = function(n) { name = n;

我喜欢闭包,因为可以从闭包中生成API,但不能有多个实例,这很糟糕


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

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

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);
};
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();
注意:

  • 但这并不高效,因为每次创建
    Person
    对象时,我们都必须创建
    Constr
    构造函数

  • 它使得从
    Constr
    /
    Person
    继承成为不可能,因为
    Constr
    无法从外部访问,并且
    Person
    的原型为空

    console.log(Person.prototype); // {}
    
  • 我认为,并不是所有的变量在你们的类中都是私有的。所以,你可以有私人会员,就像这样

    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);
    };
    
    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();
    

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

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

    您返回的公共界面将不再是
    Person
    的实例,这是一个需要记住的特殊方法。

    我认为未来的方式是,它与通常与HTML5兼容的浏览器兼容(最显著的是IE9+,请参阅以获得最佳的回填效果)

    这样,您就可以定义看起来像属性(而不是函数)的只读getter,并且不会破坏原型继承或每次都创建一个新的构造函数:()

    或者,与其他人的评论类似,您可以执行以下操作以提高浏览器兼容性,同时保持原型正确性和只读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
    

    它们是私有的,但不是每个实例所独有的。不用担心JS中的封装,这样做很好。_name,因此下划线是一种表示“私有”的约定。原型方法是共享的,因此它们不能基于每个对象访问变量@elclanrs:在大多数情况下,解决方案应该是足够的。否则,您将放弃原型方法,并为每个实例提供自己的方法。@CookieMonester但公共方法可以通过特权方法访问私有成员,因此这不是世界末日,只是效率稍低一点。:-)@RobG:通过“public”,你是在专门谈论原型方法吗?如果是这样的话,是的,这是真的,但我看不出这有什么意义,因为您仍然需要基于每个实例创建方法。那么,为什么原型方法要调用每个实例的方法,而不是直接调用每个实例的方法呢?@cookiemonster-“但我看不出这有什么意义”事实上,这就是为什么大多数走这条路的人最终只是“公开”的原因特权方法可以模拟getter和setter,但同样,它们修改的属性也可能是公共的。是的,使用特权方法获取和设置私有成员(可能还有其他东西)的值是很常见的,这样继承的方法就可以使用它们。但正如埃尔克兰斯所说,有时候,只要你遵守纪律,最终付出的努力是不值得的(但在团队中并不总是如此)。了解了后者,似乎没有其他办法。谢谢你展示了非正统的选项!太棒了。您将如何使用
    Object.defineProperties
    inside Person访问/覆盖名称?@Tek取决于您的意图。您可以再次调用Object.defineProperties(还没有尝试,只是有意义),或者如果您只是想要一个标准的getter/setter,您可以将
    writeable:true
    添加到
    {value:attributes.name}