从“原型”和“新”移动到闭合和暴露模式 [英] Moving from `prototype` and `new` to a closure-and-exposure pattern

查看:106
本文介绍了从“原型”和“新”移动到闭合和暴露模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在重新考虑别人的JavaScript代码。

I have been re-factoring someone else's JavaScript code.

之前:

function SomeObj(flag) {
    var _private = true;
    this.flag = (flag) ? true : false;
    this.version="1.1 (prototype)";
    if (!this._someProperty) this._init();
            // leading underscore hints at what should be a 'private' to me
    this.reset(); // assumes reset has been added...
}

SomeObj.prototype.reset = function() {
    /* perform some actions */
}

/* UPDATE */
SomeObj.prototype.getPrivate = function() {
    return _private; // will return undefined
}

/* ...several other functions appended via `prototype`...*/

AFTER:

var SomeObj = function (flag) {
    var _private = true;
    this.flag = (flag) ? true : false;
    this.version = "2.0 (constructor)";

    this.reset = function () {
       /* perform some actions */
    };

    /* UPDATE */
    this.getPrivate = function() {
        return _private; // will return true
    }

    /* other functions and function calls here */
}

对我来说,第一个例子看起来很难阅读,特别是在更大的上下文中。像这样使用 reset 添加方法,使用原型属性,似乎不太受控制,因为它可能发生在任何地方剧本。我的重构代码(上面的第二个例子)看起来更整洁,因此更容易阅读,因为它是自包含的。我已经通过变量声明获得了一些隐私,但我已经失去了原型链的可能性。

For me the first example looks difficult to read, especially in a larger context. Adding methods like reset on like this, using the prototype property, seems much less controlled as it can presumably happen anywhere in the script. My refactored code (the second example above) looks much neater to me and is therefore easier to read because it's self-contained. I've gained some privacy with the variable declarations but I've lost the possibilities the prototype chain.

...

问题:


  1. 首先,我想知道我还有什么由于上述原型丢失,或者如果对原型链的损失有更大的影响。 本文是6岁,但声称使用原型属性在大规模比封闭模式更有效。

  1. Firstly, I'm interested to know what else I have lost by foregoing prototype, or if there are larger implications to the loss of the prototype chain. This article is 6 years old but claims that using the prototype property is much more efficient on a large scale than closure patterns.

上面的示例仍然会由 new 运算符实例化;它们都是古典的构造函数。最后,我甚至想远离这个模型,所有的属性和函数声明为 var s,我有一个方法,我公开,能够返回一个对象打开了我需要的所有属性和方法,具有特权(通过关闭)到私有的。这样的东西:

Both the examples above would still be instantiated by a new operator; they are both 'classical'-ish constructors. Eventually I'd even like to move away from this into a model where all the properties and functions are declared as vars and I have one method which I expose that's capable of returning an object opening up all the properties and methods I need, which have privileges (by virtue of closure) to those that are private. Something like this:

var SomeObj = (function () {

    /* all the stuff mentioned above, declared as 'private' `var`s */

    /* UPDATE */
    var getPrivate = function () {
        return private;
    }

    var expose = function (flag) {
         // just returns `flag` for now
         // but could expose other properties
         return {
             flag: flag || false, // flag from argument, or default value
             getPrivate: getPrivate
         } 
    };

    return {
        expose: expose
    }
})(); // IIFE

// instead of having to write `var whatever = new SomeObj(true);` use...
var whatever = SomeObj.expose();

有关StackOverflow的几个答案解决原型vs.关闭问题(在这里这里)。但是,与原型属性一样,我感兴趣的是向这个方向移动,远离 new 运算符意味着我的代码的效率和任何可能性的损失(例如 instanceof 丢失)。如果我不打算继续使用原型继承,我实际上是否会在 new 操作符之前丢失任何内容?

There are a few answers on StackOverflow addressing the 'prototype vs. closure' question (here and here, for example). But, as with the prototype property, I'm interested in what a move towards this and away from the new operator means for the efficiency of my code and for any loss of possibility (e.g. instanceof is lost). If I'm not going to be using prototypal inheritance anyway, do I actually lose anything in foregoing the new operator?

如果我被允许,更宽松的问题,因为我要求上面的细节:如果原型真的是最有效的方式,有更多的优势(无论你认为他们可能是什么)比闭合,有什么指导或设计模式,以更新的方式写他们吗?

A looser question if I'm permitted, given that I'm asking for specifics above: if prototype and new really are the most efficient way to go, with more advantages (whatever you think they might be) than closure, are there any guidelines or design patterns for writing them in a neater fashion?

