什么是&QUOT这三种模式之间的差异;类"在JavaScript中定义? [英] What are the differences between these three patterns of "class" definitions in JavaScript?

查看:92
本文介绍了什么是&QUOT这三种模式之间的差异;类"在JavaScript中定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有任何重要/细微/显著选择使用比其他这四种模式之一时,引擎盖下的差异?而且,如果是初始化它们之间通过的Object.create() VS的运营商有什么区别?

Are there any important/subtle/significant differences under the hood when choosing to use one of these four patterns over the others? And, are there any differences between the them when "instantiated" via Object.create() vs the new operator?

1)模式的的CoffeeScript 使用翻译类的定义时:

1) The pattern that CoffeeScript uses when translating "class" definitions:

Animal = (function() {

  function Animal(name) {
    this.name = name;
  }

  Animal.prototype.move = function(meters) {
    return alert(this.name + (" moved " + meters + "m."));
  };

  return Animal;

})();

2)的图案淘汰赛似乎推动:

2) The pattern that Knockout seems to promote:

var DifferentAnimal = function(name){

    var self = this;

    self.name = name;

    self.move = function(meters){
        return alert(this.name + (" moved " + meters + "m."));
    };

}

3)类似,简单的模式我经常看到:

3) a similar, simple pattern I've often seen:

var DifferentAnimalWithClosure = function(name){

    var name = name;

    var move = function(meters){

    };

    return {name:name, move:move};

}

4)模式骨干促进:

var OneMoreAnimal= ClassThatAlreadyExists.extend({

    name:'',
    move:function(){}

});

更新1:更改模式#2和补充模式#3响应Elias的响应//少量格式

Update 1: Changed pattern #2 and added pattern #3 in response to Elias' response // minor formatting

推荐答案

只是要清楚:JS不知道的班,只是对象和自定义,自定义的构造函数,但这是除了点。

要回答你的问题在​​短期:是的,有一些小的,创造你在这里发布一个新的对象的各种方法之间甚至一些相当大的差异。

Just to be clear: JS doesn't know of classes, just objects and custom, self-defined constructor functions, but that's besides the point.
To answer your question in short: yes, there are some small and even some fairly large differences between the various ways of creating a new object you're posting here.

CoffeeScript的:

这实际上是创建自己的构造函数的最明确的和传统的方式,但它已经的在某种意义上说,它已经准备好设置为使用(可选)封变量优化的。

基本上,这code做什么,是使用IIFE,包装既构造函数定义的的在自己的私人范围,即返回到新的构造函数的引用proptotype方法分配。这只是干净,简单的JS,无异于你可能会写自己。

CoffeeScript:
This is actually the most clear-cut and traditional way to create your own constructor, but it has been "optimized" in the sense that it's been ready set-up to use (optional) closure variables.
Basically, what this code does, is use an IIFE, to wrap both the constructor definition and the proptotype method assignments in their own, private scope, that returns a reference to the new constructor. It's just clean, simple JS, no different from what you might write yourself.

淘汰赛:

现在,这把我一点点,因为对我来说,至少,你所提供的代码片段看起来模块模式的任何部分一样,或电源的构造。但是,由于你没有使用严格模式,省略了仍然会做出危险的情况,而且由于整个功能发生低谷创建 DifferentAnimal ,只给一个新实例的麻烦的然后的构造第二个对象文本,分配<$ C $的所有属性C> DifferentAnimal 来的次要目标,我会说你失去了一些东西。因为,说实话,省略了最后一个返回{}; 语句在这里,很可能没有什么区别的。另外:你可以看到,你在声明的是,在本质上,一个构造方法(移动)。这意味着的每个的实例将被分配自己的函数对象移动,而不是从原型得到它。

简而言之:有在那里你得到了这个片段另一个密切关注,并仔细检查,如果这是完整版的,因为如果是这样,我只能看到参数反对的这一点。

Knockout:
Now this threw me a little, because to me, at least, the snippet you provide looks either like part of a module pattern, or a power constructor. But since you're not using strict mode, omitting the new would still make for dangerous situations, and since the entire function goes trough the trouble of creating a new instance of DifferentAnimal, only to then construct a second object literal, assigning all properties of DifferentAnimal to that secondary object, I'd say you're missing something. Because, truth be told, omitting the last return {}; statement here, would probably make no difference at all. Plus: as you can see, you're declaring a method (move) in what is, in essence, a constructor. This means that every instance will be assigned its own function object move, rather then getting it from the prototype.
In short: have another close look at where you got this snippet from, and double-check if this is the full version, because if it is, I can only see arguments against this.

使用一个变量,在构造函数中定义很简单:一个封闭,假设你的性能有明显的初始状态,通过一些参数来确定,传递给构造函数:

Using a variable, defined inside the constructor is simply: a closure, suppose your properties have a distinct initial state, determined by some arguments, passed to that constructor:

function MyConstructor(param)
{
     var paramInit = param/2;//or something
     this.p = paramInit;//this property can change later on, so:
     this.reInit = function()
     {//this method HAS to be inside constructor, every instance needs its own method
         this.p = paramInit;//var paramInit can't, it's local to this scope
     };
}
var foo = new MyConstructor(10);
console.log(foo.p);//5
foo.p = 'hi';
console.log(foo.p);//hi
foo.reInit();
console.log(foo.p);//5
console.log(foo.paramInit);//undefined, not available outside object: it's a pseudo-private property

这是所有有过,真的。当你看到使用 VAR脂肪酶的=这一点; 类的东西,这就是常创建的主要对象是随处可用的参考,而不必处理的头痛这个(什么呢这个引用?应该采取什么方法做,当应用于对象的其他的比它原本打算呢?诸如此类......)

