具有原型与闭包的面向对象的 javascript

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3564238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 05:12:35  来源:igfitidea点击:

Object oriented javascript with prototypes vs closures

javascriptoop

提问by David

I'm curious what the difference is between the following OOP javascript techniques. They seem to end up doing the same thing but is one considered better than the other?

我很好奇以下 OOP javascript 技术之间的区别是什么。他们似乎最终做着同样的事情,但被认为比另一个更好吗?

function Book(title) {
    this.title = title;
}

Book.prototype.getTitle = function () {
    return this.title;
};

var myBook = new Book('War and Peace');
alert(myBook.getTitle())

vs

对比

function Book(title) {
    var book = {
        title: title
    };
    book.getTitle = function () {
        return this.title;
    };
    return book;
}

var myBook = Book('War and Peace');
alert(myBook.getTitle())

采纳答案by reko_t

The second one doesn't really create an instance, it simply returns an object. That means you can't take advantage of operators like instanceof. Eg. with the first case you can do if (myBook instanceof Book)to check if the variable is a type of Book, while with the second example this would fail.

第二个并没有真正创建一个实例,它只是返回一个对象。这意味着你不能利用像instanceof. 例如。对于第一种情况,您可以if (myBook instanceof Book)检查变量是否为 Book 类型,而对于第二个示例,这将失败。

If you want to specify your object methods in the constructor, this is the proper way to do it:

如果要在构造函数中指定对象方法,这是正确的方法:

function Book(title) {
    this.title = title;

    this.getTitle = function () {
        return this.title;
    };
}

var myBook = new Book('War and Peace');
alert(myBook.getTitle())

