【问题标题】:Simple JavaScript OOP Class简单的 JavaScript OOP 类
【发布时间】:2013-07-25 22:41:25
【问题描述】:

我正在使用 John Resig 的简单 OOP Class,它适用于“使用严格”并取自 SO post
在所有示例中,我都看到Class.extend 的用法如下:

var MyObj = Class.extend({
    init:function(){},
    prop: "Property"
});

但我发现以这种方式使用它对我来说有一个很大的缺点——我不能有“私有”变量,所以我不能像 var $this = this; 那样存储对 this 的引用。 我找到了适合我的情况的解决方案,现在我以下列方式使用Class.extend

var MyObj = Class.extend(new function(){
    var $this = this;
    this.init = function(){};
    this.prop = "Property";
});

在我的情况下一切正常,但我想知道从长远来看是否有一些事情会导致我出现问题?
这样我的应用程序会在浏览器中消耗更多内存吗?
我必须通过哪些替代方式来实现我的需求?

注意:我需要存储 $this,因为我大量使用事件和回调,所以我想引用“原始”this 以便访问对象上的所有方法和属性。

编辑:根据要求,这是我的代码示例:

(function () {
    "use strict";
    window.QuickPlay = Class.extend(new function () {
        var $this = this;

        this.init = function (initData) {
            $this.elementsToHide.push(initData.el);
            $(function () {
                playProcessStart();
                Sys.Application.add_load(function () {
                    $find("ctl00_ContentPlaceHolderMain_ctrlPlayPopup1").add_closed(function () { $this.setElementsVisibility(""); });
                });
                $this.setElementsVisibility("hidden");
            });
        };

        this.elementsToHide = [];

        this.setElementsVisibility = function (visibility) {
            $.each($this.elementsToHide, function (i) {
                $("#" + this).css("visibility", visibility);
            });
        };
    });
} ());

【问题讨论】:

  • 哎呀,不。我几乎不敢相信这真的对你有用。请向我们展示您如何将这个“类”与事件和回调一起使用;也许发布您的实际代码(至少涉及$this的方法)。
  • @Bergi 我添加了示例 - 这确实有效,代码已经通过了 QA 阶段:)
  • 在任何对象内部,您都应该能够访问this,它会存储到当前对象。
  • @travis 如果你看到,在 jQuery 文档准备好时,我正在使用 $this,因为如果我要使用它,它不会引用 QuickPlay 的实例 :)
  • 然后解雇 QA 团队:-/ 要看到它崩溃,您可以尝试创建多个实例。或者它应该是一个单身人士?那么你根本不应该使用Class

标签: javascript oop


【解决方案1】:

您可以使用模块模式并维护所有 OOP。这种模式为您的代码提供了更高的安全性和更好的组织。

//these are namespaces in javascript
window.project = window.project || {}; //this kind declarations prevents recreate the object
project.group = project.group || {};

//in the line below we can use $ instead jQuery, and use window and document instead ask for the browser every time.
(function (window, document, $) {
    "use strict";

    project.group.NameOfYourModule = function () {
        var privateAttribute = true,
            students = 32,    //It's is a best practice declare everything in an unique var.

            privateMethod = function () {
                alert('Now I know OOP using jQuery');
            };

        return {
            init: function () {
                //this is a public method and we can initiate some private method;
                privateMethod();

                //we call a public method using this
                this.publicMethod();
            },
            publicMethod: function () {
                //this is a public method
            }
        };
    };

    $(function () {
        var myclass = new project.group.NameOfYourModule(); //instantiate you class
        myclass.init(); //initiate some public method
    });
}(window, document, jQuery));
  • JsFiddle 的工作示例
  • 如何使用继承和模块模式here

【讨论】:

  • 看起来不错,但是继承呢?在您的模式中,我如何创建继承自 NameOfYourModule 的 MySecondModule?班级给了我。
  • 我添加了参考解释它是如何工作的继承。很高兴帮助:)
  • 谢谢,我看到了链接...我相信它会起作用,但它对其他团队成员来说太复杂了:(我正在尝试一些易于使用的东西...
  • 在我公司我们使用这种模式,维护组织并防止将来出现一些问题。为什么不花点时间学习更复杂的模式呢?将来,您可能会遇到组织问题,并且必须重构所有代码。想想看 :) 没那么复杂,我发誓 ;)
  • @RafaelGomes:你所拥有的看起来不像(单例)模块,更像是一个类。您不会使其可实例化,而是在 IEFE 中创建它。并删除 new 关键字,您只是从工厂返回一个对象,而不是调用构造函数!
【解决方案2】:

我不能有“私有”变量

当然可以。在(当前不必要的)(function () { … } ()); 包装器中,或者在您的构造函数中(init 事物)。

new function () {

Avoid that pattern!如果你真的需要你的代码像现在这样工作,使用

(function () {
    "use strict";
    // Here's the place where you could put a private, static variable
    // for example `var elementsToHide = [];`
    var $this = {
        init: function (initData) {
            $this.elementsToHide.push(initData.el);
            $(function () {
                playProcessStart();
                Sys.Application.add_load(function () {
                    $find("ctl00_ContentPlaceHolderMain_ctrlPlayPopup1").add_closed(function () {
                        $this.setElementsVisibility("");
                    });
                });
                $this.setElementsVisibility("hidden");
            });
        },
        elementsToHide: [],
        setElementsVisibility: function (visibility) {
            $.each($this.elementsToHide, function (i) {
                $("#" + this).css("visibility", visibility);
            });
        }
    };
    window.QuickPlay = Class.extend($this);
}());

我想知道是否有一些事情会导致我出现问题

是的。多个实例几乎不会起作用,因为它们都引用相同的elementsToHide 数组。而且您没有使用任何实例方法(仅类上的构造函数和静态元素),因此类模式似乎完全没有必要。请改用a module。如果您需要单个实例(和类),代码应如下所示:

"use strict";

window.QuickPlay = Class.extend({
    init: function (initData) {
        var $this = this;
        this.elementsToHide = [];
        $(function () {
            playProcessStart();
            $this.elementsToHide.push(document.getElementById(initData.el));
            Sys.Application.add_load(function () {
                $find("ctl00_ContentPlaceHolderMain_ctrlPlayPopup1").add_closed(function () {
                    $this.setElementsVisibility("");
                });
            });
            $this.setElementsVisibility("hidden");
        });
    },
    setElementsVisibility: function (visibility) {
        $(this.elementsToHide).css("visibility", visibility);
    }
});

【讨论】:

  • 感谢您以我使用 Class 的方式指出“巨大”问题...在我的应用程序中,我需要使用“singletons”和 Classes,所以看起来我需要为每种情况使用/创建两种不同的模式。目前我刚开始在项目中使用 JS OOP,所以现在改变还为时不晚 :)
  • 您能否指出一个好的模式,如何创建一个需要在创建时使用数据初始化的“模块”?
  • 我认为单例模块是完全静态的,没有“创建”。我可以想到a)数据被编码到模块代码中b)模块从全局“数据存储”中获取数据本身c)全局控制器通过调用init方法来“启动”模块,数据为论据。请参阅我链接的 Osmani 的文章以了解代码结构模式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-02
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
  • 1970-01-01
相关资源
最近更新 更多