Reputation: 2602
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));
My 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 this link
Upvotes: 2
Views: 60
Reputation: 5348
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.
Upvotes: 0
Reputation: 664579
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 shadow 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.
Upvotes: 1