DEV Community

Cover image for 10 Most Asked Questions About JavaScript
KiranPoudel98 for Truemark Technology

Posted on • Updated on • Originally published at thedevpost.com

10 Most Asked Questions About JavaScript

JavaScript is a client-side programming language. It is used in over 90% of the websites in the world. It is one of the most used programming languages in the world. So, today we will be talking about the 10 most asked questions about JavaScript.

10 Most Asked Questions About JavaScript

1. How to remove a specific item from an array?

Answer:

First, find the index of the array element you want to remove using indexOf, and then remove that index with splice.

The splice() method changes the contents of an array by removing existing elements and/or adding new elements.

const array = [2, 5, 9];

console.log(array);

const index = array.indexOf(5);
if (index > -1) {
  array.splice(index, 1);
}

// array = [2, 9]
console.log(array); 
Enter fullscreen mode Exit fullscreen mode

The second parameter of splice is the number of elements to remove. Note that splice modifies the array in place and returns a new array containing the elements that have been removed.

For the reason of completeness, here are functions. The first function removes only a single occurrence (i.e. removing the first match of 5 from [2,5,9,1,5,8,5]), while the second function removes all occurrences:

function removeItemOnce(arr, value) { 
    var index = arr.indexOf(value);
    if (index > -1) {
        arr.splice(index, 1);
    }
    return arr;
}

function removeItemAll(arr, value) {
    var i = 0;
    while (i < arr.length) {
        if(arr[i] === value) {
            arr.splice(i, 1);
        } else {
            ++i;
        }
    }
    return arr;
}
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

To remove an element of an array at an index i:

array.splice(i, 1);
Enter fullscreen mode Exit fullscreen mode

If you want to remove every element with value number from the array:

for(var i = array.length - 1; i >= 0; i--) {
    if(array[i] === number) {
        array.splice(i, 1);
    }
}
Enter fullscreen mode Exit fullscreen mode

If you just want to make the element at index i no longer exist, but you don’t want the indexes of the other elements to change:

delete array[i];
Enter fullscreen mode Exit fullscreen mode

2. How to redirect the user from one page to another using jQuery or pure JavaScript?

Answer:

One does not simply redirect using jQuery.

jQuery is not necessary and window.location.replace(...) will best simulate an HTTP redirect.

window.location.replace(...) is better than using window.location.href, because replace() does not keep the originating page in the session history, meaning the user won’t get stuck in a never-ending back-button fiasco.

If you want to simulate someone clicking on a link, use location.href.

If you want to simulate an HTTP redirect, use location.replace.

For example:

// similar behavior as an HTTP redirect
window.location.replace("http://stackoverflow.com");

// similar behavior as clicking on a link
window.location.href = "http://stackoverflow.com";
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

You can also do it as shown below.

$(location).attr('href', 'http://stackoverflow.com')
Enter fullscreen mode Exit fullscreen mode

3. How do JavaScript closures work?

Answer:

A closure is a pairing of:

  • A function, and
  • A reference to that function’s outer scope (lexical environment)

A lexical environment is part of every execution context (stack frame), and is a map between identifiers (ie. local variable names) and values.

Every function in JavaScript maintains a reference to its outer lexical environment. This reference is used to configure the execution context created when a function is invoked. This reference enables code inside the function to “see” variables declared outside the function, regardless of when and where the function is called.

If a function was called by a function, which in turn was called by another function, then a chain of references to outer lexical environments is created. This chain is called the scope chain.

In the following code, inner forms a closure with the lexical environment of the execution context created when foo is invoked, closing over variable secret:

function foo() {
  const secret = Math.trunc(Math.random()*100)
  return function inner() {
    console.log(`The secret number is ${secret}.`)
  }
}
const f = foo() // `secret` is not directly accessible from outside `foo`
f() // The only way to retrieve `secret`, is to invoke `f`
Enter fullscreen mode Exit fullscreen mode

In other words, in JavaScript, functions carry a reference to a private “box of state”, to which only they (and any other functions declared within the same lexical environment) have access. This box of state is invisible to the caller of the function, delivering an excellent mechanism for data-hiding and encapsulation.

