Reputation: 862
var x = 1;
(function(x, j) {
j.fn.cool = function() {};
x = 2;
})(x, jQuery);
console.log(jQuery.fn.cool); // returns the newly added function
I noticed this happens not with just jQuery, so I assume it's related to passing specifically objects (perhaps arrays too). This doesn't happen with primitives.
Upvotes: 4
Views: 222
Reputation: 11116
Okay, so when you have the parameter x, your x = 2 refers to the local copy that is scoped to your IIFE, it does not refer to the x that exists on the global scope. This is because the compiler always looks at the closest scope for the existance of a variable before moving outward. The reason that you can set the property on the "j" parameter, however, is because javascript treats primitives differently than objects/arrays when passed as parameters.
Any parameter in javascript is passed by value - always. Meaning that if you were to assign a new value to that parameter, it will remain unchanged in the calling scope. HOWEVER, there are a couple exceptions (objects/arrays) in that if you assign a PROPERTY of that object, or a specific ELEMENT of the array, it WILL reflect the change in the calling scope. Some people call it "pass-by-reference" because it behaves similarly, but technically speaking, the variable itself is still passed by value in every situation.
As per this stack answer, these are the rules.
- Primitive type variables like strings and numbers always remain unchanged in their calling scope.
Arrays and Objects are changed in their calling scope based on these conditions:
If you are assigning a new value to an object or array it is UNCHANGED in the calling scope
object1 = {prop: "car"}; array1 = [1,2,3];
If you are assigning a new value to a PROPERTY of an object, or ELEMENT of an array then it WILL BE CHANGED in the calling scope
object1.prop = "car"; array1[0] = 9;
You can see proof of this HERE by removing x from your argument/parameter list, and leaving everything else the same. Since there is no local variable with an identifier of x that is scoped to your IIFE, the compiler goes out and checks on the global scope, where it will find your var x declaration, and it will use that and set it equal to 2.
Great question! Hope that helps clear things up! Let me know if you need any more clarification.
Upvotes: 2