2

我正在使用 javascript 研究模块模式,下面的代码是我的第一次尝试,任务列表。我对变量的范围有一个小问题。

在我的一种公共方法中,我可以访问 tasks 变量,而在另一种方法中我不能。我会尽力提供更多细节。

我有我的公共方法“addItem”,它基本上在数组tasks.push(values);中执行“推送”,此时它运行良好,我的数组获取新数据。

但是当我尝试在我的其他公共方法“deleteTask”中显示相同的变量时,例如: console.log('deleteTask: ', tasks);. 它返回给我“deleteTask:未定义”

在第二个代码片段中,我将展示如何访问这些方法。

好吧,基本上我想了解,为什么我无法访问“deleteTask”中的私有变量?为什么我可以在“addItem”中?有什么区别?它看起来很简单,但我还没有走这么远。

var todoModule = (function ($) {
    var tasks = [];

    function doListOfTasks() {
        for(var i=0; i<tasks.length; i++){
            $('<li>', {
                name    : 'liTask',
                id      : 'liTask'+i,
                html    : tasks[i].title + ' - '
            }).appendTo('#listOfTasks');

            $('<input>', {
                type    : 'button',
                name    : 'delTask',
                id      : 'delTask'+i,
                value   : 'Del'
            }).appendTo('#liTask'+i);

            $('#delTask'+i).data('idTask', i);
        }
    }

    function clearListTasks(){
        $('#listOfTasks').html('');
    }

    return { 
        init: function(){
            this.getListTasks();
        },

        getListTasks: doListOfTasks,

        addItem: function( values ) {
            tasks.push(values);
            clearListTasks();
            this.getListTasks();

            console.log('addItem: ', tasks);
        },

        deleteTask: function(item) {
            console.log('deleteTask: ', tasks);

            var tasks = $.grep(tasks, function(value, item) {
                        //console.log('value: ', value);
                        //console.log('item: ', item);
                        return value != item;
                    });

            clearListTasks();
            doListOfTasks();
        }
    };
}(jQuery));

我的 HTML:

这里我通过事件访问公共方法:

<script type="text/javascript">
    $( document ).ready(function() {
            todoModule.init();

            $( '#btnAdd' ).click(function() {
                todoModule.addItem({
                    title: $('#tarefa').val(),
                    date: '01/01/1999',
                    flag: 0
                });
            });

            $('ul').on('click', 'input', function() {
                var idTask = $('#'+this.id).data('idTask');
                todoModule.deleteTask(idTask);
            });
        });
</script>

我正在通过这个链接研究这个模式

4

2 回答 2

1

为什么我可以访问“addItem”中的私有变量?

这是默认设置。在那里定义的每个函数都可以访问更高(封闭)范围内的变量,请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope#Nested_functions_and_closures

为什么我不能在“deleteTask”中?

因为那条线:

    var tasks = $.grep(tasks, …)
//  ^^^

在这里,您要声明另一个具有函数tasks范围名称的变量deleteTask。它会遮蔽另一个。可能您不想这样做,而是tasks从上层范围覆盖变量 - 只需省略var关键字

于 2013-09-09T20:21:04.940 回答
0

发生这种情况是因为在deleteTask方法中您定义了一个名为 的新局部变量tasks,该变量在使用时未定义(未分配任何值):

 deleteTask: function(item) {
      console.log('deleteTask: ', tasks);
      var tasks = $.grep(tasks, function(value, item) {
        //console.log('value: ', value);
        //console.log('item: ', item);
         return value != item;
      });
      clearListTasks();
      doListOfTasks();
 }

如果您首先使用然后定义它并不重要 - var 定义将覆盖tasks您打算与 local 一起使用的,它还tasks没有分配值(在 grep 执行之前不会有)。我推荐阅读var 提升在 javascript 中的内容。
您可以重命名局部tasks变量以快速解决此问题。但是,正如 Bergi 所说,您可能想要修改tasks函数范围之外的 ,因此避免使用var关键字就足够了。

于 2013-09-09T20:16:04.670 回答