And remember functions in JavaScript can be passed around like variables (first-class functions), meaning these pairings of functionality and state can be passed around your program: similar to how you might pass an instance of a class around in C++.

If JavaScript did not have closures, then more state would have to be passed between functions explicitly, making parameter lists longer and code noisier.

So, if you want a function to always have access to a private piece of state, you can use a closure, and frequently we do want to associate the state with a function. For example, in Java or C++, when you add a private instance variable and a method to a class, you are associating state with functionality.

In C and most other common languages, after a function returns, all the local variables are no longer accessible because the stack-frame is destroyed. In JavaScript, if you declare a function within another function, then the local variables of the outer function can remain accessible after returning from it. In this way, in the code above, secret remains available to the function object inner, after it has been returned from foo.

Uses of Closures

Closures are useful whenever you need a private state associated with a function. This is a very common scenario and you need to remember that JavaScript did not have a class syntax until 2015, and it still does not have a private field syntax. Closures meet this need.

Private Instance Variables

In the following code, function toString closes over the details of the car.

function Car(manufacturer, model, year, color) {
  return {
    toString() {
      return `${manufacturer} ${model} (${year}, ${color})`
    }
  }
}
const car = new Car('Aston Martin','V8 Vantage','2012','Quantum Silver')
console.log(car.toString())
Enter fullscreen mode Exit fullscreen mode

Functional Programming

In the following code, function inner closes over both fn and args.

function curry(fn) {
  const args = []
  return function inner(arg) {
    if(args.length === fn.length) return fn(...args)
    args.push(arg)
    return inner
  }
}

function add(a, b) {
  return a + b
}

const curriedAdd = curry(add)
console.log(curriedAdd(2)(3)()) // 5
Enter fullscreen mode Exit fullscreen mode

Event-Oriented Programming

In the following code, function onClick closes over variable BACKGROUND_COLOR.

const $ = document.querySelector.bind(document)
const BACKGROUND_COLOR = 'rgba(200,200,242,1)'

function onClick() {
  $('body').style.background = BACKGROUND_COLOR
}

$('button').addEventListener('click', onClick)

<button>Set background color</button>
Enter fullscreen mode Exit fullscreen mode

Modularization

In the following example, all the implementation details are hidden inside an immediately executed function expression. The functions tick and toString close over the private state and functions, they need to complete their work. Closures have enabled us to modularise and encapsulate our code.

let namespace = {};

(function foo(n) {
  let numbers = []
  function format(n) {
    return Math.trunc(n)
  }
  function tick() {
    numbers.push(Math.random() * 100)
  }
  function toString() {
    return numbers.map(format)
  }
  n.counter = {
    tick,
    toString
  }
}(namespace))

const counter = namespace.counter
counter.tick()
counter.tick()
console.log(counter.toString())
Enter fullscreen mode Exit fullscreen mode

Examples

Example 1

This example shows that the local variables are not copied in the closure. The closure maintains a reference to the original variables themselves. It is as though the stack-frame stays alive in memory even after the outer function exits.

function foo() {
  let x = 42
  let inner  = function() { console.log(x) }
  x = x+1
  return inner
}
var f = foo()
f() // logs 43
Enter fullscreen mode Exit fullscreen mode

Example 2

In the following code, three methods log, increment, and update all close over the same lexical environment.

And every time createObject is called, a new execution context (stack frame) is created and a completely new variable x, and a new set of functions (log etc.) are created, that close over this new variable.

function createObject() {
  let x = 42;
  return {
    log() { console.log(x) },
    increment() { x++ },
    update(value) { x = value }
  }
}

const o = createObject()
o.increment()
o.log() // 43
o.update(5)
o.log() // 5
const p = createObject()
p.log() // 42
Enter fullscreen mode Exit fullscreen mode

Example 3

If you are using variables declared using var, be careful you understand which variable you are closing over. Variables declared using var are hoisted. This is much less of a problem in modern JavaScript due to the introduction of let and const.

In the following code, each time around the loop, a new function inner is created, which closes over i. But because var i is hoisted outside the loop, all of these inner functions close over the same variable, meaning that the final value of i (3) is printed, three times.

