1

Why result is different in those two codes?

Here is c# code:

class Program
    {
        public static void update(string [] array)
        {
            string [] newArray = new string [2];
            newArray[0] = "myself";
            newArray[1] = "version2";
            array = newArray;

        }
        static void Main(string[] args)
        {
            string[] array = new string[2];
            array[0] = "myself";
            array[1] = "version1";
            Console.WriteLine("{0} {1}", array[0], array[1]);
            update(array);
            Console.WriteLine("{0} {1}", array[0], array[1]);
            Console.ReadLine();
        }
    }

Result is: myself version1 myself version1

Here is javascript code:

function update(arrray) {
                var newArray = [2];
                newArray[0] = "myself";
                newArray[1] = "version2";
                array = newArray;
            };

var array = ["myself", "version1"];
console.log(array);
update(array);
console.log(array);

Result is: myself version1 myself version2

I understand result from c# code, but I don't understand why javascript produces different one. Can someone explain?

bambi
  • 1,159
  • 2
  • 14
  • 31
  • javascript and c# are different language.Why do you want to know difference between them? It makes no sense to me. – Bhojendra Rauniyar Jul 15 '15 at 06:36
  • you have a typo in your javascript code. The parameter for update() is `arrray` and you're using `array` in code. – Peter Jul 15 '15 at 06:37
  • @Peter He isn't even trying to reassign the array in the C# example.. – xanatos Jul 15 '15 at 06:39
  • 2
    @BhojendraNepal I think it's a fair question to know the difference. That's how I always start learning a new programming language as well :-) – atlaste Jul 15 '15 at 06:39
  • 2
    @xanatos: Your edit **changing** `arrray` to `array` was incorrect. The typo is critical to the question. I've rolled it back. Please be very careful when changing anything but indentation in a question's code. – T.J. Crowder Jul 15 '15 at 06:54
  • @T.J.Crowder Yep... I was thinking of doing the same... But I do think you should re-edit it and add a comment, something like **THE CULPRIT IS HERE** – xanatos Jul 15 '15 at 06:55
  • @xanatos: No, I don't. The useful answers explain it. – T.J. Crowder Jul 15 '15 at 06:57
  • you have re-edited your javascript code in your question. – NiRUS Jul 15 '15 at 07:00

6 Answers6

3

The main issue is that you have a critical typo in the JavaScript version:

function update(arrray) {
// Here ----------^
    newArray = [2];
    newArray[0] = "myself";
    newArray[1] = "version2";
    array = newArray;
};

Your function argument's name is arrray (I guess you were feeling pirate-ish?), but you assign to array inside the function.

Your update is a closure over the context in which it's created, which has a variable called array, so you're assigning to that variable, which is why you see the content of that variable changing.

If you fixed your function argument name, you'd find that the result was the same as in your C# code:

function update(array) {
// Note fix ----^^^^^
  newArray = [2];
  newArray[0] = "myself";
  newArray[1] = "version2";
  array = newArray;
};

var array = ["myself", "version1"];
snippet.log(array); // myself,version1
update(array);
snippet.log(array); // myself,version1 (again)
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

You have a couple of other significant issues in your JavaScript code:

  1. You're falling prey to The Horror of Implicit Globals because you never declare your newArray variable in update. You've edited the question to add the var now.

  2. Your line initializing newArray creates an array with a single entry, the number 2, which you then immediately overwrite. You probably meant newArray = new Array(2), which would create an array with length = 2. But in JavaScript, you almost never want to use new Array. Just use newArray = []. Standard JavaScript arrays aren't really arrays at all, no need to predeclare their length.

  3. Function declarations like your declaration for update don't need a ; after them. It's harmless, but unnecessary.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

It works the same way in C# and in Javascript. So in your case, both programs (if corrected of some errors) won't do anything (see https://jsfiddle.net/0v7h3ssm/). You did some errors somewhere while testing.

In C#, if you want to reassign the array inside the function you can do

public static void update(ref string [] array)
{
    string [] newArray = new string [2];
    newArray[0] = "myself";
    newArray[1] = "version2";
    array = newArray;
}

In Javascript you could put the array inside another object.

function update(arraycontainer) {
    var newArray = [2];
    newArray[0] = "myself";
    newArray[1] = "version2";
    arraycontainer.obj = newArray;
};

