Author: Michael Hunter

I'm a software engineer by profession, working in San Diego doing mainly server software in C#, embedded software in C and C++. I also do web in ASP.NET, HTML and Javascript; database development in MS SQL, and electronics design and debugging. I studied Electrical and Information engineering in university, and have a passion for learning new things so I've done some online courses in a variety areas, as well as just reading and doing my own research. My particular areas of interest are in computer languages, machine learning, signal processing and information theory.
Global To-String
JavaScript Corners - Part 9

Global To-String
JavaScript Corners - Part 9

(This is Part 9 in my series on JavaScript corner cases).

Here’s another one.

In JavaScript, global variables are properties of the global object. By default, the global object is like any other, and inherits from the Object.prototype  object.  Object.prototype comes with a number of its own properties, such as the  toString method. So, that means that toString is also a global variable1.

Everything seems expected, except the last line, which might seem a little confusing. The toString() call is clearly invoking a function using a reference to that function, where the base of the reference is the global object, right? (Take a look at my posts on references). So surely  toString() and  global.toString() mean the same thing?

Wrong.

There’s a subtlety here. The unqualified  toString reference actually has a base value2 that is the global environment, which “knows about” the global object, but is not exactly the global object. The base object for the global environment is actually always the value  undefined. See here in the spec. This is why it prints "[object Undefined]" .

 


  1. To qualify as a global variable, there is actually an additional criterion. The property of the global object must not be listed in the set of unscopables on the global object. In this case, toString is not listed as an unscopable, since it was introduced into JavaScript before the existence of the unscopables feature, and for backwards compatibility it remains that way. 

  2. Recall that a reference has two components: the thing being referred on, and the name of the thing being referred to. For example, referring to the property named x on the object obj, in the case of obj.x 

JavaScript Corners – Part 9
Node.js With-Statement Bug

JavaScript Corners – Part 9
Node.js With-Statement Bug

What does the following evil code print?

If you’re not sure, don’t worry — neither are current JavaScript engines. Firefox prints “after”, while Edge, IE, and Node.js print “before” (node v7.9.0). I believe that Firefox is correct in this case.

The tricky statement is obviously the following one, which sets a property on an object in the same statement that deletes the property:

(Side note: if you’re not very familiar with JavaScript, the relevant language features that are being used here are the delete operator, comma operator, and the good ol’ evil with statement).

What we expect to happen

The statement  var x introduces a new variable at the script scope1.

The { x } expression creates a new object with a single property2  x, where the value of x  is copied from the variable  x in the outer scope, so it has the initial value of 'before'.

The with  statement brings the properties of the object obj into scope in a new lexical environment.

The statement x = (delete x, 'after') should perform the following steps:

  1. Evaluate the left hand side
  2. Evaluate the right hand side
  3. Assign the value from the right hand result, to the reference created when evaluating the left hand side

When the left hand side is evaluated, the property x will be found in object obj. The base value of the reference is the object, not the script variable scope.

The right hand side evaluates to 'after', but in the process it deletes the property x  from obj. However, the reference on the left hand side should still refer to “the property named 'x' on the object obj”, even though the property with that name is now deleted.

When the assignment happens, it should create a new property named 'x' on object obj, with value 'after'. The variable x in the outer scope should be left unaffected.

In this case, I think Node.js gets the wrong answer.


  1. Theoretically, the script scope is the global scope. But in Node.js, scripts are wrapped in a module wrapper that changes the behavior of global vars. This doesn’t affect the outcome of this experiment though 

  2. Bonus fact. Object literals inherit from the global intrinsic object Object.prototype, which has other properties on it, such as toString. So when I say that it has a single property, it would be more accurate to instead say that it has a single own property 

C++ vs JS
Binary Type Coupling

C++ vs JS
Binary Type Coupling

I was chatting to some of my colleagues at work recently about the potential benefits of a JavaScript compiler vs a C compiler, when targeting an embedded MCU. A concern that came up multiple times regarding different features, is

…but you can already do that in C, so how is JS better?