That's all there is too it, really. When you see ppl using var that = this; or something, that's often to create a reference to the main object that is available anywhere, without having to deal with the headaches of this (what does this reference? What should the method do when applied to an object other than the one it was originally intended for? etcetera...)

骨干:

在这里,我们正在处理另一起案件:延长对象(例如:使用方法,无论是现有的的(构造函数)或特定实例的属性)是不一样的,只需要创建一个对象。

你很清楚,JS对象可在任何给定时间被分配新的属性。这些属性可以被删除了。有时,原型属性可以在实例本身(屏蔽原型行为)等被重新定义......因此,一切都取决于你想要什么样的结果对象(新创建的对象,它扩展了给定的实例)的样子:你希望它从实例需要的所有属性,或者你希望两个对象的地方使用相同的原型向下行?

这些事情都可以通过使用简单的JS,也可以实现,但他们只是需要一点更多的精力去写自己。但是,如果你写的,例如:

Backbone:
Here, we're dealing with another case: extending objects (IE: using methods, properties of either an existing "class" (constructor) or a particular instance) is not the same as simply creating an object.
As you well know, JS objects can be assigned new properties at any given time. Those properties can be removed, too. Sometimes, prototype properties can be redefined on the instance itself (masking the prototypal behaviour) etc... So it all depends on what you want the resulting object (the newly created object, that extends the given instance) to look like: do you want it to take all properties from the instance, or do you want both objects to use the same prototype somewhere down the line?
Both of these things can be achieved by using simple JS, too, but they just take a bit more effort to write yourself. However, if you write, for example:

function Animal(name)
{
    this.name = name;
}
Animal.prototype.eat= function()
{
    console.log(this.name + ' is eating');
};

这可被视为写作等价的:

That could be deemed the equivalent of writing:

var Animal = Object.extend({name:'',eat:function()
{
    console.log(this.name + ' is eating');
}});

短了很多,但缺乏构造。

A lot shorter, but lacking the constructor.

VS 的Object.create

嗯,这是一个容易:的Object.create 只是很多更强大,:您可以定义原型方法,属性(包括天气或他们是否可枚举,可写等等)就在你需要创建,而不必写一个构造函数和原型,或与所有这些创建一个对象文字,勾搭对象,时间 Object.defineProperty 行。

这带来的不便:有些人还是的未使用ECMA5兼容的浏览器(IE8仍然没有完全死了)。以我的经验:它变得相当困难了一段时间后调试相当大的脚本:虽然我倾向于使用电源的构造比我做定期的构造函数,我还是让他们在我的脚本的顶部定义的,具有鲜明,清晰,相当描述性的名称,而对象的文字是我的事只是创建的上即时的。使用的Object.create ,我发现我倾向于创建可真有点太复杂,有资格作为实际的对象文字,仿佛它们是对象文本对象:

new vs Object.create
Well, that's an easy one: Object.create just is a lot more powerful that new: you can define prototype methods, properties (including weather or not they are enumerable, writeable etc...) right at the time you need to create an object, instead of having to write a constructor and a prototype, or create an object literal and mess around with all those Object.defineProperty lines.
The downsides: Some people still aren't using ECMA5 compliant browsers (IE8 is still not quite dead). In my experience: it does become quite hard to debug sizeable scripts after a while: though I tend to use power-constructors more than I do regular constructors, I still have them defined at the very top of my script, with distinct, clear and quite descriptive names, whereas object-literals are things I just create "on-the-fly". Using Object.create, I noticed I tend to create objects that are really a little too complex to qualify as actual object literals, as though they are object literals:

//fictional example, old:
var createSomething = (function()
{
    var internalMethod = function()
    {//method for new object
        console.log(this.myProperty || '');
    };
    return function(basedOn)
    {
        var prop, returnVal= {};
        returnVal.myProperty = new Date();
        returnVal.getCreated = internalMethod;//<--shared by all instances, thx to closure
        if (!basedOn || !(basedOn instanceof Object))
        {//no argument, or argument is not an object:
            return returnVal;
        }
        for (prop in basedOn)
        {//extend instance, passed as argument
            if (basedOn.hasOwnProperty(prop) && prop !== '_extends')
            {
                returnVal[prop] = basedOn[prop];
            }
        }
        returnVal._extends = basedOn;//<-- ref as sort-of-prototype
        return returnVal;
    };
}());

现在,这是pretty详细,但我有我的基本构造准备好了,我可以用它来扩展现有的实例了。这似乎不再那么繁琐到简单的写:

Now this is pretty verbose, but I've got my basic constructor ready, and I can use it to extend an existing instance, too. It might seem less verbose to simply write:

var createSomething = Object.create(someObject, {getCreated:function()
{
    console.log(this.myProperty);
},
myProperty:new Date()});

但IMO,这使得它很难对你做跟踪创建什么对象在哪里(主要是因为的Object.create 是一个前pression和将不会被悬挂
不错啊,那当然从一个确凿的说法远远:都有自己的亲的和反对的:我使用的模块patters,关闭和动力构造preFER,如果你不,这只是罚款。

But IMO, this makes it harder on you do keep track of what object is created where (mainly because Object.create is an expression, and will not be hoisted.
Ah well, that's far from a conclusive argument of course: both have their pro's and con's: I prefer using module patters, closures and power constructors, if you don't that's just fine.

希望这澄清了一件事或2给你。

Hope this cleared up a thing or 2 for you.

这篇关于什么是&QUOT这三种模式之间的差异;类&QUOT;在JavaScript中定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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