In this post, lets explore some lesser known Javascript concepts.
The arguments object
Functions in Javascript have a arguments
property that contains the arguments passed during a call. It looks like an array but it’s not an array, it is of the type Arguments.
function foo() { console.log(arguments.length); } foo('a'); // 1 foo('a', 1, []); // 3
That’s why Javascript functions are so flexible. For example, you can write functions like this
function sum() {
var sum = 0;
for(var i=0; i<arguments.length; i++) {
sum += arguments[i];
}
return sum;
} console.log(sum(10, 5)); // 15
console.log(sum(1, 2, 3, 4, 5)); // 15
call() and apply()
When we declare a function (without any enclosing scope), it’s declared in the document object (Browser Javascript, not NodeJs)
function foo() {
console.log(this); // prints the document object
}
Say we write a function like this
var a = 5;
var b = 10; function sum() {
return this.a + this.b;
} console.log(sum()); // prints 15, since a, b and sum are part of the document object console.log(this.sum()); // prints 15
if we have an identical object having a
and b
properties, how can we use this method on that object
var someObject = {
a: 20,
b: 22,
}; console.log(sum.call(someObject)); // prints 42 console.log(sum.apply(someObject)); // prints 42
call
and apply
are methods which help a method run in a different object's context.
Let’s see a practical example
Math.min() takes multiple arguments
Math.min(3, 4, ); // 3
Math.min(3, 4, 1); // 1
Math.min(3, 4, 1, 0); // 0
Now consider having an array of numbers. We can’t pass the array directly since the Math.min
function only accepts numbers
var n = [4, 2, 1, 3, 5];
Math.min(n); // null
This is where the apply method could be used
Math.min.apply(null, n); // 15
The first argument in the apply method is the context under which the function should execute and the second argument takes an array and passes it to the function arguments.
Difference between call() & apply()
call and apply have similar functionality except for the way the arguments are passed to the function.
var n = [4, 2, 1, 3, 5]; function foo() {
console.log(arguments.length);
} foo.call(null, n); // prints 1
foo.apply(null, n); // prints 5
The apply()
method takes an array as the second parameter whereas the call()
method takes multiple parameters.
// to send n arguments
foo.call(object, arg1, arg2, ... argn);
foo.apply(object, [arg1, arg2, ... argn]);
ES6: The Symbol type
Since ES6, has become a primitive type. A Symbol
serves as a unique identifier and no two symbols cannot be the same.
// creating a symbol
var x = Symbol(); // an optional description could be provided
var y = Symbol("some description"); typeof y // symbol
The argument taken by the Symbol
factory method is just a description and it doesn't influence the created Symbol
in any way.
Symbol("A") === Symbol("A") // false
Symbols can’t be coerced as strings, the toString
method should be called for their string representation.
var x = Symbol("x"); // Error: Cannot convert a Symbol value to a string
console.log("X: " + x); console.log("X: " + x.toString()); // X: Symbol(x)
Symbols can be added as object properties, but the syntax is different
const id = Symbol("id");
var someObj = {
name: "John",
age: 25,
[id]: 99
}; // name, age
Object.keys(someObj).forEach(o => console.log(o)); // name, age
Object.getOwnPropertyNames(someObj).forEach(o => console.log(o)); // Symbol(id)
Object.getOwnPropertySymbols(someObj).forEach(s => console.log(s.toString())); console.log(someObj["id"]); // undefined
console.log(someObj[id]); // 99
Symbol properties won’t be enumerated when using Object.keys()
or Object.getOwnPropertyNames()
.
Object.getOwnPropertySymbols(someObj)
should be used for iterating over the symbols in a object.
Also while accessing a symbol, the symbol reference should be used.
Since Symbols aren’t enumerable, they won’t appear in serialized JSON.