function foo() {
  var result = []
  for (var i = 0; i < 3; i++) {
    result.push(function inner() { console.log(i) } )
  }
  return result
}

const result = foo()
// The following will print `3`, three times...
for (var i = 0; i < 3; i++) {
  result[i]() 
}
Enter fullscreen mode Exit fullscreen mode

Final points:

  • Whenever a function is declared in JavaScript, a closure is created.
  • Returning a function from inside another function is the classic example of closure, because the state inside the outer function is implicitly available to the returned inner function, even after the outer function has completed execution.
  • Whenever you use eval() inside a function, a closure is used. The text you eval can reference local variables of the function, and in the non-strict mode, you can even create new local variables by using eval('var foo = …').
  • When you use new Function(…) (the Function constructor) inside a function, it does not close over its lexical environment, it closes over the global context instead. The new function cannot reference the local variables of the outer function.
  • A closure in JavaScript is like keeping a reference (not a copy) to the scope at the point of function declaration, which in turn keeps a reference to its outer scope, and so on, all the way to the global object at the top of the scope chain.
  • A closure is created when a function is declared. This closure is used to configure the execution context when the function is invoked.
  • A new set of local variables is created every time a function is called.

Alternative Answer:

Every function in JavaScript maintains a link to its outer lexical environment. A lexical environment is a map of all the names (eg. variables, parameters) within scope, with their values.

So, whenever you see the function keyword, code inside that function has access to variables declared outside the function.

function foo(x) {
  var tmp = 3;

  function bar(y) {
    console.log(x + y + (++tmp)); // will log 16
  }

  bar(10);
}

foo(2);
Enter fullscreen mode Exit fullscreen mode

This will log 16 because function bar closes over the parameter x and the variable tmp, both of which exist in the lexical environment of the outer function foo.

Function bar, together with its link with the lexical environment of function foo is a closure.

A function doesn’t have to return in order to create a closure. Simply by virtue of its declaration, every function closes over its enclosing lexical environment, forming a closure.

function foo(x) {
  var tmp = 3;

  return function (y) {
    console.log(x + y + (++tmp)); // will also log 16
  }
}

var bar = foo(2);
bar(10); // 16
bar(10); // 17
Enter fullscreen mode Exit fullscreen mode

The above function will also log 16 because the code inside bar can still refer to the argument x and variable tmp, even though they are no longer directly in scope.

However, since tmp is still hanging around inside bar‘s closure, it is available to be incremented. It will be incremented each time you call bar.

The simplest example of a closure is this:

var a = 10;

function test() {
  console.log(a); // will output 10
  console.log(b); // will output 6
}
var b = 6;
test();
Enter fullscreen mode Exit fullscreen mode

When a JavaScript function is invoked, a new execution context ec is created. Together with the function arguments and the target object, this execution context also receives a link to the lexical environment of the calling execution context, meaning the variables declared in the outer lexical environment (in the above example, both a and b) are available from ec.

Every function creates a closure because every function has a link to its outer lexical environment.

Note that variables themselves are visible from within a closure, not copies.

4. What does “use strict” do in JavaScript, and what is the reasoning behind it?

Answer:

To quote some interesting parts:

Strict Mode is a new feature in ECMAScript 5 that allows you to place a program, or a function, in a “strict” operating context. This strict context prevents certain actions from being taken and throws more exceptions.

And Strict mode helps out in a couple of ways:

  • It catches some common coding bloopers, throwing exceptions.
  • It prevents or throws errors when relatively “unsafe” actions are taken (such as gaining access to the global object).
  • It disables features that are confusing or poorly thought out.

Also, note that you can apply “strict mode” to the whole file or you can use it only for a specific function.

// Non-strict code...

(function(){
  "use strict";

  // Define your library strictly...
})();

// Non-strict code... 
Enter fullscreen mode Exit fullscreen mode

Which might be helpful if you have to mix old and new code.

So, it’s a bit like the "use strict" you can use in Perl. It helps you make fewer errors, by detecting more things that could lead to breakages.

Strict mode is now supported by all major browsers.

Inside native ECMAScript modules (with import and export statements) and ES6 classes, strict mode is always enabled and cannot be disabled.

Alternative Answer:

