Scope in javascript acting weird

前端 未结 6 1318
悲哀的现实
悲哀的现实 2021-02-18 18:47

Object are passed with their reference in javascript. Meaning change in that object from any where should be reflected. In this case, the expected output was {} for console.log(

6条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-18 19:16

    Object are passed with their reference in javascript.

    No, they aren't. ECMAScript/JavaScript is strictly pass-by-value. (More precisely, call-by-sharing, which is a special case of pass-by-value.)

    What is happening here?

    This is just normal pass-by-value.

    Your confusion stems from the fact that you erroneously believe ECMAScript/JavaScript is pass-by-reference, when in fact it is not.

    ECMAScript uses pass-by-value, or more precisely, a special case of pass-by-value where the value being passed is always a pointer. This special case is also sometimes known as call-by-sharing, call-by-object-sharing or call-by-object.

    It's the same convention that is used by Java (for objects), C# (by default for reference types), Smalltalk, Python, Ruby and more or less every object-oriented language ever created.

    Note: some types (e.g. Numbers) are actually passed directly by value and not with an intermediary pointer. However, since those are immutable, there is no observable behavioral difference between pass-by-value and call-by-object-sharing in this case, so you can greatly simplify your mental model by simply treating everything as call-by-object-sharing. Just interpret these special cases as internal compiler optimizations that you don't need to worry about.

    Here's a simple example you can run to determine the argument passing convention of ECMAScript (or any other language, after you translate it):

    function isEcmascriptPassByValue(foo) {
      foo.push('More precisely, it is call-by-object-sharing!');
      foo = 'No, ECMAScript is pass-by-reference.';
      return;
    }
    
    var bar = ['Yes, of course, ECMAScript *is* pass-by-value!'];
    
    isEcmascriptPassByValue(bar);
    
    console.log(bar);
    // Yes, of course, ECMAScript *is* pass-by-value!,
    // More precisely, it is call-by-object-sharing!

    If you are familiar with C#, it is a very good way to understand the differences between pass-by-value and pass-by-reference for value types and reference types, because C# supports all 4 combinations: pass-by-value for value types ("traditional pass-by-value"), pass-by-value for reference types (call-by-sharing, call-by-object, call-by-object-sharing as in ECMAScript), pass-by-reference for reference types, and pass-by-reference for value types.

    (Actually, even if you don't know C#, this isn't too hard to follow.)

    // In C#, struct defines a value type, class defines a reference type
    struct MutableCell
    {
        public string value;
    }
    
    class Program
    {
        // the ref keyword means pass-by-reference, otherwise it's pass-by-value
        // You must explicitly request pass-by-reference both at the definition and the call
        static void IsCSharpPassByValue(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux)
        {
            foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.";
            foo = new string[] { "C# is not pass-by-reference." };
    
            bar.value = "For value types, it is *not* call-by-sharing.";
            bar = new MutableCell { value = "And also not pass-by-reference." };
    
            baz = "It also supports pass-by-reference if explicitly requested.";
    
            qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." };
        }
    
        static void Main(string[] args)
        {
            var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" };
    
            var corge = new MutableCell { value = "For value types it is pure pass-by-value." };
    
            var grault = "This string will vanish because of pass-by-reference.";
    
            var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." };
    
            // the first two are passed by value, the other two by reference
            IsCSharpPassByValue(quux, corge, ref grault, ref garply);
    
            Console.WriteLine(quux[0]);
            // More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.
    
            Console.WriteLine(corge.value);
            // For value types it is pure pass-by-value.
    
            Console.WriteLine(grault);
            // It also supports pass-by-reference if explicitly requested.
    
            Console.WriteLine(garply.value);
            // Pass-by-reference is supported for value types as well.
        }
    }
    

提交回复
热议问题