While in this example the both behave the exact same way, there are differences. With closure-based implementation you can have private variables and methods (just don't expose them in the thisobject). So you can do something such as:

虽然在此示例中两者的行为方式完全相同,但还是存在差异。使用基于闭包的实现,您可以拥有私有变量和方法(只是不要在this对象中公开它们)。因此,您可以执行以下操作:

function Book(title) {
    var title_;

    this.getTitle = function() {
        return title_;
    };

    this.setTitle = function(title) {
        title_ = title;
    };

    // should use the setter in case it does something else than just assign
    this.setTitle(title);
}

Code outside of the Book function can not access the member variable directly, they have to use the accessors.

Book 函数之外的代码不能直接访问成员变量,它们必须使用访问器。

Other big difference is performance; Prototype based classing is usually much faster, due to some overhead included in using closures. You can read about the performance differences in this article: http://blogs.msdn.com/b/kristoffer/archive/2007/02/13/javascript-prototype-versus-closure-execution-speed.aspx

另一个很大的区别是性能;由于使用闭包中包含的一些开销,基于原型的分类通常要快得多。您可以在本文中了解性能差异:http: //blogs.msdn.com/b/kristoffer/archive/2007/02/13/javascript-prototype-versus-closure-execution-speed.aspx

回答by J. McNerney

Which is bettercan sometimes be defined by the context of their usage.

有时可以通过使用上下文来定义哪个更好

Three constraints of how I choose between Prototypeand Closuremethods of coding (I actively use both):

我如何在PrototypeClosure编码方法之间进行选择的三个约束(我积极使用两者):

  1. Performance/Resources
  2. Compression requirements
  3. Project Management
  1. 性能/资源
  2. 压缩要求
  3. 项目管理

1. Performance/Resources

1. 性能/资源

For a single instance of the object, either method is fine. Any speed advantages would most likely be negligible.

对于对象的单个实例,任何一种方法都可以。任何速度优势很可能可以忽略不计。

If I am instantiating 100,000 of these, like building a book library, then the Prototype Methodwould be preferred. All the .prototype. functions would only be created once, instead of these functions being created 100,000 times if using the Closure Method. Resources are not infinite.

如果我要实例化其中的 100,000 个,例如构建图书库,那么Prototype Method将是首选。所有的.prototype。函数只会被创建一次,如果使用Closure Method,这些函数不会被创建 100,000 次。资源不是无限的。

2. Compression

2. 压缩

Use the Closure Methodif compression efficiency is important (ex: most browser libraries/modules). See below for explanation:

如果压缩效率很重要(例如:大多数浏览器库/模块),请使用Closure Method。请参阅以下说明:

Compression - Prototype Method

压缩 - 原型方法

function Book(title) {
    this.title = title;
}

Book.prototype.getTitle = function () {
  return this.title;
};

Is YUI compressed to

YUI 是否压缩为

function Book(a){this.title=a}Book.prototype.getTitle=function(){return this.title};

A savings of about 18% (all spaces/tabs/returns). This method requires variables/functions to be exposed (this.variable=value) so every prototype function can access them. As such, these variables/functions can't be optimized in compression.

节省约 18%(所有空格/制表符/返回)。此方法需要公开变量/函数(this.variable=value),以便每个原型函数都可以访问它们。因此,无法在压缩中优化这些变量/函数。

Compression - Closure Method

压缩 - 闭合方法

function Book(title) {
  var title = title; // use var instead of this.title to make this a local variable

this.getTitle = function () {
  return title;
};
}

Is YUI compressed to

YUI 是否压缩为

function Book(a){var a=a;this.getTitle=function(){return a}};

A savings of about 33%. Local variables can be optimized. In a large module, with many support functions, this can have significant savings in compression.

节省约 33%。可以优化局部变量。在具有许多支持功能的大型模块中,这可以显着节省压缩成本。

3. Project Management

3. 项目管理

In a project with multiple developers, who could be working on the same module, I prefer the Prototype Methodfor that module, if not constrained by performance or compression.

在一个有多个开发人员的项目中,他们可能在同一个模块上工作,如果不受性能或压缩的限制,我更喜欢该模块的原型方法

For browser development, I can override the producton.prototype.aFunction from "production.js" in my own "test.js" (read in afterwords) for the purpose of testing or development, without having to modify the "production.js", which may be in active development by a different developer.

对于浏览器开发,我可以在我自己的“test.js”(阅读后记)中覆盖“production.js”中的 producton.prototype.aFunction 以进行测试或开发,而无需修改“production.js” ,它可能正在由不同的开发人员积极开发。

I'm not a big fan of complex GIT repository checkout/branch/merge/conflict flow. I prefer simple.

我不是复杂的 GIT 存储库检出/分支/合并/冲突流的忠实粉丝。我更喜欢简单。

Also, the ability to redefine or "hiHyman" a module's function by a testbench can be beneficial, but too complicated to address here...

此外,通过测试平台重新定义或“劫持”模块功能的能力可能是有益的,但在这里解决太复杂了......

回答by Skilldrick

The former method is how JavaScript was intended to be used. The latter is the more modern technique, popularised in part by Douglas Crockford. This technique is much more flexible.

前一种方法是 JavaScript 的使用方式。后者是更现代的技术,部分由道格拉斯·克罗克福德 (Douglas Crockford) 推广。这种技术要灵活得多。

You could also do:

你也可以这样做:

function Book(title) {
    return {
        getTitle: function () {
            return title;
        }
    }
}

The returned object would just have an accessor called getTitle, which would return the argument, held in closure.

返回的对象只有一个名为 的访问器getTitle,它会返回闭包中的参数。

Crockford has a good page on Private Members in JavaScript- definitely worth a read to see the different options.

Crockford在 JavaScript 中的私人成员上有一个很好的页面- 绝对值得一读以查看不同的选项。

回答by Arman McHitarian

It's also a little bit about re-usability under the hood. In the first example with the Function.prototypeproperty usage all the instances of the Book function-object will share the same copy of the getTitlemethod. While the second snippet will make the Bookfunction execution create and keep in the heap 'bookshelf' different copies of the local closurablebookobject.

这也是关于引擎盖下的可重用性。在第一个使用Function.prototype属性的示例中,Book 函数对象的所有实例都将共享该getTitle方法的相同副本。而第二个片段将使Book函数执行创建并保留在堆“书架”中的本地可关闭book对象的不同副本。

function Book(title) {
    var book = {
        title: title
    };
    book.getTitle = function () {
        return this.title += '#';
    };
    return book;
}

var myBook = Book('War and Peace');
var myAnotherBook = Book('Anna Karenina');
alert(myBook.getTitle()); // War and Peace#
alert(myBook.getTitle()); // War and Peace##
alert(myAnotherBook.getTitle()); // Anna Karenina#
alert(myBook.getTitle());// War and Peace###

The prototype members exist in the only copy for all the newinstances of the object on the other hand. So this is one more subtle difference between them that is not very obvious from the first sigh due to the closure trick.

new另一方面,原型成员存在于对象所有实例的唯一副本中。所以这是他们之间的一个更微妙的区别,由于关闭技巧,从第一次叹息中看并不很明显。

回答by tsinik

here is an article about thisin general Book inharets from Book.prototype. In first example you add function to getTitle Book.prototype

这里有一篇关于这方面的文章,一般来说 Book inharets 来自 Book.prototype。在第一个示例中,您将函数添加到 getTitle Book.prototype