It’s a new feature of ECMAScript 5.

It’s just a string you put in your JavaScript files (either at the top of your file or inside of a function) that looks like this:

"use strict";
Enter fullscreen mode Exit fullscreen mode

Putting it in your code now shouldn’t cause any problems with current browsers as it’s just a string. It may cause problems with your code in the future if your code violates the pragma. For instance, if you currently have foo = "bar" without defining foo first, your code will start failing which is a good thing in our opinion.

5. How to check whether a string contains a substring in JavaScript?

Answer:

ECMAScript 6 introduced String.prototype.includes:

const string = "foo";
const substring = "oo";

console.log(string.includes(substring));
Enter fullscreen mode Exit fullscreen mode

includes doesn’t have Internet Explorer support, though. In ECMAScript 5 or older environments, use String.prototype.indexOf, which returns -1 when a substring cannot be found:

var string = "foo";
var substring = "oo";

console.log(string.indexOf(substring) !== -1);
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

There is a String.prototype.includes in ES6:

"potato".includes("to");
> true
Enter fullscreen mode Exit fullscreen mode

Note that this does not work in Internet Explorer or some other old browsers with no or incomplete ES6 support. To make it work in old browsers, you may wish to use a transpiler like Babel, a shim library like es6-shim, or this polyfill from MDN:

if (!String.prototype.includes) {
  String.prototype.includes = function(search, start) {
    'use strict';
    if (typeof start !== 'number') {
      start = 0;
    }

    if (start + search.length > this.length) {
      return false;
    } else {
      return this.indexOf(search, start) !== -1;
    }
  };
}
Enter fullscreen mode Exit fullscreen mode

6. var functionName = function() {} vs function functionName() {}

Answer:

The difference is that functionOne is a function expression and so only defined when that line is reached, whereas functionTwo is a function declaration and is defined as soon as its surrounding function or script is executed (due to hoisting).

For example, a function expression:

// TypeError: functionOne is not a function
functionOne();

var functionOne = function() {
  console.log("Hello!");
};
Enter fullscreen mode Exit fullscreen mode

And, a function declaration:

// Outputs: "Hello!"
functionTwo();

function functionTwo() {
  console.log("Hello!");
}
Enter fullscreen mode Exit fullscreen mode

Historically, function declarations defined within blocks were handled inconsistently between browsers. Strict mode (introduced in ES5) resolved this by scoping function declarations to their enclosing block.

'use strict';    
{ // note this block!
  function functionThree() {
    console.log("Hello!");
  }
}
functionThree(); // ReferenceError
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

function abc(){} is scoped too — the name abc is defined in the scope where this definition is encountered. Example:

function xyz(){
  function abc(){};
  // abc is defined here...
}
// ...but not here
Enter fullscreen mode Exit fullscreen mode

Secondly, it is possible to combine both styles:

var xyz = function abc(){};
Enter fullscreen mode Exit fullscreen mode

xyz is going to be defined, as usual, abc is undefined in all browsers but Internet Explorer does not rely on it being defined. But it will be defined inside its body:

var xyz = function abc(){
  // xyz is visible here
  // abc is visible here
}
// xyz is visible here
// abc is undefined here
Enter fullscreen mode Exit fullscreen mode

If you want to alias functions on all browsers, use this kind of declaration:

function abc(){};
var xyz = abc;
Enter fullscreen mode Exit fullscreen mode

In this case, both xyz and abc are aliases of the same object:

console.log(xyz === abc); // prints "true"
Enter fullscreen mode Exit fullscreen mode

One compelling reason to use the combined style is the “name” attribute of function objects (not supported by Internet Explorer). Basically when you define a function like

function abc(){};
console.log(abc.name); // prints "abc"
Enter fullscreen mode Exit fullscreen mode

its name is automatically assigned. But when you define it like

var abc = function(){};
console.log(abc.name); // prints ""
Enter fullscreen mode Exit fullscreen mode

its name is empty — we created an anonymous function and assigned it to some variable.

Another good reason to use the combined style is to use a short internal name to refer to itself while providing a long non-conflicting name for external users:

// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
  // Let it call itself recursively:
  shortcut(n - 1);
  // ...
  // Let it pass itself as a callback:
  someFunction(shortcut);
  // ...
}
Enter fullscreen mode Exit fullscreen mode

In the example above we can do the same with an external name, but it’ll be too unwieldy (and slower).

(Another way to refer to itself is to use arguments.callee, which is still relatively long, and not supported in the strict mode.)

Deep down, JavaScript treats both statements differently. This is a function declaration:

function abc(){}
Enter fullscreen mode Exit fullscreen mode

abc here is defined everywhere in the current scope:

// We can call it here
abc(); // Works

// Yet, it is defined down there.
function abc(){}

// We can call it again
abc(); // Works
Enter fullscreen mode Exit fullscreen mode

Also, it hoisted through a return statement:

// We can call it here
abc(); // Works
return;
function abc(){}
Enter fullscreen mode Exit fullscreen mode

This is a function expression:

var xyz = function(){};
Enter fullscreen mode Exit fullscreen mode

xyz here is defined from the point of assignment:

// We can't call it here
xyz(); // UNDEFINED!!!

// Now it is defined
xyz = function(){}

// We can call it here
xyz(); // works
Enter fullscreen mode Exit fullscreen mode

Function declaration vs. function expression is the real reason why there is a difference.

Fun fact:

var xyz = function abc(){};
console.log(xyz.name); // Prints "abc"
Enter fullscreen mode Exit fullscreen mode

Personally, we prefer the “function expression” declaration because this way we can control the visibility. When we define the function like

var abc = function(){};
Enter fullscreen mode Exit fullscreen mode

We know that we defined the function locally. When we define the function like

abc = function(){};
Enter fullscreen mode Exit fullscreen mode

We know that we defined it globally providing that we didn’t define abc anywhere in the chain of scopes. This style of the definition is resilient even when used inside eval(). While the definition

function abc(){};
Enter fullscreen mode Exit fullscreen mode

depends on the context and may leave you guessing where it is actually defined, especially in the case of eval() — the answer is it depends on the browser.

7. How to remove a property from a JavaScript object?

Answer:

You can do as shown below:

delete myObject.regex;
// or,
delete myObject['regex'];
// or,
var prop = "regex";
delete myObject[prop];
Enter fullscreen mode Exit fullscreen mode

Demo

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};
delete myObject.regex;

console.log(myObject);
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

Objects in JavaScript can be thought of as maps between keys and values. The delete operator is used to remove these keys, more commonly known as object properties, one at a time.

var obj = {
  myProperty: 1    
}
console.log(obj.hasOwnProperty('myProperty')) // true
delete obj.myProperty
console.log(obj.hasOwnProperty('myProperty')) // false
Enter fullscreen mode Exit fullscreen mode

The delete operator does not directly free memory, and it differs from simply assigning the value of null or undefined to a property, in that, the property itself is removed from the object. Note that if the value of a deleted property was a reference type (an object), and another part of your program still holds a reference to that object, then that object will, of course, not be garbage collected until all references to it have disappeared.

delete will only work on properties whose descriptor marks them as configurable.

8. Which equals operator (== vs ===) should be used in JavaScript comparisons?

Answer:

The strict equality operator (===) behaves identically to the abstract equality operator (==) except no type conversion is done, and the types must be the same to be considered equal.

Reference: Javascript Tutorial: Comparison Operators

The == operator will compare for equality after doing any necessary type conversions. The === operator will not do the conversion, so if two values are not the same type === will simply return false. Both are equally quick.

JavaScript has two sets of equality operators: === and !==, and their evil twins == and !=. The good ones work the way you would expect. If the two operands are of the same type and have the same value, then === produces true and !== produces false. The evil twins do the right thing when the operands are of the same type, but if they are of different types, they attempt to coerce the values. The rules by which they do that are complicated and unmemorable. These are some of the interesting cases:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true
Enter fullscreen mode Exit fullscreen mode

Equality Comparison Table

The lack of transitivity is alarming. Our advice is to never use the evil twins. Instead, always use === and !==. All of the comparisons just shown produce false with the === operator.

For reference types == and === act consistently with one another (except in a special case).

var a = [1,2,3];
var b = [1,2,3];