This is a good point. If you’re given a problem, you can solve it in JS, or you can solve it in C (or C++). Is JavaScript really any better? Of course, you know my answer, which is probably pretty biased. But let’s dig into a few of the details.

Firstly, let’s put aside the question of performance for a moment. I argue that JS is going to yield a more performant program1, while I’m sure that most C programmers will argue that C will perform better. Probably both are right, under different circumstances. Let’s just side step this issue for the moment.

There is at least one very significant reason why I think JS has a lot more to offer than C or C++, and that’s the ability to write reusable code. This is the gateway feature that opens the door to a 10x improvement in productivity, because it means that you can leverage highly customizable libraries to do most of the heavy lifting, rather writing the code yourself. Yes, in C and C++ you can use third party libraries. But in JS you can do it an order of magnitude faster. There are many, many times, where it’s taken me literally less than 5 minutes to go from “I wonder if there’s a library that already does this”, to using the library and moving on to the next task.

The same cannot be said for any third party C or C++ library or code file that I’ve ever used, which typically take days or weeks of integration work, reading documentation, figuring out why it doesn’t compile2, and then debugging cryptic issues.

So why is this the case? Is it the package managers? Is it the community? Is it the language?

I’m guessing it’s multiple reasons, but I’m going to focus on one in particular in this post: binary coupling (at least that’s what I’m calling it).

An Example: a Sum Function

Let’s take a dummy example. Consider a function that adds together an collection of numbers (sound familiar?). In JavaScript, you can be certain it will almost definitely have a signature like this:

We can use TypeScript to make things even more unambiguous, although this doesn’t change the meaning of the code:

This function logically takes a collection of numbers. In JS, collections of this nature are represented as arrays. The output is the sum, which is obviously also a number.

What might this look like in C or C++? Here are some options:

Forgive me if I have some or all of these wrong. In my life, I’ve programmed much more in C++ than in JavaScript, but C++ always remains a little bit too complicated for me to remember all the subtleties.

What’s the difference between all of these options? In my mind, they are all logically the same thing. They represent a function to which you pass an “array” of numbers, and it give you the result.

The difference comes mainly down to how a client interacts with these functions at a binary level. What calling convention is used? How is the array represented in memory? What parameters or aspects of the function are available at compile time vs runtime?

If sum was a third party library, which of these forms would it take?

We have at least one good answer to this question, since the functionality is already part of the STL in C++. It takes the following form:

There’s nothing surprising about this. Since we’re talking about the standard template library, you expect this to be a function template. It’s a fairly generic solution, but certainly it won’t suit everyone. Because it’s a template, you can’t take the pointer of it, you can’t pass it around as an argument to non-template code, you can’t export it directly as a library function from an object file, etc. For example, try to translate the following JavaScript code into C++:

The useSum and arr value might or might not be available at compile time — a reusable piece of code shouldn’t assume one or the other.

How C++ Usually Solves This

The solution to this in C++ is normally to shunt everything to runtime when you need reusability. As a case in point, take a look at the GPIO methods that the mbed library provides. To set a single bit that represents a GPIO pin, you would use a function with the following signature:

This makes for fairly reusable code. But it comes at a cost. It invokes a function call3, using a runtime value. The function then needs to use indirect accesses and masks to figure out what bit to set, internally using a structure that looks like this:

The absolute cost here is a low – a function call is not a big deal, masking and indirection are quick, and passing an integer argument at runtime is not a big deal. But the relative cost is high — if value and the specific port happened to be known at compile time, this whole thing could have been one machine instruction. Now it has to be many more, and extra memory overhead.

But surely in JavaScript this is even worse? Isn’t everything at runtime in JavaScript?

I would argue “no”. In JavaScript you don’t specify what gets done at compile time vs runtime — you leave it up to the JavaScript engine to decide. This is why I use the term “binary coupling”. In C++, your code is coupled to the binary representation of the resulting machine code — you are forced to make certain decisions, and those decisions force the C++ compiler to use certain representations. This makes C++ a glorified assembly language — it’s a way for you to write machine code in a somewhat abstracted way.

While in JavaScript, you don’t write machine code. You specify the behavior of the program in unambiguous terms, and leave it up to the engine or compiler to implement the specification in terms of machine code.

