0

I was building my own jQuery plugin and got to wondering how the changes to the $ object persist outside the IIFE:

(function($){
  //plugin
 }(jQuery);

so I played around in a JS REPL, and found that changes to objects and arrays persist outside an IIFE, but changes do strings do not:

var obj={a:1,b:2};

(function(obj){obj.c=3})(obj);

**obj**
{ a: 1, b: 2, c: 3 }

arr=[1,2]
[ 1, 2 ]

(function(arr){arr.push(3)})(arr);

**arr**
[ 1, 2, 3 ]

str='aoeu'
'aoeu'

(function(str){str+='aoeu'})(str);

**str**
'aoeu'

Could someone please explain to me the difference here between objects, arrays and strings??

Tim Gregg
  • 53
  • 6
  • Take a look at this http://stackoverflow.com/q/518000/3951400 – E. Sundin Jan 06 '16 at 17:42
  • Because strings are primitive, the `str` in the _function_ has a different reference to the `str` outside of the _function_. This means the `+=` operator never touches value of the outside identifier. If you're familiar with other languages, if `typeof foo; // "object"` then the param is _ByRef_, otherwise it is _ByVal_ – Paul S. Jan 06 '16 at 18:11
  • This has nothing to do with IIFEs; you might want to fix up the title of the question. –  Jan 06 '16 at 19:54

3 Answers3

0

When you work with primitive types (strings, numbers, etc) you are working with their value - however with more advanced data types like arrays and objects, you are working with their reference.

I'd recommend reading this chapter, it explains the differences in much greater detail:

http://docstore.mik.ua/orelly/webprog/jscript/ch11_02.htm

robertlyall
  • 216
  • 1
  • 5
0

When typeOf argument being passed is of type Array or Object then reference(pointer) of the value is passed not the value. Hence if reference is updated, it means value which is being held by reference is updated.

In case of the String, Number or Boolean values is being passed as an argument hence value of the variable which hold the earlier value remains the same.

Rayon
  • 36,219
  • 4
  • 49
  • 76
0

You are comparison is wrong. You are performing very different operations. In your object example you do

obj.c = 3

You are reading from obj and mutate the object. You are not creating a new object.

In your string example you do

str += 'aoeu'

Here you are writing to str, overriding its previous value with a new string value. That's a completely different operation than what you do with the object.

If you were doing the same operation with the object, you would get a similar result. The equivalent example would rather be something like

obj = {a: obj.a, b: obj.b, c: 4};

Assigning a new value to variable, never updates the value of another variable:

var foo = 42;
var bar = foo;
foo = 21;

bar will stay 21. It doesn't matter which value foo had at the beginning (number, string, object, ...).

However, there are two aspects of objects that are important to understand: Objects are

  • mutable
  • represented as reference

That means if you have an object and assign it to another variable:

var foo = {};
var bar = foo;

foo and bar now point to the same object in memory. Because objects are mutable, they can be changed "in place":

bar.x = 5;
console.log(foo.x);

Primitive values (anything that is not an object), are immutable. They cannot be changed in place:

var foo = "abc";
foo[0] = "x";
console.log(foo); // still "abc", not "xbc"

Because of immutability, "changing" a value implies creating a new value. That new value has to be "put" somewhere, which is often done be assigning it to the same variable:

foo = 'x' + foo.substring(1);

Or put in other words: Immutable values force us to assign new values to variables.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143