Javascript - 在闭包中使用函数构造函数是一个坏主意吗? [英] Javascript - Is it a bad idea to use function constructors within closures?

查看:72
本文介绍了Javascript - 在闭包中使用函数构造函数是一个坏主意吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这是一个粗略的例子,我知道有一吨有不同和更好的方法来写这个,我只是想提供一个例子,其中每个构造函数现在可以访问闭包中的变量(farmer,lastToSpeak和动物)。

  //用法:myFarm = new Farm([Cow,Goat],Old MacDonald); 

函数Farm(animalList,farmer){
var animals = [],
lastToSpeak =;

函数Cow(){
this.speak = function(){
alert(我是牛,我属于+农夫);
}
lastToSpeak =A Cow;
}
函数Sheep(){
this.speak = function(){
alert(我是一只羊,我属于+农民);
}
lastToSpeak =一只羊;
}
函数Goat(){
this.speak = function(){
alert(我是山羊,我属于+农民);
}
lastToSpeak =山羊;
}

for(var i = 0; i< animalList.length; i ++){
switch(animalList [i]){
caseCow :
animals.push(new Cow());
休息;
caseSheep:
animals.push(new Sheep());
休息;
caseGoat:
animals.push(new Goat());
休息;
}
}

this.allSpeak = function(){
for(var i = 0; i< animals.length; i ++){
animals [i] .speak();
}
}
}
myFarm = new Farm([Cow,Goat],Old MacDonald);
myFarm.allSpeak();

我猜这个例子没什么区别,但是如果牛,羊和山羊都是更大更复杂,我们创建了很多农场,这种方法有什么不利之处吗?



每次农场都会将一组新的构造函数存储到内存中已创建?



更新



所以我对KemalDağ感到满意说以及Bergi的评论。



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

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

this.farmer =农民;

for(var i = 0; i< animalList.length; i ++){
switch(animalList [i]){
caseCow:
animals.push(new this.Cow(this));
休息;
caseSheep:
animals.push(new this.Sheep(this));
休息;
caseGoat:
animals.push(new this.Goat(this));
休息;
}
}

this.allSpeak = function(){
for(var i = 0; i< animals.length; i ++){
animals [i] .speak();
}
}
}
Farm.prototype.Goat = function(farm){
this.speak = function(){
alert(I我是山羊,我属于+ farm.farmer;
}
farm.lastToSpeak =A Goat;
}
Farm.prototype.Cow = function(farm){
this.speak = function(){
alert(我是牛,我属于+ farm.farmer);
}
farm.lastToSpeak =A Cow;
}
Farm.prototype.Sheep = function(farm){
this.speak = function(){
alert(我是一只羊,我属于+ farm.farmer);
}
farm.lastToSpeak =一只羊;
}

myFarm = new Farm([Cow,Goat],Old MacDonald);
myFarm.allSpeak();

更新



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

解决方案


每次农场都会将一组新的构造函数存储到内存中已创建?


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



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


我改变了代码以使用原型,这看起来更好吗?


不喜欢这个。构造函数不应该是实例方法,将它们放在原型对象上是奇怪的。最好将它们作为命名空间放在 Farm 函数对象上。



这是一个公开所有内容的例子,崇拜原型:

  function Farm(animalList,farmer){
this.farmer = farmer;
this.lastToSpeak =;
this.animals = [];

for(var i = 0; i< animalList.length; i ++){
var name = animalList [i];
if(Farm.hasOwnProperty(name))
this.animals.push(new Farm [name](this));
}
}
Farm.prototype.allSpeak = function(){
for(var i = 0; i< this.animals.length; i ++){
this.animals [i] .speak();
}
};

函数动物(农场){
this.farm = farm;
farm.lastToSpeak =A+ this.type;
}
Animal.prototype.speak = function(){
alert(我是+ this.type +,我属于+ this.farm.farmer);
};
Animal.create = function(name){
Farm [name] = function(){
Animal.apply(this,arguments);
};
Farm [name] .prototype = Object.create(Animal.prototype);
Farm [name] .prototype.type = name;
};
Animal.create(山羊);
Animal.create(Sheep);
Animal.create(Cow);

myFarm = new Farm([Cow,Goat],Old MacDonald);
myFarm.allSpeak();


I'm wondering if there are any memory or performance issues when using function constructors within a closure?

Here is a crude example, I know there are a tonne of different and better ways to write this, I just wanted to provide an example where each constructor now has access to variable in the closure (farmer,lastToSpeak and the animals).

// usage: myFarm = new Farm(["Cow","Goat"],"Old MacDonald");

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

    function Cow(){
        this.speak = function(){
            alert("I'm a Cow and I belong to "+farmer);
        }
        lastToSpeak = "A Cow";
    }
    function Sheep(){
        this.speak = function(){
            alert("I'm a Sheep and I belong to "+farmer);
        }
        lastToSpeak = "A Sheep";
    }
    function Goat(){
        this.speak = function(){
            alert("I'm a Goat and I belong to "+farmer);
        }
        lastToSpeak = "A Goat";
    }

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

    this.allSpeak = function(){
        for(var i = 0; i < animals.length; i++){
            animals[i].speak();
        }
    }
}
myFarm = new Farm(["Cow","Goat"],"Old MacDonald");
myFarm.allSpeak();

