有没有一种干净的方法来访问命名空间内的私有变量

发布于 2024-10-22 20:20:49 字数 2950 浏览 3 评论 0原文

我正在使用 https://github.com/smith/namespacedotjs 中的命名空间脚本来封装我的控制 -我的 ASP.NET MVC 应用程序中的特定 javascript 和 jQuery 代码。如果不使用命名空间,同名的方法可能会相互干扰并导致不良行为。

这是我的当前工作代码

<script type="text/javascript">

Namespace('MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber', {

        SelectDrawingNumbersControl: {
            selectedIds: [],

            setSelectedIds: function() {
                // wire up checkboxes
                $('#DrawingSheetNumbersGrid :checkbox').live('change', function(e) {
                    var $check = $(this);
                    console.log($check);
                    if ($check.is(':checked')) {
                        // add id to selectedIds
                        MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber.SelectDrawingNumbersControl.selectedIds.push($check.val());
                    }
                    else {
                        // remove id from selectedIds
                        MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber.SelectDrawingNumbersControl.selectedIds =
                            $.grep(MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber.SelectDrawingNumbersControl.selectedIds, function(item, index) {
                            return item != $check.val();
                        });
                    }
                });
            }    
        }
    });

</script>

但是,在上面的代码示例中,请注意我使用的是变量“selectedIds”,它是一个字符串数组。由于此变量被声明为我的命名空间的一部分,因此我现在被迫从同一命名空间内的其他方法通过它的完全限定路径来引用它。

理想情况下,我更愿意写这样的内容:

<script type="text/javascript">

Namespace('MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber', {

        SelectDrawingNumbersControl: {
            selectedIds: [],

            setSelectedIds: function() {
                // wire up checkboxes
                $('#DrawingSheetNumbersGrid :checkbox').live('change', function(e) {
                    var $check = $(this);
                    console.log($check);
                    if ($check.is(':checked')) {
                        // add id to selectedIds
                        selectedIds.push($check.val());
                    }
                    else {
                        // remove id from selectedIds
                        selectedIds = $.grep(selectedIds, function(item, index) {
                            return item != $check.val();
                        });
                    }
                });
            }    
        }
    });

</script>

上面的现有代码示例 #1 感觉相当麻烦 - 我习惯于编写 C# 并引用来自同一名称空间的对象,而不完全限定它们(即代码示例 #2)。

我查看了 Ben Cherry 的记录的模块模式,其中我开始使用;然而,每次创建或更新模块时,在模块代码中传递所需的所有全局变量的列表似乎是维护的噩梦。

命名空间解决方案在语法上看起来更干净,如果我可以消除完全限定“私有”变量的需要,那将是绝对完美的。

有没有人有一个好的解决方案来解决这个 JavaScript 困境?

I am using the Namespace scripts from https://github.com/smith/namespacedotjs to encapsulate my control-specific javascript and jQuery code in my ASP.NET MVC application. Without using namespaces, methods of the same name can interfere with each other and cause undesired behavior.

Here is my current working code:

<script type="text/javascript">

Namespace('MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber', {

        SelectDrawingNumbersControl: {
            selectedIds: [],

            setSelectedIds: function() {
                // wire up checkboxes
                $('#DrawingSheetNumbersGrid :checkbox').live('change', function(e) {
                    var $check = $(this);
                    console.log($check);
                    if ($check.is(':checked')) {
                        // add id to selectedIds
                        MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber.SelectDrawingNumbersControl.selectedIds.push($check.val());
                    }
                    else {
                        // remove id from selectedIds
                        MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber.SelectDrawingNumbersControl.selectedIds =
                            $.grep(MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber.SelectDrawingNumbersControl.selectedIds, function(item, index) {
                            return item != $check.val();
                        });
                    }
                });
            }    
        }
    });

</script>

However, in the code sample above, notice I am using a variable "selectedIds" which is an array of strings. Since this variable is declared as part of my namespace I am now forced to reference it, from other methods inside the same namespace, by it's fully-qualified path.

Ideally, I would prefer to write something like this:

<script type="text/javascript">

Namespace('MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber', {

        SelectDrawingNumbersControl: {
            selectedIds: [],

            setSelectedIds: function() {
                // wire up checkboxes
                $('#DrawingSheetNumbersGrid :checkbox').live('change', function(e) {
                    var $check = $(this);
                    console.log($check);
                    if ($check.is(':checked')) {
                        // add id to selectedIds
                        selectedIds.push($check.val());
                    }
                    else {
                        // remove id from selectedIds
                        selectedIds = $.grep(selectedIds, function(item, index) {
                            return item != $check.val();
                        });
                    }
                });
            }    
        }
    });

</script>

My existing code sample #1 above feels pretty cumbersome - I am used to writing C# and referencing objects from the same namespace without fully qualifying them (i.e. code sample #2).

I have looked at Ben Cherry's documented module pattern, which I started to use; however, passing in the list of all globals needed inside the module code every time you create or update a module seems like a maintenance nightmare.

The namespace solution seems syntactically cleaner and would be absolutely perfect if I could do away with the need to fully qualify "private" variables.

Does anyone have a good solution to this JavaScript dilemma?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2024-10-29 20:20:49

我认为解决您的问题的最简单方法是在您打算使用的任何方法中保留对控件的引用。实际上,您只是为类名添加别名。

        setSelectedIds: function() {
            //keep a reference to SelectDrawingNumbersControl in case we need it
            var that = this;

            // wire up checkboxes
            $('#DrawingSheetNumbersGrid :checkbox').live('change', function(e) {
                var $check = $(this);
                console.log($check);
                if ($check.is(':checked')) {
                    // add id to selectedIds
                    that.selectedIds.push($check.val());
                }
                else {
                    // remove id from selectedIds
                    that.selectedIds =
                        $.grep(that.selectedIds, function(item, index) {
                        return item != $check.val();
                    });
                }
            });
        }

The easiest way I can think to resolve your problem would be to keep a reference to your control within whichever method you intend to use. Effectively you're just aliasing the classname.

        setSelectedIds: function() {
            //keep a reference to SelectDrawingNumbersControl in case we need it
            var that = this;

            // wire up checkboxes
            $('#DrawingSheetNumbersGrid :checkbox').live('change', function(e) {
                var $check = $(this);
                console.log($check);
                if ($check.is(':checked')) {
                    // add id to selectedIds
                    that.selectedIds.push($check.val());
                }
                else {
                    // remove id from selectedIds
                    that.selectedIds =
                        $.grep(that.selectedIds, function(item, index) {
                        return item != $check.val();
                    });
                }
            });
        }
烟酉 2024-10-29 20:20:49

由于您要将 selectedIds 设为命名空间的公共成员,因此它没有任何“私有”内容。

如果您想要真正的隐私,同时还为同级级别的方法提供对变量的访问权限,请将其定义在闭包内:

(function () {
    var selectedIds = [];

    Namespace('MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber', {
        SelectDrawingNumbersControl: {
            setSelectedIds: function() {
                // use selectedIds directly
                ...

})();

Since you're making selectedIds a public member of your namespace, there's nothing "private" about it.

If you want true privacy, while also giving methods at a sibling level access to the variable, define it inside a closure:

(function () {
    var selectedIds = [];

    Namespace('MyCompany.MyApp.ReviseDrawingNumber.AddSheetNumber', {
        SelectDrawingNumbersControl: {
            setSelectedIds: function() {
                // use selectedIds directly
                ...

})();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文