Peter Seliger
3 min readDec 27, 2023

--

I have to put it that bluntly, the author looses any credibility in the very moment "closure" gets mentioned the fist time. Though constructor functions quite often create closures at instantiation time, UserProfileNoPrototype does not. There is nothing that could be closed over, no locally scoped variables, just public properties that get assigned to the newly created instance. Not even the instance-method displayInfo has the potential of being involved into the creation of a closure; it too does neither enclose anything nor is it enclosed itself.

But even worse are the sections which try to come up with closure-creating examples. Exactly one of it does accidentally create a closure (and not even for the reasons the author mentions) . The author correctly explains what a closure is, but only to immediately fail with providing a correctly implemented Product type in terms of the intended closure.

function Product(name) {
this.name = name;

this.getDetails = function () {
// Imagine this call retrieves a large amount of data

var productDetails = someService.callToGetProductDetails(name);
return productDetails;
};
}

Here the Product constructor function features the local variable name which gets provided as argument to the constructor. The “closing over” happens due to the getDetails method which does refer the name variable, which is out of the getDetails’ own scope but lives within the scope of the (outer) constructor function.

Let’s be more clear. Implementing getDetails like follows …

function Product(name) {
this.name = name;

this.getDetails = function () {
var productDetails = someService.callToGetProductDetails(this.name);
return productDetails;
};
}

… where the getDetails method does pass this.name instead of the locally scoped name to the forwarding someService.callToGetProductDetails call does not create any closure. Neither does the existence of the productDetails variable which the author wrongly identifies as the one being closed over. Since this variable's value gets returned by the getDetails method, and because there are no other references to it, this variable "dies" immediately after the method has been invoked.

An implementation which actually creates a closure for every Product instance due to a locally scoped productDetails variable looks like follows …

function Product(name) {
let productDetails;

this.name = name;

this.updateDetails = () =>
productDetails = someService.getProductDetails(this.name);

this.getProductDetails = () => productDetails;
}

Everything provided after the first Product example, regardless of text or accompanied examples, shows the misconception in the authors mind of how instantiation, JavaScript prototypes and closures are interconnected, especially regarding closures.

Just another article which contributes to the frustration beginners and intermediates are experiencing by dealing with the programming concepts and paradigms of this beautiful and expressive programming language; and not because of the language core but due to poorly written articles and badly implemented example code.

Addendum

While doing a third proof-reading I stumbled again over one of the authors claims …

> In this example, if
> someService.callToGetProductDetails(name)
>
retrieves a large amount of data, and getDetails
> is a method created for every Product instance,
> each instance will hold onto the productDetails
> data as long as that instance exists. If you have
> many Product instances, this can lead to
> significant memory use and then you will wonder
> why the website/app is running so slowly…

… which actually is written that badly and factually utterly wrong, that I hereby call the author of withdrawing the article. Please gain yourself some reliable knowledge first before advising others. Good intensions do not help if the effect is just spreading more half-baked technical ”wisdom”. At least let other people do a proof-reading of what you came up with before publishing even the smallest of it.

--

--

Responses (1)