gpt4 book ai didi

javascript - JavaScript 中 "class"定义的这三种模式有什么区别?

转载 作者:可可西里 更新时间:2023-11-01 01:33:29 25 4
gpt4 key购买 nike

在选择使用这四种模式之一而不是其他模式时,引擎盖下是否有任何重要/微妙/显着差异?并且,当通过 Object.create()“实例化”时,它们之间有什么区别吗?对比 new运算符(operator)?

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) Knockout的模式似乎促进:
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 的响应//次要格式

最佳答案

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

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

昏死:
现在这让我有点困惑,因为至少对我来说,你提供的代码片段看起来像是模块模式的一部分,或者是一个强大的构造函数。但是由于您没有使用 strict mode ,省略 new仍然会导致危险的情况,因为整个函数都会遇到创建 DifferentAnimal 的新实例的麻烦。 ,然后构造第二个对象字面量,分配 DifferentAnimal 的所有属性对于那个次要对象,我会说你错过了一些东西。因为,说实话,省略了最后一个 return {};在这里声明,可能根本没有区别。另外:正如您所看到的,您在本质上是一个构造函数中声明了一个方法( move )。这意味着每个实例都将被分配自己的函数对象 move ,而不是从原型(prototype)中获取它。
简而言之:再仔细看看你从哪里得到这个片段,并仔细检查这是否是完整版本,因为如果是,我只能看到反对这一点的论据。

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

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;什么的,那通常就是创建一个在任何地方都可用的主对象的引用,而不必处理 this的头疼问题。 ( this 引用什么?该方法应用于对象而不是它最初打算用于的对象时应该做什么?等等......)

Backbone :
在这里,我们正在处理另一种情况:扩展对象(即:使用现有“类”(构造函数)或特定实例的方法、属性)与简单地创建对象不同。
众所周知,JS 对象可以在任何给定时间分配新属性。这些属性也可以删除。有时,原型(prototype)属性可以在实例本身上重新定义(掩盖原型(prototype)行为)等等......所以这一切都取决于你想要结果对象(新创建的对象,扩展给定实例)看起来像:你希望它从实例中获取所有属性,还是希望两个对象都在某处使用相同的原型(prototype)?
这两件事也可以通过使用简单的 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');
}});

短很多,但缺少构造函数。
new对比 Object.create嗯,这很简单: Object.create只是比 new 强大得多:您可以在需要创建对象的时候定义原型(prototype)方法、属性(包括天气与否,它们是否可枚举、可写等...),而不必编写构造函数和原型(prototype),或创建对象字面量和所有这些人混在一起 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;
};
}());

现在这很冗长,但我已经准备好了基本的构造函数,我也可以用它来扩展现有的实例。简单地写下似乎不那么冗长:
var createSomething = Object.create(someObject, {getCreated:function()
{
console.log(this.myProperty);
},
myProperty:new Date()});

但是 IMO,这让您很难跟踪在何处创建了什么对象(主要是因为 Object.create 是一个表达式,并且不会被提升。嗯,当然,这远不是一个决定性的论点:两者都有他们的专业人士和缺点:我更喜欢使用模块模式、闭包和电源构造函数,如果你不这样做就好了。

希望这可以为您解决一两件事。

关于javascript - JavaScript 中 "class"定义的这三种模式有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13789559/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com