use*_*765 15 javascript coffeescript backbone.js knockout.js
当选择使用这四种模式中的一种而不是其他模式时,是否存在任何重要/细微/显着的差异?并且,当通过Object.create()vs 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;
})();
Run Code Online (Sandbox Code Playgroud)
和
2)Knockout似乎促进的模式:
var DifferentAnimal = function(name){
var self = this;
self.name = name;
self.move = function(meters){
return alert(this.name + (" moved " + meters + "m."));
};
}
Run Code Online (Sandbox Code Playgroud)
和
3)我经常看到的类似的简单模式:
var DifferentAnimalWithClosure = function(name){
var name = name;
var move = function(meters){
};
return {name:name, move:move};
}
Run Code Online (Sandbox Code Playgroud)
和
4)Backbone促进的模式:
var OneMoreAnimal= ClassThatAlreadyExists.extend({
name:'',
move:function(){}
});
Run Code Online (Sandbox Code Playgroud)
更新1:更改了模式#2并添加了模式#3以响应Elias的响应//次要格式
需要明确的是:JS不知道类,只是对象和自定义的,自定义的构造函数,但除此之外.
简而言之:您可以在这里创建一个新对象的各种方法之间存在一些小的甚至是相当大的差异.
CoffeeScript:
这实际上是创建自己的构造函数最明确和传统的方法,但它已被"优化",因为它已经准备好设置为使用(可选)闭包变量.
基本上,这段代码的作用是使用IIFE,将构造函数定义和 proptotype方法赋值包装在它们自己的私有作用域中,它返回对新构造函数的引用.它只是干净,简单的JS,与您自己编写的内容没有什么不同.
淘汰赛:
现在这让我有点意思,因为对我来说,至少,你提供的代码片段看起来像是模块模式的一部分,或者是电源构造函数.但既然你不使用strict mode,省去new仍然做出危险的情况下,由于整个功能发生槽创建的新实例的麻烦DifferentAnimal,只能再建设第二个对象文本,指定的所有属性DifferentAnimal到次级对象,我会说你错过了什么.因为,说实话,省略return {};这里的最后一句话,可能根本没有任何区别.另外:正如您所看到的,您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
Run Code Online (Sandbox Code Playgroud)
这就是它真的.当你看到使用脂肪酶var that = this;或什么的,那是经常创造的主要对象是随处可用的参考,而不必应付的头痛this(哪些呢this引用?我应该当应用于对象的方法做其他比一个它原本打算用于等等......)
Backbone:
在这里,我们正在处理另一种情况:扩展对象(IE:使用方法,现有"类"(构造函数)或特定实例的属性)与简单地创建对象不同.
众所周知,可以在任何给定时间为JS对象分配新属性.这些属性也可以删除.有时,原型属性可以在实例本身重新定义(屏蔽原型行为)等等......所以这一切都取决于你想要的结果对象(新创建的对象,扩展给定实例)看起来像:你呢希望它从实例中获取所有属性,或者您是否希望两个对象在某个地方使用相同的原型?
这两件事都可以通过使用简单的JS来实现,但是他们只需要花费更多的精力来自己编写.但是,如果你写,例如:
function Animal(name)
{
this.name = name;
}
Animal.prototype.eat= function()
{
console.log(this.name + ' is eating');
};
Run Code Online (Sandbox Code Playgroud)
这可以被认为相当于写作:
var Animal = Object.extend({name:'',eat:function()
{
console.log(this.name + ' is eating');
}});
Run Code Online (Sandbox Code Playgroud)
更短,但缺乏构造函数.
newvsObject.create
嗯,这是一个简单的方法:Object.create只是更强大new:你可以在你需要创建一个对象的时候定义原型方法,属性(包括天气与否,它们是可枚举的,可写的......等)必须编写构造函数和原型,或创建一个对象文字并乱用所有这些Object.defineProperty行.
缺点:有些人仍然没有使用符合ECMA5标准的浏览器(IE8仍然没有完全死亡).根据我的经验:在一段时间后调试大型脚本确实变得非常困难:虽然我倾向于使用power-constructors而不是常规构造函数,但我仍然将它们定义在我的脚本的最顶层,具有清晰,清晰和非常具有描述性的名称,而对象文字则是我"即时"创建的东西.使用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;
};
}());
Run Code Online (Sandbox Code Playgroud)
现在这非常冗长,但我已经准备好了我的基本构造函数,我也可以使用它来扩展现有实例.简单地写一下似乎不那么冗长:
var createSomething = Object.create(someObject, {getCreated:function()
{
console.log(this.myProperty);
},
myProperty:new Date()});
Run Code Online (Sandbox Code Playgroud)
但是IMO,这使得你更难以跟踪创建的对象在哪里(主要是因为它Object.create是一种表达,并且不会被提升.
嗯,这当然远非一个确凿的论点:两者都有他们的专家和骗子:我更喜欢使用模块模式,闭包和电源构造器,如果你不这样做就好了.
希望这能为你清理一件事或两件事.
| 归档时间: |
|
| 查看次数: |
643 次 |
| 最近记录: |