var container = { obj: array };
update(container);
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • arrays are already passed by reference. no need to use ref keyword – M.kazem Akhgary Jul 15 '15 at 06:43
  • @M.kazemAkhgary He wants to reassign the array, not the array content. So he needs `ref`. If he is happy to keep the array of two elements and simply reassign its two elements, then there is no problem, and he doesn't need `ref` – xanatos Jul 15 '15 at 06:44
  • @xanatos I see you beat me to it. :-) Yes I also believe `by ref` is the correct literal translation here. – atlaste Jul 15 '15 at 06:45
  • My question is: why did even my javascript code reassigned array? – bambi Jul 15 '15 at 06:46
  • @bambi because Javascript passes it by reference implicitly. C# is more explicit about these kinds of things. – atlaste Jul 15 '15 at 06:46
  • @atlaste False. The C# is equivalent to the JS code. – xanatos Jul 15 '15 at 06:47
  • @bambi I don't know what you did in JS, but the code you posted doesn't do what you say... See https://jsfiddle.net/0v7h3ssm/ . It is **equivalent** to the C# code. – xanatos Jul 15 '15 at 06:47
  • @xanatos OK if what you mean with *equivalent* is that in both cases you pass a pointer to an object around and you change the pointer to a new data representation, we agree. That leaves the fact that arrays work totally different in both languages, that functions don't have a `this` pointer, that the passing mechanics work differently... and a ton of other things. – atlaste Jul 15 '15 at 06:52
  • @atlaste: JavaScript never passes by reference, implicitly or otherwise. JavaScript is a purely pass-by-value language. The value passed may be an object reference, but that's not pass-by-reference, which is a term of art with a specific meaning: Passing a reference to the **variable** in the calling context into a function/method. Nothing to do with object references. – T.J. Crowder Jul 15 '15 at 07:20
  • 1
    @bambi: *"My question is: why did even my javascript code reassigned array?"* Because of the typo in your function argument name, as Ahs N and I have both explained (although his/her answer doesn't actually point out the typo, so it would be easy not to understand it). – T.J. Crowder Jul 15 '15 at 07:27
2

This is because the variable array is declared outside the function update(arrray). This makes it a Global variable which can be accessed by any function from anywhere.

Inside your function, you created a new array newArray and then you overwrite the content of global array with these lines: array = newArray;

This causes the global variable array to get the values from newArray set in them.

Therefore when you print the new content to the console, you get the new values.

Ahs N
  • 8,233
  • 1
  • 28
  • 33
  • 1
    This seems to be the only answer that answers the question: "*… I don't understand why javascript produces different one. Can someone explain?*". – RobG Jul 15 '15 at 06:49
1

So first off, there are a ton of differences between Javascript and C#. I'm not going into details here, it would simply take too long.

A few things that are noteworthy:

You can pass the array by reference, that'll solve the immediate problem. You should however learn what 'by reference' means before you try that.

public static void update(ref string [] array)
{
    string [] newArray = new string [2];
    newArray[0] = "myself";
    newArray[1] = "version2";
    array = newArray;
}

Also:

  • Arrays in Javascript are more like 'Dictionary' objects in C#. Arrays in C# are basically just a chunk of sequential memory. It's quite different, so I think it's a good idea to learn that difference.

  • Scope is very different. You might want to learn everything you can get your hands on about scope in C#. That's basically the issue you're having here as well. Once you understand that, you probably also won't pass it by ref anymore.


It's funny, some people here have approached this question from a C# perspective while others have approached it from JavaScript.

To complete the definitions:

  • Pass by value means that you take the bytes of the thing, and pass it to a function, whatever that 'thing' may be.
  • Pass by reference means that you take the memory address of the bytes of the thing, and pass that to a function.

If you call a function, assume that the things you pass to the function are copied. In other words, you either copy the address of the value (pass by reference) or the value itself (pass by value).

First off, how it works in Javascript:

As @T.J.Crowder points out, technically, all passes in Javascript are by-value, although I prefer the term 'call by sharing'. A value here can be a pointer to an object, and if the object supports it, you can change the object. An array is an object that allows you to change the contents of the array.

There are a few good examples on how this works exactly here: Javascript by-reference or by-value

Next, how it works in C#

In C#, you can pass objects by value or by reference. If you were to pass a Dictionary (which is IMHO the best translation for an array in Javascript), you can simply modify the contents:

public static void update(Dictionary<int, string> array)
{
    array[0] = "myself";
    array[1] = "version2";
}

The reason this works is because a Dictionary is a reference type, which means the pointer to the array is passed to the update function.

However, because the pointer to the array is passed 'by-value' to the update method, this also means the pointer itself is immutable from the caller's perspective. You can attempt to overwrite 'array' in the update method, but updates will be lost as soon as the update method exists because the pointer that was passed is not changed in the method that's calling update.

Confusing? Let's make it simple:

public static void update(Dictionary<int, string> array)
{
    Debugger.Break(); // look at the contents of array here

    array = new Dictionary<int, string>();
    array[0] = "myself";
    array[1] = "version2";

    Debugger.Break(); // look at the contents of array here
}

public static void Main()
{
    var foo = Dictionary<int, string>();
    foo[0] = "aap";

    update(foo);

    Debugger.Break(); // look at the contents of foo here
}

If you want to overwrite the pointer in the caller method, you need to pass it 'by reference', which basically means you pass the address to the pointer. The compiler automatically dereferences the address and updates the underlying value (the 'real' object reference) if you assign it:

public static void update(ref Dictionary<int, string> array)
{
    auto myArray2 = new Dictionary<int, string>();
    myArray2[0] = "myself";
    myArray2[1] = "version2";

    array = myArray2;
}
Community
  • 1
  • 1
atlaste
  • 30,418
  • 3
  • 57
  • 87
  • @T.J.Crowder I've added some more details. I originally understood the OP wanted to fix the C# code :-) Either way, this is what you mean? – atlaste Jul 15 '15 at 09:21
1

JavaScript is pass by pointer. When you assign array you are overwriting the pointer to the array passed into the function

function update(array) {
// array = pointer to the argument
    newArray = [2];
    newArray[0] = "myself";
    newArray[1] = "version2";
// this overrides the pointer and point's it to the new array (it does not modify the existing array)
    array = newArray;

};

Try this:

function update(array) {
    // clear the old array
    array.length = 0;

   // set some new values on the array
    array[0] = 'myself';
    array[1] = 'version2';
};
alexreardon
  • 606
  • 5
  • 12
1

As per the C#

The code is executed in closure. Observe the variable newArray in C# its been initialized inside a method. So It becomes a local variable inside the method. Its not accessible in class level.

See the inline comments for explanation:

class Program
    {
        public static void update(string [] array)
        {
            string [] newArray = new string [2]; //Local variable
            newArray[0] = "myself";
            newArray[1] = "version2";
        }
        static void Main(string[] args)
        {
            string[] array = new string[2]; //Local variable again
            array[0] = "myself";
            array[1] = "version1";
            Console.WriteLine("{0} {1}", array[0], array[1]);
            update(array);
            Console.WriteLine("{0} {1}", array[0], array[1]);
            Console.ReadLine();
        }
    }

In JavaScript the scenario varies. If you dont use var before declaring a variable inside a function it is automatically becomes accessible in global space(Window is a global variable in Javascript). See the inline comments.

function update(arrray) {
                newArray = [2]; //Automatically attached to **Window**
                newArray[0] = "myself"; //Again becomes global
                newArray[1] = "version2"; //Again becomes global
                array = newArray; //Already global
            };

var array = ["myself", "version1"]; //Scope is Global hece its equivalent to window.array
console.log(array);
update(array); //This affects window.array which is global space
console.log(array);

To achieve the output same as your c# code see the corrected version of your JS code

function update(array) {
    var newArray = [];
    newArray[0] = "myself";
    newArray[1] = "version2";
    array = newArray;
};

function exec(){
    var array = ["myself", "version1"];
    console.log(array);
    update(array);
    console.log(array);
}

exec();

Explanation: In the above code i am localizing the variable array by wrapping it inside the function. So the variable becomes local only to the function and not to the global space ie window.array variable is not created as discussed earlier.

To avoid undeclared variables in ECMA script 5 introduced "use strict" directive which tells the JavaScript interpreter to throw an error if var keyword is not used for initializing variables.

NiRUS
  • 3,901
  • 2
  • 24
  • 50