Last active
December 19, 2018 06:40
-
-
Save mrstalon/4f07f21c12b2020cf1ff4c73e10a9639 to your computer and use it in GitHub Desktop.
Some confusing and interesting topics/tasks to consider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 1) Explain why the following doesn't work as an IIFE: function foo(){ }(); | |
//What needs to be changed to properly make it an IIFE? | |
// solution & explanation | |
// IIFE - Immediately-Invoked Function Expressions | |
// The problem here is that only Function Expressions can be invoked immediately | |
function foo() { | |
console.log('foo is invoked'); | |
}(); // SyntaxError: Unexpected token ( | |
// Because we have Function Declaration which can't be immediately invoked. | |
// 1) If parses sees function keyword it treats it as a Function Declaration | |
// 2) If parses sees function keyword as a part of some expression it treats it as a Function Expression | |
// Examples of Function Expressions | |
const fn = function () {}; | |
true===function() {}; | |
+function() {}; | |
(function() {}); | |
// That is why, any of these FE can be immediately invoked | |
const fn = function () { | |
console.log('invoked!'); // invoked! | |
}(); | |
+function() { | |
console.log('invoked!'); // invoked! | |
}(); | |
(function() { | |
console.log('invoked!'); // invoked! | |
})(); | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// 2) What's the difference between a variable that is: undefined or undeclared? | |
// An undeclared variable, is a variable that was not priveously declared with var, let or const keywords. | |
// When you assign some value to undeclared variable, this variable will be defined globally. | |
// ( In 'use strict' usage of undeclared variable will bring you to Reference Error ) | |
function fn() { | |
a = 5; // a soon as a variable wasn't declared before assignment, it will be defined globally | |
} | |
fn(); | |
console.log(a); // 5 | |
// In this example, even if there is a variable in outter scope of fn function | |
// a = 5 will reassign this outter variable | |
let a = 3; | |
function fn() { | |
a = 5; // a soon as a variable wasn't declared in this scope before assignment, it will reassign global variable | |
} | |
fn(); | |
console.log(a); // 5, cause a inside fn reassigned global a | |
// A variable that is undefined is a variable that was declared, but no value was assigned to it. | |
let a; // no value was assigned | |
console.log(a); // undefined | |
console.log(a === undefined); // true | |
console.log(typeof a === 'undefined'); // true | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// 3) What's a typical use case for anonymous functions? | |
// Anonymous functions are functions that are dynamically declared at runtime. | |
// They’re called anonymous functions because they aren’t given a name in the same way as normal functions. | |
// An anonymous function can be: | |
// 1. Usual-type | |
function() {}; | |
// 2. Arrow-type | |
() => {}; | |
// They can be used in various examples: | |
// 1. As a part of IIFE, for example when using "Module Pattern" | |
let number = (function () { | |
return 1; | |
}()); | |
console.log(number); // 1 | |
// 2. As an argument for High-Order-Functions (forEach, map, filter, ...) | |
const array = [1, 2, 3]; | |
const doubledArray = array.map((item) => item * 2); | |
console.log(doubledArray); // [2, 4, 6], everything works fine! | |
// or as a returned value of High-Order-Functions | |
const sum = (a) => (b) => a + b; // sum() will return anonymous function | |
console.log(sum(1)(5)); // 6, everything works fine | |
// 3. As callbacks for events, requests, timeouts and etc... | |
element.addEventListener('click', (e) => { | |
console.log('clicked'); | |
}); | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// 4) Object Categories | |
// There are three categories of Objects in JavaScript: | |
// Native objects, Host objects, user-defined objects. | |
// 1. Native objects are those objects supplied by JavaScript ( String, Number, Array, Image, Date, Math, etc...) | |
// 2. Host objects are objects that are supplied to JavaScript by the browser environment ( window, document, forms, etc...) | |
// 3. User-defined objects are those that are defined by you, the programmer. | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// 5) How to write a function F, so that new F === F? | |
// Firstly, what a hell is invoking function with new keyword? | |
// new keyword means that a function is called as a constructor | |
// By default, constructors just assign props and methods to this | |
// And then, this will be automatically returned | |
function F(a) { | |
this.a = a; | |
} | |
let obj = new F(5); | |
console.log(obj); // logs { a: 5 } to the console. | |
// As we thought before, this is autometically returned. | |
// But what if we want to return something instead of this? How to get rid of this "default behavior"? | |
// Well, there are two ways how JS treats with return statement inside a constructor function: | |
// 1. If return is called with object, then it is returned instead of this. | |
// 2. If return is called with a primitive, it’s ignored. | |
// Primitive example: | |
function F(a) { | |
this.a = a; | |
return 5; // will be ignored and this will be returned | |
} | |
let obj = new F(5); | |
console.log(obj); // logs { a: 5 } to the console | |
// Object example: | |
function F(a) { | |
this.a = a; | |
return {}; // won't be ignored and will return empty object instead of this | |
} | |
let obj = new F(5); | |
console.log(obj); // logs {} to the console | |
// Now, when we know how constructor function and this keyword works | |
// Let's get back to the main question, shall we? | |
// Notice, that F contains just reference to the function. In order to get true from (new F === F) | |
// We need to return function itself inside constructor (instead of default this) | |
function F() { | |
console.log(F instanceof Object); // true, since any function is inhereted from Object.prototype | |
return F; // that is why this return won't be ignored and F will be returned | |
} | |
console.log(new F === F); // logs true, cause reference to F === reference to F | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// 6) What is the difference between "==" and "===" operators? | |
// https://stackoverflow.com/questions/523643/difference-between-and-in-javascript | |
// --------------------------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------------- | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment