¿Por qué la propiedad privada no tiene el mismo alcance?

I am studying module pattern with javascript and the code below is my first try, a list of tasks. I have a small issue with variable's scope.

In one of my public methods I can access the tasks variable, in another one I can't. I will try to give more details.

I have my public method "addItem" which basically does a "push" in an array tasks.push(values); in this moment it works well, my array gets the new data.

But when I try to show the same variable in my other public method "deleteTask", example: console.log('deleteTask: ', tasks);. It returns me "deleteTask: undefined"

In the second code snippet, I am showing, how I access the methods.

Well, basically I am trying to understand, why am I not able to access the private variable in "deleteTask"? And why can I in "addItem"? What the difference? It looks like simple, but I am not getting so far.

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));

Mi HTML:

Here I am accessing the public methods through events:

<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>

I am studying this pattern through este enlace

preguntado el 09 de septiembre de 13 a las 20:09

Was that mile and a half of whitespace en realidad ¿necesario? -

sorry for that, the code came from my tests... -

2 Respuestas

Why can I access the private variable in "addItem"?

That's the default. Variables in higher (enclosing) scopes are accessible to every function defined inside there, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope#Nested_functions_and_closures.

Why can't I in "deleteTask"?

Because of that line:

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

Here you are declaring another variable with the name tasks for the scope of the deleteTask function. It will sombra the other one. Probably you didn't want to do that but overwrite the tasks variable from the upper scope - just omit the var keyword.

Respondido el 09 de Septiembre de 13 a las 21:09

It happens because in the deleteTask method you define a new local variable named tasks, which is undefined (does not have any value assigned) at the moment of usage:

 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();
 }

It doesn't matter if you first use, and then define it - the var definition will override the tasks you intend to use with the local tasks, which has no value assigned yet ( won't have one until the grep execution). I recommend reading about var hoisting in javascript.
You could rename the local tasks variable to quickly fix this problem. However, as Bergi said, you would possibly want to modify the tasks that's outside the function's scope, so avoiding the var keyword would suffice.

Respondido el 09 de Septiembre de 13 a las 22:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.