You get a small taste of this in C++ with micro-optimizations and inlining. You write a function, and in some circumstances the compiler is free to chose not to represent that as an actuall CALL instruction in the output binary. This is an example that breaks the usual binary coupling, since the code does not dictate the binary interface. But this kind of behavior is necessarily very limited in C++.

The discussion here is not primarily about performance, it’s about reusuability. What I’m demonstrating is that in C++, it’s impossible to have a library API that doesn’t also dictate the binary ABI that is used to access that library. As a result you’re much less likely to find an existing library that serves your specific purposes, since you need to match not only the logical interface, but the binary interface as well (and the type interface, which is another story).


  1. Not referring to interpreted or JIT-compiled JavaScript of today, but a hypothetical bare-metal compiler 

  2. Did you leave out a macro configuration flag somewhere? did you use the right make file for your platform? are the include files out of date? were you supposed to use the .dll files, or the .o files, or the .a files? the instructions are for GCC, how do I do this in VC++? the instructions are for version 1.34 but only version 1.32b is ported to my system, and for some reason the make file doesn’t run 

  3. The class itself is a small inline wrapper around the HAL, but the HAL is implemented as separate object files 

JavaScript Corners – Part 8
References (Continued)

JavaScript Corners – Part 8
References (Continued)

Given an object o  with a member function f  that prints out what the this value is:

We know what the following prints:

And we know what the following prints1:

I always thought that the difference came down to the fact that o.f()  is actually invoking a different operator — something like a “member call operator”.

However, what do you think the following prints?

My guess, up until today, would have been that this prints “global”, since with the parentheses, this is no longer invoking the member call operator, but is instead invoking the call operator.

But I was wrong. There is no such thing as a “member call operator”. Rather, the “call” operator just behaves differently depending on whether the target of the call is a value or a reference2.

So this actually prints “o”.

But hang on. Why didn’t the parentheses coerce o.f to a value?

One might have expected the parentheses to automatically dereference  o.f, something like the following examples that use the logical OR and comma operators to coerce the target to a value instead of a reference:

Indeed, this could have been the case for bare parentheses as well, but the language designers chose not to do it that way, so that the  delete and  typeof operators still work when extraneous parentheses are provided:

 


  1. assuming the use strict directive isn’t provided in this case 

  2. To be more accurate, the target also behaves differently depending on whether the target reference refers to a property of an object vs a variable in an environment record 

JavaScript Corners – Part 7
Calls and With Statements

JavaScript Corners – Part 7
Calls and With Statements

Here’s a quick one. What does the following print? (Assuming not in strict mode)

In non-strict mode, the naked function call foo() gets a  this value that is the global object. So the first case prints “Global”.

In the second case, we’re invoking foo as a member of  bar, and so the this value is bar (it prints “Bar”).

The last case is the most interesting, and the most useless (since with statements are strongly discouraged, and cannot be used outside of non-strict mode). The this object in this case is actually bar. JavaScript recognizes that the function foo here is being invoked within the context of a with statement, and implicitly uses the bar object. This prints “Bar”.

JavaScript Corners – Part 6

JavaScript Corners – Part 6

In what order does the following evaluate?

TL;DR Answer


Step 1: Variable Access

First off, what does this code even mean? If you’re not intimate with JavaScript, this might seem like a very confusing line of code. In fact, even if you’re familiar with JavaScript, this can be confusing.

So let’s break it down, starting with:

The expression a loads the value a from the surrounding scope1. This is done by searching up the scope chain until a is found.

There are a number of different types of scopes in JavaScript, including those that refer to blocks (like the inside of a for-loop), functions (the contents of a function), objects (scopes that are created using a with statement, or the global scope).

For our purposes, let’s define a at the global scope. You’ll see why in a moment. Assuming we’re working in Node.js, the global object is called global, and properties of the global object are part of the global scope2.

But, since we’re interested in the order of evaluation, it would be useful to know when the value a is accessed. Luckily, in JavaScript, you can define properties that have a getter and/or setter, which we can use to log when the global variable is accessed:

