Javascript-在闭包中使用函数构造函数是个坏主意吗?

Javascript-在闭包中使用函数构造函数是个坏主意吗?,javascript,performance,memory,Javascript,Performance,Memory,我想知道在闭包中使用函数构造函数时是否存在内存或性能问题 这是一个粗略的例子,我知道有很多不同的更好的方法来编写它,我只是想提供一个例子,每个构造函数现在都可以访问闭包中的变量(farmer、lastToSpeak和animals) //用法:myFarm=新农场([“奶牛”、“山羊”、“老麦当劳”); 功能农场(动物学家、农民){ 变量=[], lastToSpeak=“”; 函数Cow(){ this.speak=函数(){ 警惕(“我是一头牛,我属于”+农夫); } lastToSpeak

我想知道在闭包中使用函数构造函数时是否存在内存或性能问题

这是一个粗略的例子,我知道有很多不同的更好的方法来编写它,我只是想提供一个例子,每个构造函数现在都可以访问闭包中的变量(farmer、lastToSpeak和animals)

//用法:myFarm=新农场([“奶牛”、“山羊”、“老麦当劳”);
功能农场(动物学家、农民){
变量=[],
lastToSpeak=“”;
函数Cow(){
this.speak=函数(){
警惕(“我是一头牛,我属于”+农夫);
}
lastToSpeak=“一头牛”;
}
功能羊(){
this.speak=函数(){
警惕(“我是一只羊,我属于”+农夫);
}
lastToSpeak=“绵羊”;
}
功能山羊(){
this.speak=函数(){
警惕(“我是一只山羊,我属于”+农夫);
}
lastToSpeak=“山羊”;
}
对于(变量i=0;i
我猜在这个例子中没有什么区别,但是如果牛、羊和山羊都更大、更复杂,并且我们创建了很多农场,这种方法会有任何缺点吗

function Farm(animalList, farmer){
    var animals = [],
        lastToSpeak = "";

    this.farmer = farmer;

    for(var i = 0; i < animalList.length; i++){
        switch(animalList[i]){
            case "Cow":
                animals.push(new this.Cow(this));
                break;
            case "Sheep":
                animals.push(new this.Sheep(this));
                break;
            case "Goat":
                animals.push(new this.Goat(this));
                break;
        }
    }

    this.allSpeak = function(){
        for(var i = 0; i < animals.length; i++){
            animals[i].speak();
        }
    }
}
Farm.prototype.Goat = function(farm){
    this.speak = function(){
        alert("I'm a Goat and I belong to "+farm.farmer);
    }
    farm.lastToSpeak = "A Goat";
}
Farm.prototype.Cow = function(farm){
    this.speak = function(){
        alert("I'm a Cow and I belong to "+farm.farmer);
    }
    farm.lastToSpeak = "A Cow";
}
Farm.prototype.Sheep = function(farm){
    this.speak = function(){
        alert("I'm a Sheep and I belong to "+farm.farmer);
    }
    farm.lastToSpeak = "A Sheep";
}

myFarm = new Farm(["Cow","Goat"],"Old MacDonald");
myFarm.allSpeak();
是否每次创建场时都会将一组新的构造函数存储到内存中

更新

因此,我对凯末尔·达奥所说的以及贝尔吉的评论感到高兴

如果我像Bergi建议的那样更改代码以使用原型并在农场中传递,那么这似乎是更好的方法吗

function Farm(animalList, farmer){
    var animals = [],
        lastToSpeak = "";

    this.farmer = farmer;

    for(var i = 0; i < animalList.length; i++){
        switch(animalList[i]){
            case "Cow":
                animals.push(new this.Cow(this));
                break;
            case "Sheep":
                animals.push(new this.Sheep(this));
                break;
            case "Goat":
                animals.push(new this.Goat(this));
                break;
        }
    }

    this.allSpeak = function(){
        for(var i = 0; i < animals.length; i++){
            animals[i].speak();
        }
    }
}
Farm.prototype.Goat = function(farm){
    this.speak = function(){
        alert("I'm a Goat and I belong to "+farm.farmer);
    }
    farm.lastToSpeak = "A Goat";
}
Farm.prototype.Cow = function(farm){
    this.speak = function(){
        alert("I'm a Cow and I belong to "+farm.farmer);
    }
    farm.lastToSpeak = "A Cow";
}
Farm.prototype.Sheep = function(farm){
    this.speak = function(){
        alert("I'm a Sheep and I belong to "+farm.farmer);
    }
    farm.lastToSpeak = "A Sheep";
}

myFarm = new Farm(["Cow","Goat"],"Old MacDonald");
myFarm.allSpeak();
功能农场(动物学家、农民){
变量=[],
lastToSpeak=“”;
这个农民=农民;
对于(变量i=0;i
更新


我编造了一把小提琴,而不是在这个问题上添加另一个版本。我已经完全分离了我的动物构造器,并将speakAll()移到了原型中。我想我真的在寻找一种解决方案,它允许我在不向全局范围添加任何内容的情况下跨实例共享变量。我最终决定将对象传递给每个实例,而不是构造函数,这意味着我不必在构造函数上公开它们。谢谢大家。

在javascript中,每个函数本身都是一个对象,所以你的问题的答案是肯定的。每次创建农场对象时,都会创建其所有私有方法,例如:Cow、Sheep、Goat

要防止这种情况,请在农场对象的原型中创建函数。这可以防止为这些函数重新分配内存,但它们会立即成为公共函数。见:

Farm.prototype.Goat = function(farmer){
        this.speak = function(){
            alert("I'm a Goat and I belong to "+farmer);
        }
        this.lastToSpeak = "A Goat";
}
你必须决定私人功能是否对你至关重要?那么原型方法就更好了

但请记住,在javascript中使用原型有点棘手,所以我不得不修改代码的某些方面,您可以看到一个工作示例

在该示例中,您会发现
this.lastToSpeak
赋值基本上是错误的。因为您将在农场对象的原型处创建的函数用作对象构造函数本身。然后,
这个
变成了对Goat对象而不是Farm对象的引用,所以如果您想引用父Farm对象,您可能会将引用传递给parent to Goat构造函数。请记住,原型继承与标准类继承完全不同,但您几乎可以模仿您想要的任何行为

是否每次创建场时都会将一组新的构造函数存储到内存中

对。但是,如果他们真的需要访问闭包变量(比如
lastToSpeak
),这是合理的,就像特权方法一样。拥有私有构造函数可能有点奇怪,但可能是必需的

当您处理一组类似(但范围不同)的构造函数时,为它们提供一个公共原型对象可能是一种性能优化。如果原型方法也不需要访问闭包变量,则使用
构造函数外部的静态对象,并将其分配给每个特权构造函数

我将代码改为使用原型,这似乎是更好的方法吗

function Farm(animalList, farmer){
    var animals = [],
        lastToSpeak = "";

    this.farmer = farmer;

    for(var i = 0; i < animalList.length; i++){
        switch(animalList[i]){
            case "Cow":
                animals.push(new this.Cow(this));
                break;
            case "Sheep":
                animals.push(new this.Sheep(this));
                break;
            case "Goat":
                animals.push(new this.Goat(this));
                break;
        }
    }

    this.allSpeak = function(){
        for(var i = 0; i < animals.length; i++){
            animals[i].speak();
        }
    }
}
Farm.prototype.Goat = function(farm){
    this.speak = function(){
        alert("I'm a Goat and I belong to "+farm.farmer);
    }
    farm.lastToSpeak = "A Goat";
}
Farm.prototype.Cow = function(farm){
    this.speak = function(){
        alert("I'm a Cow and I belong to "+farm.farmer);
    }
    farm.lastToSpeak = "A Cow";
}
Farm.prototype.Sheep = function(farm){
    this.speak = function(){
        alert("I'm a Sheep and I belong to "+farm.farmer);
    }
    farm.lastToSpeak = "A Sheep";
}

myFarm = new Farm(["Cow","Goat"],"Old MacDonald");
myFarm.allSpeak();
不是这样的。构造函数不应该是实例方法,将它们放在原型对象上是很奇怪的。最好把它们放在农场上