Home > Web Front-end > JS Tutorial > In-depth understanding of JavaScript series (19): Detailed explanation of evaluation strategy_Basic knowledge

In-depth understanding of JavaScript series (19): Detailed explanation of evaluation strategy_Basic knowledge

WBOY
Release: 2016-05-16 16:11:09
Original
963 people have browsed it

Introduction

In this chapter, we will explain the strategy of passing parameters to functions in ECMAScript.

In computer science, this strategy is generally called "evaluation strategy" (Uncle's note: Some people say it is translated as evaluation strategy, and some people translate it as assignment strategy. Looking at the following content, I think it is called assignment Strategy is more appropriate, anyway, the title should be written as an evaluation strategy that is easy for everyone to understand), such as setting rules for evaluating or calculating expressions in a programming language. The strategy of passing arguments to functions is a special case.

http://dmitrysoshnikov.com/ecmascript/chapter-8-evaluation-strategy/
The reason for writing this article is because someone on the forum asked for an accurate explanation of some parameter passing strategies. We have given the corresponding definitions here, hoping to be helpful to everyone.

Many programmers are convinced that in JavaScript (and even some other languages), objects are passed by reference, while primitive value types are passed by value. In addition, many articles mention this "fact", but many people Do you really understand this terminology, and how much is correct? We will explain it one by one in this article.

General Theory

It should be noted that there are generally two assignment strategies in assignment theory: strict-meaning that the parameters are calculated before entering the program; non-strict-meaning that the parameters are calculated according to the calculation requirements. Computation (that is, equivalent to delayed computation).

Then, here we consider the basic function parameter passing strategy, which is very important from the ECMAScript starting point. The first thing to note is that ECMAScript (and even other languages ​​such as C, JAVA, Python and Ruby) uses a strict parameter passing strategy.

In addition, the calculation order of passed parameters is also very important - in ECMAScript it is left to right, and the reflection order (from right) implemented in other languages ​​​​can also be used.

The strict parameter passing strategy is also divided into several sub-strategies, the most important of which we discuss in detail in this chapter.

Not all strategies discussed below are used in ECMAScript, so when discussing the specific behavior of these strategies, we use pseudocode to demonstrate them.

Pass by value

Pass by value, as many developers know very well. The value of a parameter is a copy of the value of the object passed by the caller. Changing the value of the parameter inside the function will not affect the external object (the parameter is in External value), generally speaking, new memory is reallocated (we do not pay attention to how the allocated memory is implemented - it is also a stack or dynamic memory allocation), the value of the new memory block is a copy of the external object, and Its value is used inside the function.

Copy code The code is as follows:

bar = 10

procedure foo(barArg):
barArg = 20;
end

foo(bar)

// Changing the value inside foo will not affect the value of internal bar
print(bar) // 10

However, if the parameter of the function is not a primitive value but a complex structure object, it will cause a big performance problem. C has this problem. When the structure is passed into the function as a value - it is a complete copy.

Let’s give a general example and use the following assignment strategy to test it. Think about a function that accepts 2 parameters. The first parameter is the value of the object, and the second parameter is a Boolean mark. Marks whether the passed object is completely modified (reassigned a value to the object), or only some properties of the object are modified.

Copy code The code is as follows:

// Note: The following are pseudocode, not JS implementation
bar = {
x: 10,
y: 20
}

procedure foo(barArg, isFullChange):

if isFullChange:
barArg = {z: 1, q: 2}
exit
end

barArg.x = 100
barArg.y = 200

end

foo(bar)

// Pass by value, external objects are not changed
print(bar) // {x: 10, y: 20}

// Completely change the object (assign new value)
foo(bar, true)

//No change either
print(bar) // {x: 10, y: 20}, instead of {z: 1, q: 2}

Pass by reference

Another well-known pass-by-reference method receives not a copy of the value, but an implicit reference to the object, such as the direct external reference address of the object. Any changes to the parameters inside the function will affect the value of the object outside the function, because both refer to the same object, that is to say: at this time, the parameter is equivalent to an alias of the external object.

Pseudo code:

Copy code The code is as follows:

procedure foo(barArg, isFullChange):

if isFullChange:
barArg = {z: 1, q: 2}
exit
end

barArg.x = 100
barArg.y = 200

end

//Use the same object as above
bar = {
x: 10,
y: 20
}

// The result of calling by reference is as follows:
foo(bar)

// The object's attribute value has been changed
print(bar) // {x: 100, y: 200}

// Reassigning new values ​​also affects the object
foo(bar, true)

// The object is now a new object
print(bar) // {z: 1, q: 2}

This strategy allows for more efficient delivery of complex objects, such as large structural objects with large batches of properties.

Call by sharing
Everyone knows the above two strategies, but the strategy I want to talk about here may not be well understood by everyone (actually it is an academic strategy). However, we will soon see that this is exactly the strategy in which it plays a key role in parameter passing strategies in ECMAScript.

There are also some synonyms for this strategy: "pass by object" or "pass by object sharing".

This strategy was proposed by Barbara Liskov in 1974 for the CLU programming language.

The key point of this strategy is: the function receives a copy (copy) of the object, and the reference copy is associated with the formal parameters and their values.

We cannot call the reference appearing here "pass by reference" because the parameter received by the function is not a direct object alias, but a copy of the reference address.

The most important difference is: reassigning a new value to the parameter inside the function will not affect the external object (similar to the case of passing by reference in the above example), but because the parameter is an address copy, it cannot be accessed outside and inside. The same object is accessed (for example, the external object is not a complete copy like passing by value), and changing the attribute value of the parameter object will affect the external object.

Copy code The code is as follows:

procedure foo(barArg, isFullChange):

if isFullChange:
barArg = {z: 1, q: 2}
exit
end

barArg.x = 100
barArg.y = 200

end

//Still use this object structure
bar = {
x: 10,
y: 20
}

// Passing by contribution will affect the object
foo(bar)

// The properties of the object have been modified
print(bar) // {x: 100, y: 200}

// Reassignment has no effect
foo(bar, true)

// Still the above value
print(bar) // {x: 100, y: 200}


This processing assumes that objects are used in most languages, rather than primitive values.

Pass by share is a special case of pass by value

The pass-by-share strategy is used in many languages: Java, ECMAScript, Python, Ruby, Visual Basic, etc. Furthermore, the Python community has adopted this terminology, and other languages ​​may also use this terminology, as other names tend to cause confusion. In most cases, such as in Java, ECMAScript or Visual Basic, this strategy is also called pass-by-value - meaning: special value-reference copy.

On the one hand, it is like this - the parameter passed to the function is just a name of the bound value (reference address) and will not affect the external object.

On the other hand, these terms are really considered wrong without digging deeper, as many forums talk about how to pass objects to JavaScript functions).