Great! We can now see when the global variable “a” is accessed. There aren’t many languages where you can do that. Hooray for JavaScript.

We may want to define more globals this way, so lets refactor this to use a helper:

Step 2: Calling the function

Now let’s look at the following statement:

This is, unsurprisingly, a function call. It first evaluates a, as indicated above, by fetching a from the current scope. Then it calls a as a function. Nothing special going on here.

But to make this work with our a, we’re going to need to make sure that a is defined as a function, and not the value 42. So let’s change our getter to return a function:

To answer our original question, we’re going to need to create a whole bunch of functions. So let’s again refactor this into a helper:

Step 3: Member access

The expression x[y], in JavaScript, is a property lookup. It evaluates the expressions x and y, and then finds the property on the object x that has the name resulting from the expression y. Here’s a snippet that illustrates this:

If you’re not very familiar with JavaScript, it’s important to note here that the property name used here is "myProp", and not "y". The property name is the result of evaluating y.

Again, it will be useful to know exactly when the property is accessed, so let’s use a getter instead:

Here I’ve just used the ES6 getter syntax, rather than using defineProperty.

As before, we’re going to need to do this a few times, so let’s create a helper function:

Step 4: Assignment

The last piece of the puzzle is the assignment operator. Consider the following code:

The assignment operator, like the other operators so far, will evaluate the each operand, and then perform some operation on the results. In the above case, x is evaluated, and then y is evaluated, and then the result of y is assigned to the result of x.

But wait. What do you mean “the result” of x?

The model here that JavaScript uses internally, is that x actually evaluates to a reference. This is a type in JavaScript which you’ve probably never heard of. A reference value consists of two components:

  • A base value, that tells you what container the value is stored in
  • A name, that tells you which value in the container is being referred to

In this case, the expression x evaluates to a reference that has the following attributes:

  • A base value that is the global object
  • A name that is the string "x"

In other words, the reference value is something like the English description “the property x on the global object”. When you assign to x, you are assigning to “the property x on the global object”. When you delete x, you are deleting “the property x on the global object”.

The expression y also evaluates to a reference, but the assignment operator coerces that reference to the actual referenced value. The same thing is done in expressions such as x + y or x(y).

Here’s another example of an assignment:

In this case, the base value of the reference is the object x, and the name is y.  The assignment sets the value referred to as “the property ‘y’ of the object x”. Similarly, you can do delete x.y to delete “the property ‘y’ of the object x”.

In a more detailed consideration of the above example, x and z evaluate to references. Both x and z are then coerced to values (dereferenced, by fetching the property or variable), and then a third reference is created refers to the property y on the base object x.

But, what order does this occur in? To find out, let’s use our trusty helper functions:

This might come as a little bit of a surprise. The expression x is evaluated before the expression y, and then the assignment takes place. In some ways, one expects the opposite — one expects that the left hand side of an assignment is not considered until the right hand side.

This seems to be a general rule in JavaScript. Operands are evaluated from left to right, and then the operator is executed. Perhaps an exception to this rule-of-thumb, is that the short-circuiting operators such as && must necessarily execute part of the operation without all the operands fully evaluated.

Side note: in languages such as C++, the order of the left and right hand side of a most operators is not defined. The compiler can chose to evaluate them in whatever order it thinks is best, or even evaluate them simultaneously (e.g. if the CPU has multiple cores). JavaScript is different, in that the specification lays out a specific, unambiguous ordering.

We can follow this to its logical conclusion, and determine the order of execution of the whole of the original program in question:

Can we abuse it? (Advanced)

The reason I started looking into this at all, is that I was trying to discover a way to “see” references. They are objects that exist in the execution model, but are never shown explicitly to the user of the language, so do they really need to exist at all?

This is import to me, because I’m writing a JavaScript compiler, and need to know whether references are best left as just a description mechanism in the ECMAScript specification, or if they should be considered to be real entities with real allocated memory in the runtime.

So, can we design an example, that unequivocally proves that there must be a reference allocated in memory at some point?

Here’s my attempt:

