DEV Community

Cover image for Lesser-Known JavaScript Tricks
Parwinder 👨🏻‍💻
Parwinder 👨🏻‍💻

Posted on • Updated on

Lesser-Known JavaScript Tricks

Constructor brackets are optional

const newDate = new Date(); // valid
const myClass = new MyClass(); // valid

const anotherDate = new Date; // Also valid
const myClass = new MyClass; // You bet this is valid

The only time you would need those brackets is if a constructor expects arguments.

With statement

🚨with statement is not recommended, and it is forbidden in ES5 strict mode.

with statement extends the scope chain for a statement. with will add up all properties of an object passed in the scope chain.

const person = {
    name: "Parwinder",
    age: 33,
    work: "Software Architect"
}

with (person) {
    console.log(`Hi, I am ${name}, and I am ${ age } years old. I work as a ${work}.`);
    // Hi, I am Parwinder, and I am 33 years old. I work as a Software Architect.
}

Function arguments

Every function (except arrow functions) has an arguments array-like object that contains the value of all arguments passed to the function.

function foo(a, b, c) {
  console.log(arguments[0]); // 1
  console.log(arguments[1]); // 2
  console.log(arguments[2]); // 3
}

foo(1, 2, 3);

arguments have two properties:

  1. arguments.callee: the function being invoked
  2. arguments.callee.caller: the function that has invoked the current function

🚨Just like the with statement above, callee and caller are forbidden in ES5 strict mode.

Pure object

A pure object has no functions in its prototype.

const x = {};

This creates an object, but the prototype will have a constructor and methods like hasOwnProperty, isPrototypeOf, and toString.

const x = Object.create(null);

create(null) generates an object with no prototype! 🤯

Removing duplicates from an array

const arr = [1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 6, 6, 6, 7, 8, 9];
const arrWithoutDuplicates = [...new Set(arr)];
console.log(arrWithoutDuplicates); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

The key property of a set is having unique values. Once we have the Set from an array, we can use the spread(...) operator to spread it into an empty array.

Optional Chaining

Whenever you access a nested object property where you do not know if the sub object exists or not, you end up doing this:

const nestedObject = {
    name: "Parwinder",
    details: {
        age: 33,
        cars: {
            first: "jeep",
            second: "tesla",
            accessories: {
                x: 200,
                y: 300
            }
        }
    }
}

if (nestedObject &&
    nestedObject.details &&
    nestedObject.details.cars &&
    nestedObject.details.cars.accessories) {
    console.log(nestedObject.details.cars.accessories.x); // 200
}

Optional chaining eliminates the clutter. With optional chaining you can do:

const nestedObject = {
    name: "Parwinder",
    details: {
        age: 33,
        cars: {
            first: "jeep",
            second: "tesla",
            accessories: {
                x: 200,
                y: 300
            }
        }
    }
}

console.log(nestedObject?.details?.cars?.accessories?.x); // 200

🚨 Optional Chaining has made it to the ES2020/ES11 Specifications! Check it out here: https://tc39.es/ecma262/2020/

Top comments (12)

Collapse
 
bartosz profile image
Bartosz Wójcik • Edited

That thing with arguments[] array was new to me! Thanks :). dev.to is a really refreshing breeze after StackOverflow experience.

Collapse
 
bhagatparwinder profile image
Parwinder 👨🏻‍💻

I'm glad you discovered something new! Keeps me motivated to write. Thanks for reading ♥️

Collapse
 
pentacular profile image
pentacular

Every function has an arguments array-like object that contains the value of all arguments passed to the function.

Note that arrow functions do not have an arguments object.

Collapse
 
bhagatparwinder profile image
Parwinder 👨🏻‍💻

This is such an oversight from me. Thanks for catching it. I wrote a full blog post on arrow functions and how they behave differently with this, new and arguments. I missed it here. I'll update.

Thanks for reading ♥️

Collapse
 
kenbellows profile image
Ken Bellows • Edited

🚨At the time of writing, optional chaining is in Stage 4 (Draft) of the new ES standard, and it will most likely make it to the final spec. 🤞

Optional Chaining made it into ES2020, and it's implemented in all major browsers now (caniuse.com/#feat=mdn-javascript_o...)!

Collapse
 
bhagatparwinder profile image
Parwinder 👨🏻‍💻 • Edited
Collapse
 
kenbellows profile image
Ken Bellows

Idk how those pages get updated, but there's no doubt it made it into ES2020: 2ality.com/2019/12/ecmascript-2020...

Thread Thread
 
bhagatparwinder profile image
Parwinder 👨🏻‍💻

TC39 is the committee that handles ES proposals and specifications.

That being said your article does lead to what I was eventually looking for

tc39.es/ecma262/2020/

Looks like it is in the final document. I will update the post. Thanks for the awesome feedback ♥️

Thread Thread
 
kenbellows profile image
Ken Bellows

Yeah I know about TC39, I just meant that I don't know at what point on the process those specific pages get updated; I would have thought it would be after ES2020 is finalized and released, but apparently not

Collapse
 
melvincarvalho profile image
Melvin Carvalho

Great post. Slight nit:

The only time you would need those brackets is if a constructor expects arguments.

new Date().toString() // works
new Date.toString() // fails

Collapse
 
bhagatparwinder profile image
Parwinder 👨🏻‍💻

I am so glad you brought this up. I would love to explain this! There is a reason why this works:

const x = new Date; // What I taught in this blog post
console.log(x.toString());

And this does not

new Date.toString();

It's because new Date.toString() is not equal to new Date().toString(). *There is an extremely subtle difference. They have different precedence. *

Check out: developer.mozilla.org/en-US/docs/W...

new Date.toString() throws an error because . has higher precedence than new Date so the expression becomes (or it is resolved as) (new (Date.toString))(). They might look same but they are evaluated differently!

In short, if you would like to invoke the constructor and chain it with a method in the object, the correct syntax is:

(new Date).toString();

Give it a try😉

Collapse
 
melvincarvalho profile image
Melvin Carvalho

That's pretty amazing thanks!

So when chaining you dont save typing the parentheses, they can just go in two different places :)