I'm guessing in this example it makes little difference, but if the cow,sheep and goat were much larger and complex and we were creating lots of farms would there be any disadvantages to this approach?

Will a new set of constructor functions be stored to memory every time a farm is created?

UPDATE

So i'm happy with what Kemal Dağ said and also the comment from Bergi.

If I changed the code to use prototypes and passed in the farm as Bergi suggests, does that seem like the better approach?

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

UPDATE

I put together a fiddle rather than add another version to the question here. I've separated my animal constructors completely and moved speakAll() to the prototype. I think I was really looking for a solution that allowed me to share variables across my instances without adding anything to the global scope. I finally decided to pass an object to each instance rather than the constructor, meaning I don't have to make them public on the constructor. Thanks Guys.

解决方案

Will a new set of constructor functions be stored to memory every time a farm is created?

Yes. However, if they really need access to the closure variables (like lastToSpeak) that can be reasonable, just as it is for privileged methods. Having private constructors might be a bit odd, but can be required.

When you are dealing with a set of similar (but differently-scoped) constructors it can be a performance optimisation to give them a common prototype object. If the prototype methods do not need access to the closure variables as well, then use a static object outside the Farm constructor and assign that to each privileged constructor.

I changed the code to use prototypes, does that seem like the better approach?

Not like this. Constructors should not be instance methods, putting them on the prototype object is odd. Better put them on the Farm function object as a namespace.

Here's an example of making everything public, worshipping prototypes:

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

    for(var i = 0; i < animalList.length; i++){
        var name = animalList[i];
        if (Farm.hasOwnProperty(name))
            this.animals.push(new Farm[name](this));
    }
}
Farm.prototype.allSpeak = function(){
    for(var i = 0; i < this.animals.length; i++){
        this.animals[i].speak();
    }
};

function Animal(farm) {
    this.farm = farm;
    farm.lastToSpeak = "A "+this.type;
}
Animal.prototype.speak = function(){
    alert("I'm a "+this.type+" and I belong to "+this.farm.farmer);
};
Animal.create = function(name) {
    Farm[name] = function() {
        Animal.apply(this, arguments);
    };
    Farm[name].prototype = Object.create(Animal.prototype);
    Farm[name].prototype.type = name;
};
Animal.create("Goat");
Animal.create("Sheep");
Animal.create("Cow");

myFarm = new Farm(["Cow","Goat"],"Old MacDonald");
myFarm.allSpeak();

这篇关于Javascript - 在闭包中使用函数构造函数是一个坏主意吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