What I’ve done here is break up the x[y] = z assignment using the await operator. The await operator will suspend the statement (and the rest of the async function), allowing us to swap out various things in the environment to see if we can mess with the operation while it is suspended. What we’re trying to prove here, is that the reference itself must be preserved in memory, from the time that the operation is suspended, to the time that it is resumed (when z is resolved).

To make it even more apparent, I’ve executed the async function multiple times, trying different ways to “mess” with the pending operations.

Conclusions

This experiment has proven to me that references are “almost” tangible objects. We can see that they must exist in memory under some circumstances, and that they are not simple “pointer” values — they must refer to both the object and the property name.

This leads to some interesting results when it comes to the order of evaluation of various expressions. While this knowledge isn’t needed for everyday programming scenarios, it helps to have a deeper understanding of what’s going on so that we know where the limit lies.

 

 

 

 


  1. Known in ECMAScript as a Lexical Environment 

  2. There is an interesting recursion here, since the value global here is also a globally scoped binding, which means the global property on the global object points to itself. You can see this if you have a statement like console.log(global.global.a) 

Coding on Paper in an Interview

Coding on Paper in an Interview

My company is in the process of hiring a back end or full stack software engineer. During the interview process, I often get complaints from candidates when I bring out an old fashioned pad of paper and pencil and ask them to write some code for me (or I offer for them to code on the whiteboard).

This is 2017, and we have syntax highlighters, auto-complete, Stack Overflow, etc. Why would I want to test a candidate’s ability to code on paper?? This seems barbaric and absurd. Like asking a racing car driver to ride around a track on a bicycle to see how well he handles the corners. Surely we’re past this antiquated form of testing in this day and age?

Well, no. Let me share my side of the story.

I need people who can code

The position is for a software engineer. I need to know that you can code1. It’s quite simple.

We can have a good chat about Azure, about how you parted the red sea, or how you helped get a man on the moon. But in the end, you’re here to code, so you need to show me that you can.

Hiring a coder without seeing them code, is like hiring a chef without tasting their food.

The number one best way to test your real-world coding ability would be to have you work with me for 3 months, but that’s not a practical way to screen people for a new position.

Another way for me to establish your level of skill would be for me to look at work you’ve done in the past. AKA your public contributions to GitHub, Stack Overflow, blogs, etc. I am perhaps one of the few managers who will actually clone your GitHub repos and look through your code, your commit history, your documentation, your blog posts2, your answers on forums, etc.

A quick side note on this: remember that I’m also a software engineer, like you. I understand perfectly well that there are times when you need to throw a heap of “poor” code together, just to get something done quickly, or because it’s just an experimental throw-away project that you were working on in your spare time. I won’t judge you on this. The signature of good style and craftsman ship will still shine through, even in your darkest code, so I still read it.

But, I can’t just look at past work you’ve already done. I also need to look inside your head. I need to see those cogwheels spinning when you’re working on a problem. I don’t just want to see the final outcome, I want to know what thoughts went through your mind on the journey to get there. The best way to do this is for us to work on a piece of code together, in an interview. Here you can explain to me what you’re thinking, and ask questions3

The code itself is the easy part

In the past, I used to ask two coding questions in an interview. I started with an easy one, and then would progress to the harder question. But I became tired of the emotional distress of watching people struggle through the harder question, and often eventually give up.

So, now I just ask the easy question4.

In fact, here it is. I’ll give it to you.

Write a function that adds up a collection of numbers.

That it.

That’s it?

Yes. That’s it.

In fact, I’ll give you the5 answer too6 :

Here’s another one:

Side note: One person has pointed out that they would just use the Sum function that .net provides. Well done. Ten brownie points for you7. But I then I will follow on by saying something like “Somebody on the .net development team had to write that builtin Sum function. Pretend it was you. How would you write it?”

There are obviously many different ways to write some code that satisfies the initial requirements statement of this test question. This is true in the real world as well — feature requests come in many different forms, to varying degrees of specification, and you need to be able to dig in and understand the problem that the user is trying to solve, and explore different solutions and the effectiveness of each.

Be resourceful. Dig in.

