DEV Community

Discussion on: A Collection of JavaScript Tips Based on Common Areas of Confusion or Misunderstanding

Collapse
 
pentacular profile image
pentacular

Since this is about common areas of confusion ... :)

whether that primitive is assigned by reference or by value.

Assignment in Javascript is always by value, never by reference.

That is, a = b assigns the value produced by evaluating b to a.

This is important, since if it b were assigned a by reference, it would refer to the value of a and given a++, a === b would remain true.

What you could say is that an object evaluates to a value that holds a reference to the object, but that's kind of long winded.

And in Javascript a reference is a resolved name or property binding.
e.g., in delete a.b; a.b produces a reference type.

I think it's simpler to say that evaluation in Javascript produces the value, rather than a copy of the value, and this is true of both primitives and objects.

Let's not bring assignment by reference into the picture to confuse things further. :)

Closure is an important javascript pattern to give private access to a variable.

Closures do not give private access to variables.

They allow the variable to be in multiple scopes, and to persist for the extent of those scopes.

// Nothing private about a.
let a = 0;

const foo () => {
  // Have a closure over a, foo.
  foo(() => a);
  // Have a closure over a, bar.
  bar(() => a);
};
Enter fullscreen mode Exit fullscreen mode

Rather, closures provide a mechanism which allows delegation of access to a variable via a function call.

Variables are pointing to references to the objects in memory, not the objects themselves!

Variables are pointers now?
And they point at references?

Why not just say that the value of a variable is the object itself, like the ecmascript standard does?

So, when you compare two object values, you're seeing if they're the value of the same object.

The critical point here is that the value of an object is the object itself, not a copy of the object.

And so, saying a = b; assigns the value of b to a, which is the object itself, and so a.c accesses the same property as b.c, while a and b are independent variables which currently have the same value.

Identity Operator (===) vs. Equality Operator (==)

Let's start by saying that === is the Strict Equality Comparison, and == is the Abstract Equality Comparison, and neither of them are an identity operator.

Let's take a look at the Strict Equality Comparison

1. If Type(x) is different from Type(y), return false.
2. If Type(x) is Number or BigInt, then
  a. Return ! Type(x)::equal(x, y).
3. Return ! SameValueNonNumeric(x, y).
Enter fullscreen mode Exit fullscreen mode

Case 2.a is the important one.

Let's take a look at Number::equal

1. If x is NaN, return false.
2. If y is NaN, return false.
3. If x is the same Number value as y, return true.
4. If x is +0 and y is -0, return true.
5. If x is -0 and y is +0, return true.
6. Return false
Enter fullscreen mode Exit fullscreen mode

And there's where it falls short of being an identity operator.

Did you know both were options? i++ returns i and then increments it whereas ++i increments i and then returns it.

This introduces a confusing model of time into evaluation.

i++ returns i, then increments? But a return is a transfer of control ... what's going on here ?!?

Instead we can say that both i++ and ++i increment i.

The difference is that i++ evaluates to the old value of i, and ++i evaluates to the new value of it.

Collapse
 
mrjjwright profile image
John Wright

that was really helpful

Collapse
 
pentacular profile image
pentacular

Glad to be of help :)

Thread Thread
 
z2lai profile image
z2lai • Edited

Woah, that was a lot of elaboration, but in the end it all made sense. Some of the further elaboration did confused me a little though.
For example, you say:

The critical point here is that the value of an object is the object itself, not a copy of the object.

and before that you say:

What you could say is that an object evaluates to a value that holds a reference to the object

So combining these two thoughts: the value of an object is the object itself, which evaluates to a value that holds a reference to the object.
Conceptually, it makes sense to me - the value of an object evaluates to a value that holds a reference to the object - which evaluates to a value that holds a reference to the object - which... But then again, the latter quote forms an infinite loop of logic with itself! What's the term for that...

Personally, I find explaining code in English to be extremely hard because I tend to get into infinite loops of logic.

Thread Thread
 
pentacular profile image
pentacular

I think that you're trying to impose the understanding of JS semantics on top of an assumed implementation model.

Let's imagine that there's a kind of value called an 'object type value'.

And having this 'object type value' lets you access the same set of 'object properties'.

Now, if I pass you my 'object type value' by value, you have an equivalent 'object type value' which lets you access the same 'object properties' that I access using my copy of the 'object type value'.

And the two 'object type values' will compare equal.

And so we can say that these two 'object type values' are the same object.

But actually, the 'object' is in the relationships that the 'object type value' makes available.

We don't need to talk about references or pointers or anything else -- the above is sufficient.

Thread Thread
 
z2lai profile image
z2lai • Edited

Hey, thanks for the reply. So what you're saying is that the implementation of 'object type values' being just reference values (pointers) to the memory location containing the object is an assumption rather than a fact? If that's the case, what is the actual implementation? This would be a huge revelation as most educational material online explain the implementation this way.

I'm trying really hard to understand your high level explanation of the implementation but I'm honestly confused because of how high level it is and the new terminology used. For example, you say "when I pass you my 'object type value' by value", that doesn't equate to some code that I can visualize, which forces me to infer that you mean when you assign your 'object type value' to a new variable, but my inference might be wrong. Then you say, "the 'object' is in the relationships". I've never heard of this relationship term used in Javascript before, so I have no idea what that sentence means. Please correct me if I'm wrong and if relationships is an actual term used in the implementation model instead of an abstract concept.

It could just be me though, since I understand explanations much easier from a low level rather than abstract explanations. Ultimately, I think I already understand 'how it works' at a high level and it seems to be the same as what you're explaining (regardless of whether we're using the term relationship or reference). However, I'm inclined to understand how things work under the hood (coming from a math and physics background), which why these high level explanations don't work well with me.

Thread Thread
 
pentacular profile image
pentacular

Let us consider a simple program.

const a = { size: 10 };
const b = a;
const aSize = a.size;
const bSize = b.size;

Now imagine an implementation of Javascript in Javascript, where objects are represented as numbers, and we have Get and Set methods.

We might represent the above like so.

const a = 0;
Set(a, "size", 10);
const b = a;
const aSize = Get(a, "size");
const bSize = Get(b, "size");

The value of the object is its identity, which enables us to access the object's properties.

Sharing this identity allows others to access the same properties.

So we don't need to talk about pointers or references -- we just need the object value and some way to use that to access the object's properties.

There's nothing special about numbers for object values in the example, it might as well have been strings, or dates, or anything that can provide an identity.

As for "under the hood", there isn't any -- unless you're assuming a particular implementation, in which case you're no-longer reasoning about the language, but some particular implementation of it.

If you come from a math background it should be natural to understand things in terms of relationships, rather than mechanics.