...

请注意, expose 每次都返回一个新对象,因此这是实例化发生的地方。根据我的理解,对象引用在 SomeObj 闭包中声明的方法,它们是所有对象的相同方法(除非被覆盖)。在标志变量(我现在已更正)的情况下,这可以继承自 expose ,具有默认值,或再次返回到封装的预先存在的方法或属性。因此,有对象被生成的实例,并有一些继承(加上多态性?)在这里。

Note that expose returns a new object each time, so this is where the instantiation happens. As I understand this, where that object refers to methods declared in the SomeObj closure, they are the same methods across all objects (unless overwritten). In the case of the flag variable (which I've now corrected), this can be inherited from the argument of expose, have a default value, or again refer back to a encapsulated pre-existing method or property. So there are instances of objects being produced and there is some inheritance (plus polymorphism?) going on here.

所以重复问题2:如果我不去无论如何使用原型继承,我实际上在上述 new 运算符中丢失了什么吗?

So to repeat question 2: If I'm not going to be using prototypal inheritance anyway, do I actually lose anything in foregoing the new operator?

推荐答案


我之前失去的还有原型

我相信有人可以提供答案,至少给它一枪。至少有两个原因使用原型

I'm sure someone can provide an answer, but I'll at least give it a shot. There are at least two reasons to use prototype:





$

将方法创建为对象成员意味着为对象的每个实例创建方法。这是每个对象更多的内存,它减慢了对象创建(因此你的效率)。人们倾向于说,原型方法就像类方法,而成员方法就像对象方法,但这是非常误导,因为原型链中的方法仍然可以使用对象实例。

Creating a method as an object member means that it is created for every instance of the object. That's more memory per object, and it slows down object creation (hence your efficiency). People tend to say that prototype methods are like class methods whereas member methods are like object methods, but this is very misleading since methods in the prototype chain can still use the object instance.

您可以将原型定义为对象本身,因此您可能更喜欢语法(但它并不完全不同):

You can define the prototype as an object itself, so you may like the syntax better (but it's not all that different):

SomeObj.prototype = {
    method1: function () {},
    method2: function () {}
}

你的论点似乎较少受到控制对我有效。我认为在创建对象时涉及到两个块是很奇怪的。但是,它有点虚假,没有什么阻止某人覆盖你的其他对象的原型。

Your argument that it seems less controlled is valid to me. I get that it is weird to have two blocks involved in creating an object. However, it's a bit spurious in that there is nothing stopping someone from overwriting the prototype of your other object anyway.

//Your code
var SomeObj = function (flag) { //...

//Sneaky person's code
delete SomeObj.reset;
SomeObj.prototype.reset = function () { /* what now? */ }



前进



如果你只是通过 {} 符号在飞行中创建特定的对象实例,使用 new 。您需要使用 new 从类( function )定义创建同一对象的多个实例。这是不寻常的,因为它适用于任何面向对象的编程语言,它与重用。

Foregoing new

If you're only going to be creating specific object instances on the fly via {} notation, it's not really different from using new anyway. You would need to use new to create multiple instances of the same object from a class (function) definition. This is not unusual as it applies to any object oriented programming language, and it has to do with reuse.

对于您当前的应用程序,这可能工作很好。但是,如果你想出了一个可重用的跨上下文的一些真棒插件,它可能会令人讨厌,必须重写它很多。我认为您正在寻找类似 require.js 的内容,它允许您定义可以使用 require 函数导入的模块。你在一个 define 函数闭包中定义一个模块,所以你可以保持构造函数和原型定义被包装在一起,没有其他人可以触摸它们,直到他们导入模块

For your current application, this may work great. However, if you came up with some awesome plugin that was reusable across contexts, it could get annoying to have to rewrite it a lot. I think that you are looking for something like require.js, which allows you to define "modules" that you can import with the require function. You define a module within a define function closure, so you get to keep the constructor and prototype definitions wrapped together anyway, and no one else can touch them until they've imported that module.

它们不是互斥的:

var attachTo = {};
;(function (attachTo, window, document, undefined) {
    Plugin = function () { /* constructor */ };
    Plugin.prototype = { /* prototype methods */ };

    attachTo.plugin = Plugin;
})(attachTo, window, document);
var plugin = new (attachTo.plugin);

http://jsfiddle.net/ExplosionPIlls/HPjV7/1/

这篇关于从“原型”和“新”移动到闭合和暴露模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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