var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };

var e = "text";
var f = "te" + "xt";

a == b            // false
a === b           // false

c == d            // false
c === d           // false

e == f            // true
e === f           // true
Enter fullscreen mode Exit fullscreen mode

The special case is when you compare a literal with an object that evaluates to the same literal, due to its toString or valueOf method. For example, consider the comparison of a string literal with a string object created by the String constructor.

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false
Enter fullscreen mode Exit fullscreen mode

Here the == operator is checking the values of the two objects and returning true, but the === is seeing that they’re not the same type and returning false. Which one is correct? That really depends on what you’re trying to compare. Our advice is to bypass the question entirely and just don’t use the String constructor to create string objects.

Alternative Answer:

Using the == operator (Equality)

true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2;  //true, because "2" is converted to 2 and then compared
Enter fullscreen mode Exit fullscreen mode

Using the === operator (Identity)

true === 1; //false
"2" === 2;  //false
Enter fullscreen mode Exit fullscreen mode

This is because the equality operator == does type coercion, meaning that the interpreter implicitly tries to convert the values before comparing.

On the other hand, the identity operator === does not do type coercion, and thus does not convert the values when comparing, and is, therefore, faster (as according to This JS benchmark test) as it skips one step.

9. What is the most efficient way to deep clone an object in JavaScript?

Answer:

Native deep cloning

It’s called “structured cloning”, works experimentally in Node 11 and later, and hopefully will land in browsers.

Fast cloning with data loss – JSON.parse/stringify

If you do not use Dates, functions, undefined, Infinity, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, sparse Arrays, Typed Arrays or other complex types within your object, a very simple one-liner to deep clone an object is:

JSON.parse(JSON.stringify(object))

const a = {
  string: 'string',
  number: 123,
  bool: false,
  nul: null,
  date: new Date(),  // stringified
  undef: undefined,  // lost
  inf: Infinity,  // forced to 'null'
  re: /.*/,  // lost
}
console.log(a);
console.log(typeof a.date);  // Date object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
console.log(typeof clone.date);  // result of .toISOString()
Enter fullscreen mode Exit fullscreen mode

Reliable cloning using a library

Since cloning objects is not trivial (complex types, circular references, function, etc.), most major libraries provide a function to clone objects. Don’t reinvent the wheel – if you’re already using a library, check if it has an object cloning function. For example,

  • lodash – cloneDeep; can be imported separately via the lodash.clonedeep module and is probably your best choice if you’re not already using a library that provides a deep cloning function
  • AngularJS – angular.copy
  • jQuery – 1jQuery.extend(true, { }, oldObject)1; 1.clone()1 only clones DOM elements

ES6

For completeness, note that ES6 offers two shallow copy mechanisms: Object.assign() and the spread syntax. which copies values of all enumerable own properties from one object to another. For example:

var A1 = {a: "2"};
var A2 = Object.assign({}, A1);
var A3 = {...A1};  // Spread Syntax
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

Check out this benchmark: http://jsben.ch/#/bWfk9

In our previous tests where speed was a main concern we found

JSON.parse(JSON.stringify(obj))
Enter fullscreen mode Exit fullscreen mode

to be the slowest way to deep clone an object (it is slower than jQuery.extend with deep flag set true by 10-20%).

jQuery.extend is pretty fast when the deep flag is set to false (shallow clone). It is a good option, because it includes some extra logic for type validation and doesn’t copy over undefined properties, etc., but this will also slow you down a little.

If you know the structure of the objects you are trying to clone or can avoid deep nested arrays you can write a simple for (var i in obj) loop to clone your object while checking hasOwnProperty and it will be much much faster than jQuery.

Lastly if you are attempting to clone a known object structure in a hot loop you can get much much more performance by simply in-lining the cloning procedure and manually constructing the object.

JavaScript trace engines suck at optimizing for..in loops and checking hasOwnProperty will slow you down as well. Manual clone when speed is an absolute must.

var clonedObject = {
  knownProp: obj.knownProp,
  ..
}
Enter fullscreen mode Exit fullscreen mode

