为什么私有财产没有相同的范围?

时间:2013-09-09 19:56:23

标签: javascript design-patterns

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

在我的一个公共方法中,我可以访问任务变量,另一个我不能。我会尝试提供更多细节。

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

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

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

好吧,基本上我想了解,为什么我无法访问“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>

我正在通过this link

研究这种模式

2 个答案:

答案 0 :(得分: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 keyword

答案 1 :(得分: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一起使用的tasks,该tasks尚未分配任何值(直到grep执行才赢得一个)。我建议阅读var hoisting in javascript 您可以重命名本地tasks变量以快速解决此问题。但是,正如Bergi所说,您可能希望修改功能范围之外的var,因此避免使用{{1}}关键字就足够了。