I don’t care whether or not you remember the syntax for generics or extension methods in C#. I don’t care if you remember what the C# equivalent to a fold/reduce function is. These are questions that Google or Stack Overflow can answer in the real world.

I don’t care about your spelling. This is something a spell checker would check in the real world.

I want to see how you engage a problem. When you’re actually working on the job, you’re going to have all sorts of weird and wonderful requests thrown your way. How do you deal with them? Do you blindly start pecking at the keyboard, or do you dig into what’s actually being asked?

If you need some tool to help you, do you say “this company is so stupid, they don’t even provide xyz!”, or do you say “how do we get xyz?”.

The same is true in an interview. Do what you need to do to get the job done. If you need to understand the context more, then ask me. If you need auto-complete and an IDE, or Google, ask for a laptop (actually I typically offer one).

At the very least, I expect you to ask me what kind of numbers we’re adding together.

If you need help remembering the way something works, or the syntax for something, ask me. Let’s work through it together. I want to know that you can work effectively with me and others on the team. I want to know that you feel comfortable asking for advice, that you’re not the kind of person to suffer in silence.

If you think that the whole thing is stupid, let me know. I want to know that the people on my team can challenge me and can stand up to being challenged themselves.

It’s about why

It’s not about what your answer looks like. It’s about why you made certain choices. Were there performance concerns you were worried about? What usage scenarios were you planning for — and did you ask? Is one language construct better than another from a maintainability standpoint? What approaches did you consider, and how did you weigh up each?

If you’re [un]lucky enough to interview with me, keep in mind that the main thing I’m looking for is your reasoning and approach when encountering a problem. Talk me through your thinking.

It’s a toy

Yes, this coding exercise is a toy example. And yes, I’ll make stuff up as I go. If you ask whether the numbers need to be integers or floats, I’ll make the answer up as a I go, and it might be different every time I do an interview.

But put yourself in my shoes for a moment. In an interview setting, we only have time to play with a toy example. We don’t have time for me to explain a real problem and have you craft a real solution for me. I need to know how you code, and a toy example is the only tool in the box that can get the job done effectively in a short span of time.

Hopefully by now you understand that it really won’t help you to use a laptop in my interview. The things I’m looking for are things where a laptop won’t help you. Sorry. But do whatever makes you feel comfortable.


  1. …and that you can communicate effectively, and work well with my team, and have the relevant experience. But all of this is pointless if you can’t code. 

  2. I don’t care what the blog posts are about actually — I will evaluate you based on passion, ability to communicate clearly, etc. Bonus points if your blog is about coding, and I can get a two-for-one evaluation on communication and coding. 

  3. Like maybe “WTF are we doing this for?” 

  4. [Edit:] Since writing this post, I’ve changed my mind about the second, “hard” question. I now ask the hard question as well, depending on how much time is available. I might also ask a “time-boxed” version of the hard question — saying something like “do as much as you can of this in 10 minutes”. Part of the reason is that I want to give you the opportunity to present your skills on structurally different questions. 

  5. *an 

  6. Since the position is for an Azure developer, the most common language of choice for this question is C# 

  7. Even if you didn’t know that it existed, I’d give you points for saying “I’m sure this function already exists in some library somewhere. I would probably first work out if I can use that, rather than reinventing the wheel” 

JavaScript Corners – Part 5

JavaScript Corners – Part 5

Here’s a quick one:

This was quite unexpected to me. It’s the only time I’ve ever seen where the left-hand side of an assignment can affect the right-hand side.

This only happens once. Once the anonymous function has a name, it can’t be re-named:

Interestingly, this doesn’t seem to work with destructuring:

This implies that somewhere between when the anonymous function is instantiated, and when it added to the array literal, the anonymous function acquires a name. It’s not the destructuring itself that suppresses the name, as can be seen in the following example:

It also doesn’t seem to work with anonymous functions passed as parameters:

It also doesn’t seem to work with anonymous functions evaluated from more complicated expressions:

 

JavaScript Corners – Part 4

JavaScript Corners – Part 4

Here’s another quick one. It relates to the scoping rules with parameter expressions.