Beware using the JSON.parse(JSON.stringify(obj)) method on Date objects – JSON.stringify(new Date()) returns a string representation of the date in ISO format, which JSON.parse() doesn’t convert back to a Date object. See this answer for more details.

Additionally, please note that in Chrome 65 at least, native cloning is not the way to go. According to JSPerf, performing native cloning by creating a new function is nearly 800x slower than using JSON.stringify which is incredibly fast all the way across the board.

Update for ES6

If you are using Javascript ES6 try this native method for cloning or shallow copy.

Object.assign({}, obj);
Enter fullscreen mode Exit fullscreen mode

10. How to include a JavaScript file in another JavaScript file?

Answer:

The old versions of JavaScript had no import, include, or require, so many different approaches to this problem have been developed.

But since 2015 (ES6), JavaScript has had the ES6 modules standard to import modules in Node.js, which is also supported by most modern browsers.

For compatibility with older browsers, build tools like Webpack and Rollup and/or transpilation tools like Babel can be used.

ES6 Modules

ECMAScript (ES6) modules have been supported in Node.js since v8.5, with the --experimental-modules flag, and since at least Node.js v13.8.0 without the flag. To enable “ESM” (vs. Node.js’s previous CommonJS-style module system [“CJS”]) you either use "type": "module" in package.json or give the files the extension .mjs. (Similarly, modules written with Node.js’s previous CJS module can be named .cjs if your default is ESM.)

Using package.json:

{
    "type": "module"
}
Enter fullscreen mode Exit fullscreen mode

Then module.js:

export function hello() {
  return "Hello";
}
Enter fullscreen mode Exit fullscreen mode

Then main.js:

import { hello } from './module.js';
let val = hello();  // val is "Hello";
Enter fullscreen mode Exit fullscreen mode

Using .mjs, you’d have module.mjs:

export function hello() {
  return "Hello";
}
Enter fullscreen mode Exit fullscreen mode

Then main.mjs:

import { hello } from './module.mjs';
let val = hello();  // val is "Hello";
Enter fullscreen mode Exit fullscreen mode

ECMAScript modules in browsers

Browsers have had support for loading ECMAScript modules directly (no tools like Webpack required) since Safari 10.1, Chrome 61, Firefox 60, and Edge 16. Check the current support at caniuse. There is no need to use Node.js’ .mjs extension; browsers completely ignore file extensions on modules/scripts.

<script type="module">
  import { hello } from './hello.mjs'; // Or it could be simply `hello.js`
  hello('world');
</script>
Enter fullscreen mode Exit fullscreen mode
// hello.mjs -- or it could be simply `hello.js`
export function hello(text) {
  const div = document.createElement('div');
  div.textContent = `Hello ${text}`;
  document.body.appendChild(div);
}
Enter fullscreen mode Exit fullscreen mode

Read more at https://jakearchibald.com/2017/es-modules-in-browsers/

Dynamic imports in browsers

Dynamic imports let the script load other scripts as needed:

<script type="module">
  import('hello.mjs').then(module => {
      module.hello('world');
    });
</script>
Enter fullscreen mode Exit fullscreen mode

Read more at https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js require

The older CJS module style, still widely used in Node.js, is the module.exports/require system.

// mymodule.js
module.exports = {
   hello: function() {
      return "Hello";
   }
}
Enter fullscreen mode Exit fullscreen mode
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"
Enter fullscreen mode Exit fullscreen mode

There are other ways for JavaScript to include external JavaScript contents in browsers that do not require preprocessing.

AJAX Loading

You could load an additional script with an AJAX call and then use eval to run it. This is the most straightforward way, but it is limited to your domain because of the JavaScript sandbox security model. Using eval also opens the door to bugs, hacks, and security issues.

Fetch Loading

Like Dynamic Imports, you can load one or many scripts with a fetch call using promises to control order of execution for script dependencies using the Fetch Inject library:

fetchInject([
  'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
  console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})
Enter fullscreen mode Exit fullscreen mode

jQuery Loading

The jQuery library provides loading functionality in one line:

$.getScript("my_lovely_script.js", function() {
   alert("Script loaded but not necessarily executed.");
});
Enter fullscreen mode Exit fullscreen mode

Dynamic Script Loading

