MaryRichelle / weird-JavaScript

JavaScript tricky /weird snippets and explanation

Home Page:https://maryrichelle.github.io/weird-JavaScript/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Weird πŸ™„ behavior of Coolest JavaScript

The trickier it gets, the more interesting it becomes, and the more I love it.

When you're convinced you understand it, but it still finds new ways to surprise you and force you to say that's weird πŸ™„

$=_=>`$=${$};$()`;$()  // '$=_=>`$=${$};$()`;$()' that's weird πŸ™„
($=_=>`$=${$};$()`)()  // '$=_=>`$=${$};$()`;$()' 
typeof '$=_=>`$=${$};$()`;$()' // 'string' 

Function Prints itself
lets break it down

  • $ ==> variable declaration $ (but not allowed in 'strict mode without let ,const or var)
  • = ===> assignment operator to assign a left hand side(aka target) a value
  • _=> ===>arrow function with no parameters (valid in js)
  • `$=${$};$()` ===> template literals string inside
  • ${$} ===> calling $ variable (which is function itself) in side template literals
  • $(): ===> lastly calling(invoking) $ function like this $()
    NOTE don't confuse it with recursion though function is calling itself

The most lovely one ⬇️ BaNaNa

"B" + "a" + +"a" + "a"; // -> 'BaNaNa'
  • string concatenation with + operator and typeof "string"
  • +"a" ===> Number("a") // NaN unary plus operator converts its operand to a number

1+2+3+4+5+6+7  // 28
1+2+"3"+4+"5"+6+ +7; // -> '334567' //string value type
"1"+2+"3"+4+"5"+6+ +7 // '1234567' //string value type

!!"false" == !!"true"; // -> true
!!"false" === !!"true"; // -> true
!!false == !!true // false
!!"false" == !!false;// true

break it down
!!"false"
1: the unary ! negate operator explicitly coerces a value to a boolean. Boolean("false"); // true
2: !"false" which is false because "false" is a string and a truthy value (but not a boolean false) and !(truthy value) is false
3: !false ===> true
4: thus true === true // true


var amount = 42
console.log(amount)

why its weird 😡

  • console.log(......) command has to implicitly coerce the number 42 value to a string value type to print it 42

const objWithNoPrototype = Object.create(null)
console.log(objWithNoPrototype)
 // {}
No properties
  • Object.create(null) creates a new object with null as its prototype
  • so when we try to access any property, it will be undefined because this object don't have properties and prototypes
  • only object that don't have prototype

b *2

why its weird 😡 a standalone expression statement is not very useful and common as it will not have any effect on running the program it would retrieve the value of of b and multiply it by 2 but than wouldn't do anything with the result. which means javascript will run line by line will execute this expression and move to next line but if we want to use it we can store it in a variable and use it (that's weird πŸ™„)


  typeof null // "object"
  typeof NaN // "number"