General theory does say that it is passed by value: but at this time the value is what we call an address copy (copy), so it does not break the rules.

In Ruby, this strategy is called pass by reference. Again: it's not passed as a copy of the big structure (i.e. not passed by value), and on the other hand, we're not dealing with a reference to the original object, and can't modify it; therefore, this cross-term concept may cause more problems. confusion.

In theory, there is no special case of passing by reference like the special case of passing by value.

But it is still necessary to understand that in the above-mentioned technologies (Java, ECMAScript, Python, Ruby, other), in fact - the strategy they use is pass-by-share.

Press Share & Pointer

For С/С, this strategy is ideologically the same as pass-by-pointer-by-value, but with one important difference - this strategy can dereference the pointer as well as completely mutate the object. But in general, a value (address) pointer is allocated to a new memory block (that is, the previously referenced memory block remains unchanged); changing the object attributes through the pointer will affect the Adon external object.

So, and the pointer category, we can obviously see that this is passed by address value. In this case, pass-by-share is just "syntactic sugar" that behaves like a pointer assignment (but cannot dereference), or modifies a property like a reference (no dereference operation required). Sometimes, it can be named " Safe pointers".

However, С/С also has special syntax sugar when referencing object properties without explicit pointer dereference:

Copy code The code is as follows:

obj->x instead of (*obj).x

This ideology is most closely associated with C and can be seen in the implementation of "smart pointers", for example, in boost::shared_ptr, which overloads the assignment operator and copy constructor and also uses the object's reference counter. , delete objects through GC. This data type even has a similar name - shared_ptr.

ECMAScript implementation

Now we know the strategy of passing objects as parameters in ECMAScript - passing by sharing: modifying the properties of the parameter will affect the outside, but reassigning will not affect the external object. However, as we mentioned above, ECMAScript developers among them generally call it: pass by value, except that the value is a copy of the reference address.

JavaScript inventor Brendan Ash also wrote: What is passed is a copy of the reference (copy of the address). So what everyone in the forum once said about passing by value is also correct under this explanation.

More precisely, this behavior can be understood as a simple assignment. We can see that inside it is a completely different object, but it refers to the same value - that is, a copy of the address.

ECMAScript code:

Copy code The code is as follows:

var foo = {x: 10, y: 20};
var bar = foo;

alert(bar === foo); // true

bar.x = 100;
bar.y = 200;

alert([foo.x, foo.y]); // [100, 200]

That is, two identifiers (name bindings) are bound to the same object in memory and share this object:

foo value: addr(0xFF) => {x: 100, y: 200} (address 0xFF) <= bar value: addr(0xFF)
With reassignment, the binding is to a new object identifier (new address) without affecting previously bound objects:

Copy code The code is as follows:

bar = {z: 1, q: 2};

alert([foo.x, foo.y]); // [100, 200] – unchanged
alert([bar.z, bar.q]); // [1, 2] – but now referencing a new object

That is, now foo and bar have different values ​​and different addresses:
Copy code The code is as follows:

foo value: addr(0xFF) => {x: 100, y: 200} (address 0xFF)
bar value: addr(0xFA) => {z: 1, q: 2} (address 0xFA)

Let me emphasize again, the value of the object mentioned here is the address (address), not the object structure itself. Assigning a variable to another variable is a reference to the assigned value. Therefore both variables refer to the same memory address. The next assignment is a new address, which resolves the address binding to the old object and then binds it to the address of the new object. This is the most important difference from passing by reference.

In addition, if we only consider the abstraction level provided by the ECMA-262 standard, all we see in the algorithm is the concept of "value", and the "value" passed by the implementation (can be a primitive value or an object), But according to our definition above, it can also be called "pass by value" because the reference address is also a value.

However, in order to avoid misunderstandings (why the properties of external objects can be changed inside the function), there are still implementation-level details that need to be considered here - what we see as passing by sharing, or in other words - passing by safe pointer , and it is impossible for a safe pointer to dereference and change the object, but it can modify the attribute value of the object.

Term Version

Let’s define the term version of this strategy in ECMAScript.

It can be called "passing by value" - the value mentioned here is a special case, that is, the value is an address copy. From this level we can say: All objects in ECMAScript except exceptions are passed by value. This is actually the abstract level of ECMAScript.

Or in this case, it is specifically called "pass by share". Through this, you can see the difference between traditional pass by value and pass by reference. This situation can be divided into 2 situations: 1 : Original values ​​are passed by value; 2: Objects are passed by sharing.

The sentence "Converting an object to a function by reference type" has nothing to do with ECMAScript, and it is wrong.

Conclusion

I hope this article helps to understand more details on the big picture and its implementation in ECMAScript. As always, if you have any questions, feel free to discuss them.

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template