Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/382.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.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_Backbone.js_Knockout.js_Coffeescript - Fatal编程技术网

这三种模式之间的区别是什么;“类”;JavaScript中的定义?

这三种模式之间的区别是什么;“类”;JavaScript中的定义?,javascript,backbone.js,knockout.js,coffeescript,Javascript,Backbone.js,Knockout.js,Coffeescript,当选择使用这四种图案中的一种时,与其他图案相比,发动机罩下是否存在任何重要/细微/显著的差异?而且,当通过Object.create()与new操作符“实例化”时,它们之间有什么区别吗 1) CoffeeScript在翻译“类”定义时使用的模式: Animal = (function() { function Animal(name) { this.name = name; } Animal.prototype.move = function(meters) {

当选择使用这四种图案中的一种时,与其他图案相比,发动机罩下是否存在任何重要/细微/显著的差异?而且,当通过
Object.create()
new
操作符“实例化”时,它们之间有什么区别吗

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

Animal = (function() {

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

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

  return Animal;

})();

2)
淘汰
的模式似乎促进了:

var DifferentAnimal = function(name){

    var self = this;

    self.name = name;

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

}

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

var DifferentAnimalWithClosure = function(name){

    var name = name;

    var move = function(meters){

    };

    return {name:name, move:move};

}

4)
Backbone
促进的模式:

var OneMoreAnimal= ClassThatAlreadyExists.extend({

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

});

更新1:更改模式2并添加模式3,以响应Elias的响应//次要格式

第一个示例将移动功能放在原型中,所有动物实例将共享该功能

第二个示例为每个动物实例创建一个新的移动函数

第三个示例生成了一个动物类,原型中的move函数与第一个示例类似,但代码分配较少。 (在您的示例中,名称也在所有实例之间共享,这可能是您不想要的)


将函数放在原型中可以加快动物的实例化速度,而且由于JIT引擎的工作方式,甚至函数的执行速度也更快。

需要明确的是:JS不知道类,只知道对象和自定义的构造函数,但这不是重点
简而言之,回答你的问题:是的,你在这里发布的创建新对象的各种方法之间存在一些小的甚至是相当大的差异

咖啡脚本:
这实际上是创建您自己的构造函数的最清晰和传统的方法,但是它已经“优化”了,因为它已经准备好使用(可选)闭包变量
基本上,这段代码所做的是使用IIFE,将构造函数定义和proptotype方法赋值包装在它们自己的私有范围中,该范围返回对新构造函数的引用。它只是干净、简单的JS,与您自己可能编写的没有什么不同

淘汰赛:
这让我有点吃惊,因为至少对我来说,您提供的代码片段看起来像是模块模式的一部分,或者是power构造函数。但是,由于您没有使用
严格模式
,省略
新的
仍然会导致危险情况,而且由于整个函数都会遇到创建
差异对象
的新实例的麻烦,只会构造第二个对象文本,将
differentitanimal
的所有属性分配给第二个对象,我认为您缺少了一些东西。因为,说实话,省略最后的
返回{}语句可能根本没有区别。另外:正如您所看到的,您在本质上是一个构造函数中声明了一个方法(
move
)。这意味着每个实例将被分配其自己的函数对象
move
,而不是从原型中获取它
简言之:再仔细看看这段代码的来源,再仔细检查一下这是否是完整版本,因为如果是,我只能看到反对这一点的论点

使用构造函数中定义的变量很简单:一个闭包,假设您的属性具有不同的初始状态,由一些参数确定,并传递给该构造函数:

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
就这些,真的。当您看到ppl使用
var that=this或其他东西,这通常是为了创建对任何地方都可用的主对象的引用,而不必处理
(此
引用的是什么?当该方法应用于它最初打算用于的对象以外的对象时,应该做什么?等等…)

主干:
这里,我们处理的是另一种情况:扩展对象(即:使用方法、现有“类”(构造函数)或特定实例的属性)与简单地创建对象不同
正如您所知,JS对象可以在任何给定的时间分配新属性。这些属性也可以删除。有时,可以在实例本身上重新定义原型属性(屏蔽原型行为)等等。。。因此,这完全取决于您希望结果对象(扩展给定实例的新创建对象)的外观:您希望它从实例中获取所有属性,还是希望两个对象在某个地方使用相同的原型?
这两件事也可以通过使用简单的JS来实现,但是自己编写它们需要更多的努力。但是,如果您编写,例如:

function Animal(name)
{
    this.name = name;
}
Animal.prototype.eat= function()
{
    console.log(this.name + ' is eating');
};
这可以被视为等同于书面形式:

var Animal = Object.extend({name:'',eat:function()
{
    console.log(this.name + ' is eating');
}});
短得多,但缺少构造函数

新建
vs
对象。创建

这很简单:
对象。create
new
强大得多:你可以在需要创建对象的时候定义原型方法、属性(包括天气、可枚举、可写等),而不必编写构造函数和原型,或者创建一个对象文字,并处理所有那些
object.defineProperty
行。
缺点:有些人仍然没有使用兼容ECMA5的浏览器(IE8还没有完全消亡)。根据我的经验:过一段时间后,调试大型脚本确实变得非常困难:虽然我倾向于使用power构造函数,而不是常规构造函数,但我仍然在脚本的最顶端定义了它们,具有独特、清晰和相当描述性的名称,而对象文本是我“动态”创建的东西。使用
Object.create
,我注意到我倾向于创建一些过于复杂的对象,不适合作为
//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;
    };
}());
var createSomething = Object.create(someObject, {getCreated:function()
{
    console.log(this.myProperty);
},
myProperty:new Date()});