why its weird 😡?
typeof null is "object" (that's weird πŸ™„) even null is primitive value but typeof null is object


console.log(z) // ReferenceError: z is not defined
typeof z; // "undefined"

The typeof operator returns "undefined" even for β€œundeclared” ( β€œnot defined”) variables. (that's weird πŸ™„)


Numbers / Floating Points

0 === -0 // true
0 > -0 // false
-0 + "" // 0
0 + "" === -0 + "" // true
typeof 42.0 // number ===> there is only 7 type of values in js number is one of them 
999999999999999 // 999999999999999 ==> double-precision floating-point format 
9999999999999999 // ===>10000000000000000
1 === 1.01 // false
1 === 1.000000000000001 // false 
1 === 1.0000000000000001// true (that's weird πŸ™„ 😭) 
0o363 === 0O363; // true (that's weird πŸ™„ ) they say javascript is case sensitive 😭 this presentation of numbers is octal base system where we can use Capital "O" or small "o" same  goes for other base systems
013 === 11 // true
0o13 === 11 //true
013 === 0o13 === 11 // false
013 === 0o13 // false
Infinity - Infinity // NaN
infinity / infinity // NaN
Number.isInteger( 42 );     // true
Number.isInteger( 42.000 ); // true
Number.isInteger( 42.3 );   // false
42.toFixed(3) // SyntaxError here . is property accessor
42 .toFixed(3) // "42.000" with space 
42..toFixed(3) // "42.000"
console.log(1..toString() === "1");// true (that's weird πŸ™„)

why its weird 😡?

  • floating point 1.0
  • first . is for floating point 1.0
  • second . for property accessor .toString()/.toFixed(3)

0.5+0.1 === 0.6 // true
0.2+0.1 === 0.3 // false  

the representations for 0.1 and 0.2 in binary floating point are not exact, so when they are added, the result is not exactly 0.3. It’s really close, 0.30000000000000004


const aFloatingPoint = 5.99;
const floatingToFixed = aFloatingPoint.toFixed(2)
console.log(typeof aFloatingPoint) // "number" 
console.log(typeof floatingToFixed) // "string" 

const num = () =>{
return 9;
};

console.log(num() < 10); // true

num function returns 9 which is less than 10


const value = "123abc";
const result = Number(value);

console.log(typeof result);// "number" 

function fun(a, b, c) {
return b + c
}
fun(5, 3, "wowwwwww", "this is so cool") // '3wowwwwww' string concatenation 

  • javascript work on the right side of = assignment operator and then assign that value to left hand side(technically not accurate)
    but the thing under the hood is this is because of the assignment operator associativity this binary operator have right to left associativity.
console.log(-4 + 3 + "8") // 18 -1 + "8" === 18 - have higher precedence
console.log("A" - 1); // NaN
console.log(2 + "-2" + "2"); // 2-22
console.log("Hello" - "World" + 78); //NaN ==>  "Hello" - "World" (trying to subtract strings) + 78 NaN
console.log("Hello" + "78"); "Hello78"
console.log(5 + "5"); // "55"  + operator number is coerced to string 
console.log(5 - "5"); // 0 ==> - operator string coerced to number 
console.log("5" * "5"); // 25 ==> * operator string coerced to number 
console.log("5" / "5"); // 1 = / operator string coerced to number 
console.log(5 + +"5") // 10 ==> unary plus have higher Precedence than addition operator so its grouped 1st {5 + (+"5")} and unary plus operator coerce string to number thank addition operator left to right associativity add them together
console.log("5" - - "5"); // 10 unary minus (-"5") ==> 5 + 5
Math.min()// Infinity
Math.max()// -Infinity
!typeof "name" === "object" // false ==> !(typeof "name") === "object" ! operator have higher precedence than === than (!"string") negate truthy value 'string" to false and false !== "object" so the out put is false 
true + true + true// 3 ==> because of + operator true becomes 1 
true - true // 0  ==> 1 - 1 = 0
//TODO πŸ‘‡
(!+[]+[]+![]) // 'truefalse' TODO
(!+[]+[]+![]).length // 9

let x = 9;
let y = x++; // y= 9 x= 10 (that's weird πŸ™„) postfix increment operator
console.log({x}) // 10
console.log({y}) // 9
let z = ++x// 11
console.log({x}) // 11
console.log({z}) // 11
console.log(z * y) ; // 11* 9 (that's weird πŸ™„) prefix increment operator

why its weird 😡?

  • x++ the postfix increment operator increments and returns the value before incrementing. it return x first and than increment it on line let y = x++ x current value is returned and assigned to y and than it increment
  • ++x the prefix increment operator increments and returns the value after incrementing. x is increment before its value is return

let a = 5;
let b = a++; //a = 6, b= 5 (that's weird πŸ™„)
let c = ++a; // a = 7, c = 7 (that's weird πŸ™„)

let result = a + b + c; // 19

console.log(result);

console.log(4 + (5 - - 4) - - 5)// 18 

// Operator precedence 1:(5 - - 4) => 5 +4 => 9 () grouping have hight precedence ⬇️ 2: 4 + 9 => 13
3: 13 - - 5 => 13 + 5 => 18


console.log([10]+[10]); // "1010"
console.log([10]+[10,10]); //'1010,10'
console.log([1, 2] + [3, 4]);// '1,23,4' 

why its weird 😡?

because of + operator array are coerced to strings "10" , "10,10" (that's weird πŸ™„)


let x=10 ; 
let y='hello';
let z = Number('5'+x) 
console.log(z , typeof z]);//  output : 510 "number"(that's weird πŸ™„)
console.log(`The result ${y} and`+ false); // 'The result hello andfalse'

why its weird 😡? string concatenation because of + operator with typeof number and string accordingly


function display()  {  
  console.log("10"+(20+30));  // "1050" Operator precedence for () 
  console.log("10"+20+30); // "102030"
  console.log(10+20+"30") // "3030"

}  
display();  

why its weird 😡?
because + have left to right Associativity string concatenation and 1: () grouping Operator precedence 2: + operator


(function() {
    return +(new Date())
})(); 

(function() {
    return ''+(new Date());
})();

logical not

!!null; // false ===> null falsy value ===> !false // true 
!!''; // false 
!!1; // 1 is truthy 

!!null; // false starting from left side

  • ===> null falsy value
  • ===> !false // true
  • ===> !true // false

logical && and ||

true && true; // true ===> if first test is true print the value of 2nd operand if the first operand is true, go and print th e value of right side operand of && .
true && false; //  false ===> if first test is true print the value of 2nd operand
false && true; // false ===> if first  test is false print the value of 1st operand if the first operand is false, there is no need to evaluate the second operand, as the overall result will be false.
false && false; // false ==> if first  test is false print the value of 1st operand
  
true || true; //   true ===> if the first  test is true prints the value of first operand
true || false; // true ===> if the first  test is true prints the value of first operand
false || true; // true ===> if the first  test is false prints the value of 2nd one operand
false || false; // false ===> if the first  test is false prints the value of 2nd one operand

console.log("555" === 555 || 555 === 555); // true

"555" === 555 is false
555 === 555 is true false || true with || operator when the fist value is false print the value of second operand in our case is "true"


var a = 22
var b = "Mary"
var c = null

a && b // "Mary"
a || b // 22
b && c // null
c || a // 22

a && b if the test is true, the && expression results in the value of the second operand (b).
a || b if the test is true, the || expression results in the value of the first operand
b && c b is true nd javascript prints the value of c which is null
c || a c is falsy so it will print the value of second operand which is a(22)


const array = [1, 2, 3];
let result = 0;
for (const value in array) {
  // console.log(value) 0,1,2,
result += +value; // 3 ==> append operator add 1 to its previous index as its iterating over indexes but ```+value``` +(unary Operator: it covert string to number) didn't make any difference its already a number
}
console.log(result)
function returnStr(){
return console.log("hello world") 
}
function returnTrue(){
return console.log(true)
}
console.log(returnStr() && console.log(true)) // "hello world" "undefined"

console.log(returnStr() && console.log(true)) // "hello world" "undefined" returnStr() first function is called and which return and prints "hello world" as the out of console.log() but the function return undefined and undefined is a falsy value so && operator stops here and prints the value of 1st operand which is undefined


== and === operators

  • string comparison
""*0 === 0 // true 
"1"* 0 === 0 // true

-0 === +0 // true
+0 !== -0 // true
' '===' '  // true
'' == 0 // false
'' == ''// true
false == 0// true
"0" == false // true
false == [] // true
"" == [] // true
0 == [] // true
2 == [2] // true
"" == [null] // true
0 == "\n" // true
"" == 0// true
"\t\r \v\f " == "" // true
  • number comparison
42 == "42" // true ==> with loose equality implicit type coercion happened on one or both value to make of some type "24" coerced to number  
"24" === 24 //false no type coercion
  • boolean comparison
true == 1 // true ==> type coercion 
true === 1 // false
false + 1 === 1 // true with + operator false become 0 hence 0 + 1 
true + 1 === 1 //false
"42" == true // false  ==>  with == boolean converted to numbers (true = 1, false = 0) thus 
"42" == 1 // false ==> == type coercion happens and string  coerce to number
42 == 1 // false ==> values are not same

[!NOTE] Never compare boolean(true or false) any other type of value with ==

  • NaN
NaN == NaN// false
NaN === NaN // false
NaN ** 0 // 1
NaN ** NaN // NaN
"1" == NaN // false
"1" === NaN // false
5 === NaN // false
42 == NaN // false
false === NaN // false
true == NaN // false
NaN !== NaN // false
Number.isNaN(NaN); // true
Number.isNaN("abc"); // false
Number.isNaN({}); // false
Number.isNaN([1]); // false
Number.isNaN(Infinity); // false
Number.isNaN(-Infinity); // false
Number.isNaN(true); // false
Number.isNaN(false); // false
Number.isNaN(null); // false
Number.isNaN(undefined); // false
Number.isNaN(''); // false
Number.isNaN([]); // false
Number.isNaN({}); // false
Number.isNaN(/a/g); // false
{a:1} + {b:2} // NaN
null + undefined // NaN

NaN is never equal to any other value and to it self NaN it will return false
loose equal and strictly equal treats NaN as unequal to every other value

var a = 2 / "foo";      // NaN 
typeof a === "number";  // true
  • Objects/Array comparison
[undefined]===[undefined] //false 
[null]===[] //false
[]==[] //false
[] === [] //false
[] !== [] // true
{}==={} //false
[]+[]=="" // true
[]*1 === 0// true * operator convert [] to primitive "" * 
[1]===[]+1 // false because []+1 results in "1", but it's a string
console.log({} + []); // "[object Object]"
[] == "" // true [] coerce to ""
// ({}) == "[object object]" // false
{} + [] //  0  {} standalone block  than (+ []) is a expression with + [] coerce to 0
[] + {} // "[object Object]" //true [] array are coerce to "" and thus object converted to string "[object Object]"
[5] + [6] === "56" // true // converted to ""
[1, 2] == [1, 2]; // false because it compares by reference not by value
[1, 2].toString() == [1, 2].toString(); // true because we convert them into string before comparing
  let a = []
  let b = []
  console.log(a == b) // false 
  console.log(a === b)// false
  • objects are held by reference both == and === check only if the reference match not the content/value so both are false

undefined'

in non-strict mode πŸ‘‡

let undefined = 5
console.log(undefined) // 5
// in strict mode Identifier 'undefined' has already been declared
function foo(){
var undefined = 2;
console.log(undefined)}
foo(0) // 2
let null = 5 //  Uncaught SyntaxError: Unexpected token 'null'

null

!!null;
null === 0 // false
null == 0 // false
null === null // true
null == null // true
null > 0 // false
null < 0 // false
null >= 0 // true
null <= 0 // true
null === undefined; // false
null == undefined; // true
null === null; // true
null == null; // true
!null; // true 
Number.isNaN(1 + null); // false
Number.isNaN(1 + undefined)

var a = null; 
!a && typeof a === "object"; // true

initially a is null which is falsy value
!a making a true when is true with && operator


// (function() {
//     return (function(){}) === (function(){});
// })();

Implicit Type Coercion

let a = 0;
let b = false;
console.log((a === b));// false ===> type coercion not allowed
console.log((a == b)); //true ===>  
//1 because of == type coercion happen   
//2  boolean coerced to  number but when    
//3 false coerced to number it become 0 and true converted to 1
// but if 
let c  = 41;
console.log((c == b)); // false since c is coerced to 0 (0 == 41)

let a=[]
let b=""
console.log(a==b) // true ==> with == loose equal array are coerced to string

why its weird 😡?
loose equal == converts one or both values to same type and [] is converted to ""


let a = "52";
let b = 52
a === b // false (that's weird πŸ™„)
a ==b // true 
typeof (a==b); // boolean

true because type coercion happens behind the walls javascript tries to convert the type of one of the operand of == operator to match them and a "52" becomes 52

with === the coercion is not allowed


true != 1;  // false (that's weird πŸ™„)  
true !== 1; // true (that's weird πŸ™„)

with Inequality != operator type coercion occurs true becomes 1 and its false !== Strict Inequality operator type coercion is not allowed true and 1 are not same


Hoisting

console.log(x); // undefined
var x = 5;
  • variable declaration (with var keyword)and function declaration(with function keyword) are hoisted in this snippet of code because of hoisting var x (variable declaration ) is taken at the top of the scope where its undefine because its value is not initialized yet and we initialize the value with initializer =

var employeeId = '1234abe';
(function(){
console.log(employeeId);// undefined 
var employeeId = '122345';
})();

why its weird 😡?
inside IIFE it is undefined because of hoisting moves variable at the top of the scope and at the point var employeeId is just declared but not yet initialize (that's weird πŸ™„) yes it didnt go to global scop since it find employeeId inside function scop


  console.log(a) // undefined ===> var a is hoisted in global scop
  var a;
  function foo(){
  console.log(a) // undefined ===> looking in global scop where a is undefined 
  }
  foo()
  a = 1
  console.log(a) // 1

but if

console.log(a) // ReferenceError: a is not defined because of let 
  let a;

var x = 23;
(function(){
var x = 43;

  (function random(){
    // x is hoisted here but undefined
    x++; // undefined++ 
    console.log(x); // NaN 
    var x = 21; // x = 21 initialized
})();

})();

Array and Array Methods

function foo(x) {
x.push( 4 );
x; // [1,2,3,4]
x.length//4 
// later
x.length = 0; // empty existing array in-place
x.push( 4, 5, 6, 7 );
x; // [4,5,6,7]
}
var a = [1,2,3];
a// [1,2,3];
foo( a );
a; // [4,5,6,7] not [1,2,3,4]
const arr = [1, 2, 3];
arr[5] = 6;
console.log(arr.length); //6 with two empty spaces

const arr = [1,2,3,4,5,5,,6]
const a= arr.map((x,y)=> x+y)
 console.log(a)// [ 1, 3, 5, 7, 9, 10, <1 empty item>, 13 ]

function myFun(){
var arrayNumb = [2, 8, 15, 16, 23, 42];
arrayNumb.sort();
console.log(arrayNumb);// [ 15, 16, 2, 23, 42, 8 ] 
const prices = ["a", "b", "f", "e", "d","c"];
prices.sort();
console.log(prices);// ["a","b","c","d","e","f"]
}
myFun()

why its weird 😡?
one that sorts an array in place and sort method with out argument reacts on elements of array as string and sort them in dictionary order (lexicographic ) (that's weird πŸ™„)


let v =[56,67,21,78,(1,2,3),(4,5,6)];
let [a,b,...c]  = v
console.log(c); // [ 21, 78, 3, 6 ]
console.log(a)//56
console.log(b)//67

var greet = 'Hello World';
var toGreet = [].filter.call(greet, function(element, index) {
return index > 5;
});
console.log(toGreet);

a = [1, 2, 3]
b = a // reference to a as array are pass by reference
a = a + [4] // 1,2,34 both a(reference to a) and [4]converted to string and concat
console.log(b) // [1, 2, 3] a was assign to b before it changes it values on a = a + [4]

(that's weird πŸ™„)


 const arr = [1,2,3,4,5,5,,6]
 const a= arr.slice()
 console.log(a) // [ 1, 2, 3, 4, 5, 5, <1 empty item>, 6 ]

let numbers = [1, 2, 3, 4, NaN];
console.log(numbers.indexOf(NaN), typeof numbers[numbers.length-1], number[-1] )// -1 ,"number" 'undefined'

Recursion

function test(x){
if(x > 0){
test(x-1)// Recursion function runs until x > 0 but every time function runs x-1
}
console.log(x)// 0 1 2 3 4 5
}
let data = 5
test(data);

why its weird 😡?


Objects

const props = [
{ id: 1, name: "John"},
{ id: 2, name: "Jack"},
{ id: 3, name: "Tom"}
];
const [, , { name }] = props; 
console.log(name); "Tom"

first two objects are skipped and { id: 3, name: "Tom"} is destructed {name} thus name = Tom


const obj1 = { a: 0 };
const obj2 = Object.assign({}, obj1);

obj1.a = 2;
console.log(obj1, obj2);// { a: 2 } { a: 0 }

why its weird 😡?
obj2 have all the the value of it and add new obj1 so its { a: 0 }
later obj1 value of property a was changed but not in the obj2


const a = {};
const b = { key: 'b' };
const c = { key: 'c' };

a[b] = 123; 
a[c] = 456;

console.log(a[b]);// 456 (that's weird πŸ™„ 😭)

why its weird 😡? in js objects can be passed as a keys to another object but they are coerced to string
==> In a[b] = 123; since b is object it becomes a["object object"]
==> a["object object"] = 123 ==> in a[c] = 456; again a[c] becomes a["object object"]
==> and so a[c] 456 since a["object object"]


let x= {}, y = {name:"Ronny"},z = {name:"John"};
x[z] = {name:"Jene"};
x[y] = {name:"Jenney"};// assigning a property/key y with value {name:"Jenney"} to variable x (which is empty object)    
// x['object Object'] = {name:"Jenney"} OR

console.log(x[y]); // {name:"Jenney"}

1: objects can be used as keys
2: object literals are not copied, they point to same memory location
3: objects coerced to strings when they are passed as keys x[y] becomes x['object Object']

 x = {
  "[object Object]": { name:"Jenney"}
};

in the end, you have an object x with a single property where the key is the string "[object Object]", and its value is {name:"Jenney"}


// TODO ===> need more attention here 
  let hero = {
      powerLevel: 99,
      getPower(){
      return this.powerLevel;
    }
  }
  let powerOfHero = hero.getPower;
  let hero2 = {powerLevel:42};
  console.log(powerOfHero());//undefined
  console.log(powerOfHero.apply(hero2)); //42

  const someFunction = function(){
    console.log(this); //global/ window object 
    const b = {
      func1: function(){
      console.log(this); //b object
      }
  }
  const c = {
    func2: ()=>{
    console.log(this); // window because of arrow function 
    }
  }
  b.func1();
  c.func2();
  }
 someFunction();
var set = new Set();
set.add("+0").add("-0").add(NaN).add(undefined).add(NaN);
console.log(set);
/*Set(4) {  
  '+0',  
  '-0',   
  NaN,  
  undefined   
  }*/

this keyword

function myFunc(){
console.log(this.message);// undefined
}//(that's weird πŸ™„)
myFunc.message = "Hi John";// setting a property to function 
myFunc()

why its weird 😡?
but properties in function are not directly accessible


  const b = {
    name:"John",
    itsFun : function(){
      var self = this;
      console.log(this.name); // "John"

        (function(){
          console.log(this.name); // undefined 
          console.log(self.name); // "John"
        })();

      }
  }
  b.itsFun();

Scope and Closure

function sayHi() {
  return (() => 0)();
}

console.log(typeof sayHi());
for (var i = 1; i <= 5; i++) {
  setTimeout(function timer() {
    console.log(i)///6 6 6 6 6(that's weird πŸ™„)  
  }, i * 1000)
}

because of var i is global
setTimeout because of its async behavior decide to run after i * 1000 time so the for loop started to execute but when its i = 5 code runs condition meet but before the loop ends i++ which is now 6 so in the scope of loop i = 6 and condition false i !<= 5 i = 6 resides in the global scope for setTime out
when set time out run it triggers the i which is 6 for 5 times with execution of loop


  (function(a){
    return (function(){
      console.log(a);// 45 ===> because of Closure inner function have access to parent function
      a = 23;
    })()
  })(45);

// Simpler ⬇️
  function outer(a){
    return function inner(){
    console.log(a)
      a = 23;
      console.log(a)
    }
 }
 const parent = outer(45)
 parent()

function bigFunc() {
  let newArray = new Array(700).fill('β™₯');
  return (element) => newArray[element];
}
let getElement = bigFunc(); // Array is created only once
getElement(599);
getElement(670);
// without Closure ⬇️
  function bigFunc(element){
    let newArray = new Array(700).fill('β™₯');
    return newArray[element];
    }
    console.log(bigFunc(599)); // Array is created on every function call
  console.log(bigFunc(670));

  function randomFunc(){
  for(let i = 0; i <= 5; i++){
    (function(){
        let j = i
      setTimeout(()=>console.log(j),1000)// 0 ,1 , 2 , 3 , 4 ,5
      })()  
    }
  }
 const fun =  randomFunc();
 

  function randomFunc(){
    for(let i = 0; i <=5; i++){
      setTimeout(()=> console.log(i),1000);// 0 ,1 , 2 , 3 , 4 ,5 
    }
  }
  randomFunc();

because of let declaration block scope


async js

setTimeout(()=>{console.log("second")},0)
console.log("first")

"first"
"second" set time out is Asynchronous


console.log("hello");

setTimeout(() => console.log("world"), 0);

console.log("hi");

(that's weird πŸ™„)
"hello"
"hi"
"world"
why its weird 😡? setTimeout is async function and it give space to other code to execute first even it set to 0


function randomFunc(){
for(var i = 0; i < 2; i++){
setTimeout(()=> console.log(i),1000); // 2 ,2
}
}
randomFunc();

var i is global variable when set time out run after the loop it triggers 2 from the value of i before condition false

function someFun(){
setTimeout(()=>{
console.log(x); // 2 
console.log(y); // 12
},3000);
var x = 2;
let y = 12;
}
someFun()

because setTimeout as a async function it give space to rest of the code(as its going to wait for 3`) and entire function executes from top to bottom lets say setTimeout is now before the closing } of someFun and after x and y declaration and initialization


(function(){
setTimeout(()=> console.log(1),2000);
console.log(2);
setTimeout(()=> console.log(3),0);
console.log(4);
})();

output is
2 ===> executes immediately
4 ===> executes immediately
3 ===> runs after 0 seconds had to give place to rest of the code
1 ===> runs after 3 seconds


button.addEventListener("click",()=>{
Promise.resolve().then(()=>console.log("promise"))
console.log("eventListener")
})

1: "eventListener"
2: "promise"


event Delegation

<div onclick="console.log('first div')">
  <div onclick="console.log('second div')">
    <button onclick="console.log('button')">
      Click!
    </button>
  </div>
</div>
<!-- event.stopPropagation -->

button second div
first div When you click a button (or perform any other event-triggering action) in a web page, the browser follows the event propagation phases. The click event goes through the capturing phase, then the target phase (where the actual click occurred), and finally, the bubbling phase.

During the bubbling phase, event listeners attached to the elements involved in the event (including the target and its ancestors) have the opportunity to respond to the event. This is where you can capture the response of the click event by attaching event listeners to relevant elements. technical term of this behavior is called event delegation

Capturing Targeting bubbling
⬇️first div ➑️button Click! ⬆️ button
⬇️second div ⬆️ second div
⬇️button ⬆️ first div

Notice the arrows


(() => {
  let x, y;
  try {
    throw new Error();
  } catch (x) {
    (x = 1), (y = 2);
    console.log(x);
  }
  console.log(x);
  console.log(y);
})();
(![] + [])[+[]] +
  (![] + [])[+!+[]] +
  ([![]] + [][[]])[+!+[] + [+[]]] +
  (![] + [])[!+[] + !+[]];

spread operator

const value = { number: 10 };

const multiply = (x = { ...value }) => {
  console.log((x.number *= 2));
};

multiply();
multiply();
multiply(value);
multiply(value);

Javascript is not yet done......
continue...
(that's weird πŸ™„)


Since you are here and if you find

  • wrong explanation
  • wrong term used
  • typo
  • things are not clear or need more explanation
    Please open a Issue
    or lets open a Discussion

if you find it helpful don't forget to ⭐ the repo

Thanks 😁

About

JavaScript tricky /weird snippets and explanation

https://maryrichelle.github.io/weird-JavaScript/