Although code like this is probably not best practice, I ran into something strange while working the other day. Recreating it as a simple example, I expected the following code to alert 'dog' and then 'cat', but instead it alerted 'dog' twice. By my understanding of JavaScript closure, that seems like very odd behavior to me. Anyone have a good explanation for this?
var printMan = {
printer: function(animal){
this.innerPrinter = this.innerPrinter || function(){
alert(animal)
}
this.innerPrinter(animal)
}
}
printMan.printer('dog' )
printMan.printer('cat')
Here's the Fiddle
Edit ----- Thanks everyone for the great explanations. This is one of the reasons why I love this language - there's a great community here. I thought I knew a great deal about the language, but I was wrong about how this function would work. For anyone reading this, it's probably best to not do something like this example.
The function you assign to this.innerPrinter does not have any arguments in its definition:
function(){
alert(animal)
}
So when you call it with this.innerPrinter(animal), it ignores the argument and gets animal from the wider scope (which is printer: function(animal){).
The first time you call printer, the object does not have a innerPrinter value, so you assign a new function to it.
This function is declared within the scope of the first call to printer, so animal is 'dog'. It alerts 'dog'.
The second time you call the function, this.innerPrinter already has a value, so this.innerPrinter || function(){ evaluates as the function from the first call. It therefore alerts 'dog' because that is the value of animal for the first function generated from the function expression.
It is in fact perfectly normal that you are getting two dogs. You forgot the parameter in the inner function. It should look like this:
var printMan = {
printer: function(animal){
this.innerPrinter = this.innerPrinter || function(animal){
alert(animal)
}
this.innerPrinter(animal)
}
}
printMan.printer('dog' )
printMan.printer('cat')
Let me try to explain. The first time you go trough the printer function, the innerPrinter gets constructed, and the variable is hard coded in there from it's parent scope. The second time you call the printer, the innerPrinter you made in the previous cycle is used, with your hard coded dog in there. By passing the parameter it is not hard coded and you will get the expected cat on the second run. Changing the variable names may make it a bit clearer:
printer: function(animal){
this.innerPrinter = this.innerPrinter || function(innerAnimal){
alert(innerAnimal)
}
this.innerPrinter(animal)
}
Hope this makes sense. Feel free to ask if you want me to explain further.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With