Javascript Jems - First class functions |
Written by Ian Elliot | ||||
Tuesday, 10 August 2010 | ||||
Page 2 of 3
ArgumentsThe rule for function arguments is that they are always passed by value - there are no exceptions to this rule even if there appears to be. The reason for the slight confusion is the way pass by value looks with different types of variable. Some variables are value types, like simple numbers, and some are reference types, like objects, and this gives the appearance of pass-by-value and reference semantics. What this means is that if you pass a numeric or string value then within the function the parameter is a copy of the value. Then any changes made to the parameter in the function don’t change the variable in the rest of the program. However, if you pass an object then the parameter is again a copy of the value but in this case it’s a reference to an object and this is the same object referenced in the rest of the program. Hence any changes you make to the parameter don’t affect anything in the rest of the program but any changes you make to the object that the parameter references do make permanent changes. This is exactly how it is in language such as C# and VB so it’s worth getting absolutely clear. For example if we define: function myfunc1(a) Then after: var b = 1 b is still 1 despite the function’s “attempt” to change it to 2. However, if the function is redefined to be: function myfunc1(a) that is we are changing the x property of an object, then following: var b = { x: 1, y: 2 }; the x property of b, which was initialised to 1, is changed to 2. However, if we change the parameter (not a property of the object it references) then again the function has no effect on the rest of the program: function myfunc1(a) With this definition of the function b.x is unchanged when the function returns. To be clear, in the function a initially references the same object as b, then it is set to reference a new object and finally it is destroyed when the function ends leaving b referencing the original object. So JavaScript always passes by value but the effect changes according to the type of variable passed. Pass a value by referenceThere seems to be no way to pass a primitive value such as a number by reference. You can try wrapping it as an object as in: var b =new Number(2); but the value of the new Number object, i.e. 2, is an internal property that you can’t access and this stops you using primitive types as if they were objects in creative ways. The closest approach to passing a primitive value by reference is to create a new object type with a new value property that is accessible. This isn’t particular practical but it is a good example of object-oriented JavaScript in action. First we need the new object type and so we need a constructor function:
refNumber = function(value) The first line creates a new Number object with its internal value set to the specified value. We then add a value property which is also used to store the value. Notice that we explicitly return a reference to the new object that has been created. With the new constructor we can now create new refNumber objects: var b = new refNumber(1); At this point b behaves like a standard number, set to 1, within expressions but notice that if you assign a new value to it then it simply reverts to being a standard Number object. If a function wants to change the value of this refNumber object then it has to explicitly change its value property: function myfunc1(a) If you now call the function using b myfunc1(b); then the value of b will have been changed to 2. Of course the internal value will not have been changed and if you use b in an expression it will still be set to 1. The only solution is to “normalise” the internal value to be the same as the value property but this can only be done by creating a new refNumber object: var b = new refNumber(1); Now you will discover that the internal value of b is also set to 2. This isn’t entirely satisfactory as you have to remember to use the value property within the function and you have to remember to normalise the variable after its use. Even so it’s impressive that you can get this close to automatic pass by reference using nothing but the Javascript language. <ASIN:0596517742> <ASIN:0321572602> <ASIN:0596806752> <ASIN:1590597273> <ASIN:059680279X> <ASIN:0596805527> |
||||
Last Updated ( Thursday, 19 August 2010 ) |