You could add a script tag with the script URL into the HTML. To avoid the overhead of jQuery, this is an ideal solution.

The script can even reside on a different server. Furthermore, the browser evaluates the code. The <script> tag can be injected into either the web page <head>, or inserted just before the closing </body> tag.

Here is an example of how this could work:

function dynamicallyLoadScript(url) {
    var script = document.createElement("script");  // create a script DOM node
    script.src = url;  // set its src to the provided URL

    document.head.appendChild(script);  // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
}
Enter fullscreen mode Exit fullscreen mode

This function will add a new <script> tag to the end of the head section of the page, where the src attribute is set to the URL which is given to the function as the first parameter.

Both of these solutions are discussed and illustrated in JavaScript Madness: Dynamic Script Loading.

Detecting when the script has been executed

Now, there is a big issue you must know about. Doing that implies that you remotely load the code. Modern web browsers will load the file and keep executing your current script because they load everything asynchronously to improve performance. (This applies to both the jQuery method and the manual dynamic script loading method.)

It means that if you use these tricks directly, you won’t be able to use your newly loaded code the next line after you asked it to be loaded, because it will be still loading.

For example: my_lovely_script.js contains MySuperObject:

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined
Enter fullscreen mode Exit fullscreen mode

Then you reload the page hitting F5. And it works! Confusing.

So what to do about it?

You can put all the code using the remote library in the callback function. For example:

function loadScript(url, callback)
{
    // Adding the script tag to the head as suggested before
    var head = document.head;
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Then bind the event to the callback function.
    // There are several events for cross browser compatibility.
    script.onreadystatechange = callback;
    script.onload = callback;

    // Fire the loading
    head.appendChild(script);
}
Enter fullscreen mode Exit fullscreen mode

Then you write the code you want to use after the script is loaded in a lambda function:

var myPrettyCode = function() {
   // Here, do whatever you want
};
Enter fullscreen mode Exit fullscreen mode

Then you run all that:

loadScript("my_lovely_script.js", myPrettyCode);
Enter fullscreen mode Exit fullscreen mode

Note that the script may execute after the DOM has loaded, or before, depending on the browser and whether you included the line script.async = false;. There’s a great article on Javascript loading in general which discusses this.

Source Code Merge/Preprocessing

As mentioned at the top of this answer, many developers use build/transpilation tool(s) like Parcel, Webpack, or Babel in their projects, allowing them to use upcoming JavaScript syntax, provide backward compatibility for older browsers, combine files, minify, perform code-splitting etc.

Alternative Answer:

If you are looking for something more advanced, try out RequireJS. You’ll get added benefits such as dependency management, better concurrency, and avoid duplication (that is, retrieving a script more than once).

You can write your JavaScript files in “modules” and then reference them as dependencies in other scripts. Or you can use RequireJS as a simple “go get this script” solution.

Example:

Define dependencies as modules:

some-dependency.js

define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {

     //Your actual script goes here.   
     //The dependent scripts will be fetched if necessary.

     return libraryObject;  //For example, jQuery object
});
Enter fullscreen mode Exit fullscreen mode

implementation.js is your “main” JavaScript file that depends on some-dependency.js

require(['some-dependency'], function(dependency) {

    //Your script goes here
    //some-dependency.js is fetched.   
    //Then your script is executed
});
Enter fullscreen mode Exit fullscreen mode

Excerpt from the GitHub README:

RequireJS loads plain JavaScript files as well as more defined modules. It is optimized for in-browser use, including in a Web Worker, but it can be used in other JavaScript environments, like Rhino and Node. It implements the Asynchronous Module API.

RequireJS uses plain script tags to load modules/files, so it should allow for easy debugging. It can be used simply to load existing JavaScript files, so you can add it to your existing project without having to re-write your JavaScript files.

In Conclusion

These are the 10 most commonly asked questions about JavaScript. If you have any suggestions or any confusion, please comment below. If you need any help, we will be glad to help you.

We, at Truemark, provide services like web and mobile app development, digital marketing, and website development. So, if you need any help and want to work with us, please feel free to contact us.

Hope this article helped you.

Original Source: DevPostbyTruemark

Top comments (0)