Function foo has three parameters: x, f, and y. The key thing here is that the default value for f is a function that encloses the local lexical scope surrounding the function, and we’ve designed the function in such a way that when we call it it “tells” us the values of x, y, and z in the surrounding scope.

So the question is, which values of x, y, and z does f close over? There are global variables x, y, and z, there are parameters x and y, and there are local variables x, y and z. The parameter x is intentionally ordered before the function f is initialized, while parameter y is positioned to be after the function f is initialized.

I’ll spare you the time of running the code yourself. On my machine, in node.js 7.0.0, the output is [ 1, 2, 'c']. Clearly no local variables have been used, and f is capable of seeing parameter y even though it’s declared after f. The output is the same whether or not the code is executed in strict mode.

One of the most interesting things here, to me, is that the local variable x is not an alias for the parameter x.  This is strange when you consider the following code:

Given that local variables are apparently not aliases of the parameters with the same name, you would expect the output of the above to be undefined, since variable x is not initialized, even though parameter x is initializedHowever, the output is actually 42.

Where did we go wrong in our logic? Let’s see if we can get an example that explores what’s going on:

The output of this is:

This clearly tells me that variable x is not an alias of parameter x, but rather a separate variable that is initialized to the same value as parameter x.

Also, as a side note, it tells me that there is a subtle semantic distinction between initializing a variable to undefined and not initializing a variable at all, which is very interesting.

I should note that we’ve explored this empirically, not deducing the behavior from the spec. When I run the same experiment in Firefox I get a different result — both instances of y are undefined.

Which is correct?

I believe the V8 (node.js) implementation is more accurate in this case. There’s a note in the ECMAScript specification1 that says:

NOTE A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.

I think this note is self explanatory, and tell us that the closure function in the parameter list is not meant to be able to see the local variables of its parent function.

P.S.

I’m going add one last investigation to this post. The above quote applies only if there are parameter expressions (if some parameters have default values). If there are no parameter expressions, then apparently this second “environment” is not created, and so the variable x should be an alias for the parameter x.

At first I thought that there was no way that we could ever test this distinction. Can you think of a way to test this difference?

Spoiler alert, I did think of a way. If the code is not executing in strict mode, then the arguments variable holds aliases for the parameters, which makes it possible to mutate parameters without referring to them by name. This is important, because once you have a local variable with the same name, there is no way to know if the local variable is a copy of the parameter, or an alias of the parameter, based purely on code that identifies it by name.

Take a look at the following experiment:

First note that y is not used in this code sample, but you’ll see why I added it in a moment.

The first log output of “1” shows that the variable x is either a copy of parameter x or an alias of parameter x. Then we continue by modifying the parameter x, without touching the variable x. Then we log the value of the variable x and see that it’s also changed — because in fact the variable and parameter x are both symbols for the same binding.

But now look at this slight modification to the code:

Note that again y is not used. In fact, to keep this a controlled experiment, y is even initialized to the same value that is passed as a parameter. The contents of the value initializer is not relevant though, because the initializer is never evaluated. What is important in this case is that there is an initializer expression at all, regardless of whether it executes or not.

The surprising thing, as I noted in the comment on the snippet, is that the second output is now 1 instead of 2, resulting from the fact that the mutation of the argument does not change the variable.

This is not a bug in node.js, but just an interesting quirk of the spec, in another corner of JavaScript.

 


  1. https://tc39.github.io/ecma262/#sec-functiondeclarationinstantiation 

JavaScript Corners – Part 3

JavaScript Corners – Part 3

I was busy reading ES spec today, and the following question popped into my head: at what point are default parameters evaluated?

To answer this question, I wrote the following script:

If default parameters are evaluated when the function is declared, then we would expect 'a' to appear once in the terminal output.

On the other hand, if the default parameter expressions are evaluated when the function is called, then we would expect 'a' to appear two or three times, corresponding to each time the function is called, and whether the default parameter expression is evaluated even when an argument is provided.

What do you think the output is? I won’t show you here… you can run the snippet yourself in a REPL to see if you’re correct or not.

As I did last time, I’ll leave you with this  mind-bending challenge: what does the following do?