{"id":23511574,"url":"https://github.com/maryrichelle/weird-javascript","last_synced_at":"2026-02-09T18:32:17.426Z","repository":{"id":191063282,"uuid":"670076174","full_name":"MaryRichelle/weird-JavaScript","owner":"MaryRichelle","description":"JavaScript tricky /weird snippets and explanation ","archived":false,"fork":false,"pushed_at":"2025-02-05T14:33:06.000Z","size":78,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-07T18:21:09.526Z","etag":null,"topics":["javascript","javascript-interview-questions","javascript-quiz","tricky-javascript"],"latest_commit_sha":null,"homepage":"https://maryrichelle.github.io/weird-JavaScript/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MaryRichelle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-24T08:40:26.000Z","updated_at":"2025-02-05T14:33:09.000Z","dependencies_parsed_at":"2023-11-24T06:37:13.768Z","dependency_job_id":"a72e7125-6fac-4cfd-a7b2-fa22272ac08b","html_url":"https://github.com/MaryRichelle/weird-JavaScript","commit_stats":null,"previous_names":["maryrichelle/weird-javascript"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MaryRichelle/weird-JavaScript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaryRichelle%2Fweird-JavaScript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaryRichelle%2Fweird-JavaScript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaryRichelle%2Fweird-JavaScript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaryRichelle%2Fweird-JavaScript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaryRichelle","download_url":"https://codeload.github.com/MaryRichelle/weird-JavaScript/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaryRichelle%2Fweird-JavaScript/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29275588,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-09T17:15:22.002Z","status":"ssl_error","status_checked_at":"2026-02-09T17:14:42.395Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","javascript-interview-questions","javascript-quiz","tricky-javascript"],"created_at":"2024-12-25T12:15:23.516Z","updated_at":"2026-02-09T18:32:17.408Z","avatar_url":"https://github.com/MaryRichelle.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Weird 🙄 behavior of Coolest JavaScript\r\n\r\n***The trickier it gets, the more interesting  it becomes, and the more I love it.***\r\n\r\n## When you're convinced you understand  it, but it still finds new ways to surprise you and force you to say  *that's weird 🙄*\r\n\r\n```js\r\n$=_=\u003e`$=${$};$()`;$()  // '$=_=\u003e`$=${$};$()`;$()' that's weird 🙄\r\n($=_=\u003e`$=${$};$()`)()  // '$=_=\u003e`$=${$};$()`;$()' \r\ntypeof '$=_=\u003e`$=${$};$()`;$()' // 'string' \r\n\r\n```\r\n\r\nFunction Prints itself  \r\nlets break it down  \r\n\r\n* $ ==\u003e variable declaration ***\\$*** (but not allowed in 'strict mode without *let* ,*const* or *var*)\r\n* = ===\u003e assignment operator to assign a left hand side(aka target) a value\r\n* _=\u003e ===\u003earrow function with no parameters (valid in js)\r\n* \\``$=${$};$()`\\` ===\u003e template literals  string inside  \r\n* *\\${\\$}* ===\u003e calling $ variable (which is function itself) in side template literals  \r\n* \\$(): ===\u003e lastly calling(invoking)  \\$ function like this \\$()  \r\n**NOTE** don't confuse it with recursion though function is calling itself\r\n\r\n***\r\nThe most lovely one ⬇️ BaNaNa\r\n\r\n```js\r\n\"B\" + \"a\" + +\"a\" + \"a\"; // -\u003e 'BaNaNa'\r\n\r\n```\r\n\r\n* string concatenation with + operator and typeof \"string\"\r\n* +\"a\" ===\u003e Number(\"a\")  // NaN\r\nunary plus operator converts its operand to a number\r\n\r\n***\r\n\r\n```js\r\n1+2+3+4+5+6+7  // 28\r\n1+2+\"3\"+4+\"5\"+6+ +7; // -\u003e '334567' //string value type\r\n\"1\"+2+\"3\"+4+\"5\"+6+ +7 // '1234567' //string value type\r\n\r\n```\r\n\r\n***\r\n\r\n```js\r\n!!\"false\" == !!\"true\"; // -\u003e true\r\n!!\"false\" === !!\"true\"; // -\u003e true\r\n!!false == !!true // false\r\n!!\"false\" == !!false;// true\r\n```\r\n\r\nbreak it down  \r\n!!\"false\"  \r\n1: the unary ! negate operator explicitly coerces a value to a boolean.\r\n Boolean(\"false\"); // true  \r\n2: !\"false\" which is false  because \"false\" is a string and  a truthy value (but not a boolean *false*) and\r\n*!(truthy value)* is  false  \r\n3: !false ===\u003e true  \r\n4: thus true === true // true\r\n\r\n***\r\n\r\n```js\r\nvar amount = 42\r\nconsole.log(amount)\r\n```\r\n\r\nwhy its weird 😵\r\n\r\n* console.log(......) command has to implicitly coerce the *number 42* value to a *string* value type  to print it 42\r\n\r\n***\r\n\r\n```js\r\nconst objWithNoPrototype = Object.create(null)\r\nconsole.log(objWithNoPrototype)\r\n // {}\r\nNo properties\r\n```\r\n\r\n* Object.create(null) creates a new object with null as its prototype\r\n* so when we try to access any property, it will be undefined\r\nbecause this object don't have properties and prototypes\r\n* only object that don't have prototype\r\n\r\n***\r\n\r\n```js\r\nb *2\r\n```\r\n\r\nwhy its weird 😵\r\na 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 🙄)\r\n***\r\n\r\n```js\r\n  typeof null // \"object\"\r\n  typeof NaN // \"number\"\r\n ```\r\n\r\nwhy its weird 😵?  \r\ntypeof null is \"object\" (that's weird 🙄)\r\neven null is primitive value  but typeof null is object\r\n\r\n***\r\n\r\n```js\r\nconsole.log(z) // ReferenceError: z is not defined\r\ntypeof z; // \"undefined\"\r\n```\r\n\r\nThe typeof operator returns \"undefined\" even for “undeclared” ( “not defined”) variables. (that's weird 🙄)\r\n\r\n***\r\n\r\n## Numbers / Floating Points\r\n\r\n```js\r\n0 === -0 // true\r\n0 \u003e -0 // false\r\n-0 + \"\" // 0\r\n0 + \"\" === -0 + \"\" // true\r\ntypeof 42.0 // number ===\u003e there is only 7 type of values in js number is one of them \r\n999999999999999 // 999999999999999 ==\u003e double-precision floating-point format \r\n9999999999999999 // ===\u003e10000000000000000\r\n1 === 1.01 // false\r\n1 === 1.000000000000001 // false \r\n1 === 1.0000000000000001// true (that's weird 🙄 😭) \r\n0o363 === 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\r\n013 === 11 // true\r\n0o13 === 11 //true\r\n013 === 0o13 === 11 // false\r\n013 === 0o13 // false\r\nInfinity - Infinity // NaN\r\ninfinity / infinity // NaN\r\nInfinity * 0 // NaN\r\nNumber.isInteger( 42 );     // true\r\nNumber.isInteger( 42.000 ); // true\r\nNumber.isInteger( 42.3 );   // false\r\n```\r\n\r\n```js\r\n42.toFixed(3) // SyntaxError here . is property accessor\r\n42 .toFixed(3) // \"42.000\" with space \r\n42..toFixed(3) // \"42.000\"\r\nconsole.log(1..toString() === \"1\");// true (that's weird 🙄)\r\n```\r\n\r\nwhy its weird 😵?  \r\n\r\n* floating point 1.0\r\n* first . is for floating point 1.0  \r\n* second . for property accessor .toString()/.toFixed(3)\r\n\r\n***\r\n\r\n```js\r\n0.5+0.1 === 0.6 // true\r\n0.2+0.1 === 0.3 // false  \r\n```\r\n\r\n 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\r\n***\r\n\r\n```js\r\nconst aFloatingPoint = 5.99;\r\nconst floatingToFixed = aFloatingPoint.toFixed(2)\r\nconsole.log(typeof aFloatingPoint) // \"number\" \r\nconsole.log(typeof floatingToFixed) // \"string\" \r\n```\r\n\r\n***\r\n\r\n```js  \r\nconst num = () =\u003e{\r\nreturn 9;\r\n};\r\n\r\nconsole.log(num() \u003c 10); // true\r\n```\r\n\r\nnum function returns 9 which is less than 10  \r\n***\r\n\r\n```js\r\nconst value = \"123abc\";\r\nconst result = Number(value);\r\n\r\nconsole.log(typeof result);// \"number\" \r\n```\r\n\r\n***\r\n\r\n```js\r\nfunction fun(a, b, c) {\r\nreturn b + c\r\n}\r\nfun(5, 3, \"wowwwwww\", \"this is so cool\") // '3wowwwwww' string concatenation \r\n```\r\n\r\n***\r\n\r\n## [Operators / Operator Precedence / associativity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table)\r\n\r\n* javascript work on the right side of = *assignment operator* and then assign that value to left hand side(technically not accurate)  \r\nbut the thing under the hood is this is because of the assignment operator associativity this binary operator have  right to left associativity.\r\n\r\n```js\r\n\r\nconsole.log(-4 + 3 + \"8\") // 18 -1 + \"8\" === 18 - have higher precedence\r\nconsole.log(\"A\" - 1); // NaN\r\nconsole.log(2 + \"-2\" + \"2\"); // 2-22\r\nconsole.log(\"Hello\" - \"World\" + 78); //NaN ==\u003e  \"Hello\" - \"World\" (trying to subtract strings) + 78 NaN\r\nconsole.log(\"Hello\" + \"78\"); \"Hello78\"\r\nconsole.log(5 + \"5\"); // \"55\"  + operator number is coerced to string \r\nconsole.log(5 - \"5\"); // 0 ==\u003e - operator string coerced to number \r\nconsole.log(\"5\" * \"5\"); // 25 ==\u003e * operator string coerced to number \r\nconsole.log(\"5\" / \"5\"); // 1 = / operator string coerced to number \r\nconsole.log(5 + +\"5\") // 10 ==\u003e 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\r\nconsole.log(\"5\" - - \"5\"); // 10 unary minus (-\"5\") ==\u003e 5 + 5\r\nMath.min()// Infinity\r\nMath.max()// -Infinity\r\n!typeof \"name\" === \"object\" // false ==\u003e !(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 \r\ntrue + true + true// 3 ==\u003e because of + operator true becomes 1 \r\ntrue - true // 0  ==\u003e 1 - 1 = 0\r\n//TODO 👇\r\n(!+[]+[]+![]) // 'truefalse' TODO\r\n(!+[]+[]+![]).length // 9\r\n```\r\n\r\n***\r\n\r\n```js\r\nlet x = 9;\r\nlet y = x++; // y= 9 x= 10 (that's weird 🙄) postfix increment operator\r\nconsole.log({x}) // 10\r\nconsole.log({y}) // 9\r\nlet z = ++x// 11\r\nconsole.log({x}) // 11\r\nconsole.log({z}) // 11\r\nconsole.log(z * y) ; // 11* 9 (that's weird 🙄) prefix increment operator\r\n```\r\n\r\nwhy its weird 😵?  \r\n\r\n* **x++ the postfix increment operator increments and returns the value before incrementing.**  it return x first and than increment it\r\n  on line ``let y = x++`` x  current value is returned and  assigned to y and than it increment\r\n* **++x the prefix increment operator increments and returns the value after incrementing.** x is increment before its value is return\r\n\r\n***\r\n\r\n```js\r\n\r\nlet a = 5;\r\nlet b = a++; //a = 6, b= 5 (that's weird 🙄)\r\nlet c = ++a; // a = 7, c = 7 (that's weird 🙄)\r\n\r\nlet result = a + b + c; // 19\r\n\r\nconsole.log(result);\r\n```\r\n\r\n***\r\n\r\n```js\r\nconsole.log(4 + (5 - - 4) - - 5)// 18 \r\n```\r\n\r\n // Operator precedence\r\n1:(5 - - 4) =\u003e 5 +4 =\u003e 9 () grouping have hight precedence ⬇️\r\n2: 4 + 9 =\u003e 13  \r\n3: 13 - - 5 =\u003e 13 + 5 =\u003e 18  \r\n***\r\n\r\n```js\r\nconsole.log([10]+[10]); // \"1010\"\r\nconsole.log([10]+[10,10]); //'1010,10'\r\nconsole.log([1, 2] + [3, 4]);// '1,23,4' \r\n\r\n```\r\n\r\nwhy its weird 😵?  \r\n\r\nbecause of + operator array are coerced to strings \"10\" , \"10,10\" (that's weird 🙄)  \r\n***\r\n\r\n```js\r\nlet x=10 ; \r\nlet y='hello';\r\nlet z = Number('5'+x) \r\nconsole.log(z , typeof z]);//  output : 510 \"number\"(that's weird 🙄)\r\nconsole.log(`The result ${y} and`+ false); // 'The result hello andfalse'\r\n```\r\n\r\nwhy its weird 😵?\r\nstring concatenation because of + operator with typeof number and string accordingly  \r\n\r\n***\r\n\r\n```js\r\n\r\nfunction display()  {  \r\n  console.log(\"10\"+(20+30));  // \"1050\" Operator precedence for () \r\n  console.log(\"10\"+20+30); // \"102030\"\r\n  console.log(10+20+\"30\") // \"3030\"\r\n\r\n}  \r\ndisplay();  \r\n```\r\n\r\nwhy its weird 😵?  \r\n because + have left to right Associativity  string concatenation and\r\n 1: () grouping Operator precedence\r\n 2: + operator\r\n\r\n***\r\n\r\n```js\r\n(function() {\r\n    return +(new Date())\r\n})(); \r\n\r\n(function() {\r\n    return ''+(new Date());\r\n})();\r\n```\r\n\r\n## logical not\r\n\r\n```js\r\n!!null; // false ===\u003e null falsy value ===\u003e !false // true \r\n!!''; // false \r\n!!1; // 1 is truthy \r\n```\r\n\r\n!!null; // false\r\nstarting from left side\r\n\r\n* ===\u003e null falsy value\r\n* ===\u003e !false // true\r\n* ===\u003e !true // false\r\n\r\n***\r\n\r\n## logical \u0026\u0026 and ||\r\n\r\n```js\r\n\r\n\r\ntrue \u0026\u0026 true; // true ===\u003e 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 \u0026\u0026 .\r\ntrue \u0026\u0026 false; //  false ===\u003e if first test is true print the value of 2nd operand\r\nfalse \u0026\u0026 true; // false ===\u003e 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.\r\nfalse \u0026\u0026 false; // false ==\u003e if first  test is false print the value of 1st operand\r\n  \r\ntrue || true; //   true ===\u003e if the first  test is true prints the value of first operand\r\ntrue || false; // true ===\u003e if the first  test is true prints the value of first operand\r\nfalse || true; // true ===\u003e if the first  test is false prints the value of 2nd one operand\r\nfalse || false; // false ===\u003e if the first  test is false prints the value of 2nd one operand\r\n```\r\n\r\n***\r\n\r\n```js\r\nconsole.log(\"555\" === 555 || 555 === 555); // true\r\n```\r\n\r\n```\"555\" === 555``` is false  \r\n```555 === 555``` is true\r\n```false || true``` with || operator when the fist value is false print the value of second operand in our case is \"true\"\r\n***\r\n\r\n```js\r\nvar a = 22\r\nvar b = \"Mary\"\r\nvar c = null\r\n\r\na \u0026\u0026 b // \"Mary\"\r\na || b // 22\r\nb \u0026\u0026 c // null\r\nc || a // 22\r\n```\r\n\r\n`a \u0026\u0026 b` if the test is true, the \u0026\u0026 expression results in the value of the second operand (b).  \r\n`a || b` if the test is true, the || expression results in\r\nthe value of the first operand  \r\n`b \u0026\u0026 c` b is true nd javascript prints the value of c which is null  \r\n`c || a` c is falsy so it will print the value of second operand which is a(22)\r\n***\r\n\r\n```js\r\nconst array = [1, 2, 3];\r\nlet result = 0;\r\nfor (const value in array) {\r\n  // console.log(value) 0,1,2,\r\nresult += +value; // 3 ==\u003e 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\r\n}\r\nconsole.log(result)\r\n```\r\n\r\n```js\r\nfunction returnStr(){\r\nreturn console.log(\"hello world\") \r\n}\r\nfunction returnTrue(){\r\nreturn console.log(true)\r\n}\r\nconsole.log(returnStr() \u0026\u0026 console.log(true)) // \"hello world\" \"undefined\"\r\n```\r\n\r\nconsole.log(returnStr() \u0026\u0026 console.log(true)) // \"hello world\" \"undefined\"\r\n`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 \u0026\u0026 operator stops here and prints the value of 1st operand which is undefined\r\n\r\n***\r\n\r\n## == and === operators\r\n\r\n* string comparison\r\n\r\n```js\r\n\r\n\"\"*0 === 0 // true \r\n\"1\"* 0 === 0 // true\r\n\r\n-0 === +0 // true\r\n+0 !== -0 // true\r\n' '===' '  // true\r\n'' == 0 // false\r\n'' == ''// true\r\nfalse == 0// true\r\n\"0\" == false // true\r\nfalse == [] // true\r\n\"\" == [] // true\r\n0 == [] // true\r\n2 == [2] // true\r\n\"\" == [null] // true\r\n0 == \"\\n\" // true\r\n\"\" == 0// true\r\n\"\\t\\r \\v\\f \" == \"\" // true\r\n```\r\n\r\n* number comparison\r\n\r\n```js\r\n\r\n42 == \"42\" // true ==\u003e with loose equality implicit type coercion happened on one or both value to make of some type \"24\" coerced to number  \r\n\"24\" === 24 //false no type coercion\r\n```\r\n\r\n* boolean comparison\r\n\r\n```js\r\ntrue == 1 // true ==\u003e type coercion \r\ntrue === 1 // false\r\nfalse + 1 === 1 // true with + operator false become 0 hence 0 + 1 \r\ntrue + 1 === 1 //false\r\n\"42\" == true // false  ==\u003e  with == boolean converted to numbers (true = 1, false = 0) thus \r\n\"42\" == 1 // false ==\u003e == type coercion happens and string  coerce to number\r\n42 == 1 // false ==\u003e values are not same\r\n\r\n```\r\n\r\n\u003e [!NOTE] `Never compare  boolean(true or false) any other type of value with  ==`\r\n\r\n* NaN\r\n\r\n```js\r\nNaN == NaN// false\r\nNaN === NaN // false\r\nNaN ** 0 // 1\r\nNaN ** NaN // NaN\r\n\"1\" == NaN // false\r\n\"1\" === NaN // false\r\n5 === NaN // false\r\n42 == NaN // false\r\nfalse === NaN // false\r\ntrue == NaN // false\r\nNaN !== NaN // false\r\nNumber.isNaN(NaN); // true\r\nNumber.isNaN(\"abc\"); // false\r\nNumber.isNaN({}); // false\r\nNumber.isNaN([1]); // false\r\nNumber.isNaN(Infinity); // false\r\nNumber.isNaN(-Infinity); // false\r\nNumber.isNaN(true); // false\r\nNumber.isNaN(false); // false\r\nNumber.isNaN(null); // false\r\nNumber.isNaN(undefined); // false\r\nNumber.isNaN(''); // false\r\nNumber.isNaN([]); // false\r\nNumber.isNaN({}); // false\r\nNumber.isNaN(/a/g); // false\r\n{a:1} + {b:2} // NaN\r\nnull + undefined // NaN\r\n```\r\n\r\nNaN is never equal to any other value and to it self NaN it will return false  \r\n**loose equal and strictly equal  treats NaN as unequal to every other value**\r\n\r\n```js\r\nvar a = 2 / \"foo\";      // NaN \r\ntypeof a === \"number\";  // true\r\n```\r\n\r\n* Objects/Array comparison\r\n\r\n```js\r\n[undefined]===[undefined] //false \r\n[null]===[] //false\r\n[]==[] //false\r\n[] === [] //false\r\n[] !== [] // true\r\n{}==={} //false\r\n[]+[]==\"\" // true\r\n[]*1 === 0// true * operator convert [] to primitive \"\" * \r\n[1]===[]+1 // false because []+1 results in \"1\", but it's a string\r\nconsole.log({} + []); // \"[object Object]\"\r\n[] == \"\" // true [] coerce to \"\"\r\n// ({}) == \"[object object]\" // false\r\n{} + [] //  0  {} standalone block  than (+ []) is a expression with + [] coerce to 0\r\n[] + {} // \"[object Object]\" //true [] array are coerce to \"\" and thus object converted to string \"[object Object]\"\r\n[5] + [6] === \"56\" // true // converted to \"\"\r\n[1, 2] == [1, 2]; // false because it compares by reference not by value\r\n[1, 2].toString() == [1, 2].toString(); // true because we convert them into string before comparing\r\n\r\n\r\n```\r\n\r\n```js\r\n  let a = []\r\n  let b = []\r\n  console.log(a == b) // false \r\n  console.log(a === b)// false\r\n```\r\n\r\n* objects are held by reference both `==` and `===` check  only if the reference match not the content/value so both are false\r\n\r\n***\r\n\r\n## undefined'\r\n\r\nin non-strict mode 👇\r\n\r\n```js\r\nlet undefined = 5\r\nconsole.log(undefined) // 5\r\n// in strict mode Identifier 'undefined' has already been declared\r\nfunction foo(){\r\nvar undefined = 2;\r\nconsole.log(undefined)}\r\nfoo(0) // 2\r\nlet null = 5 //  Uncaught SyntaxError: Unexpected token 'null'\r\n```\r\n\r\n## null\r\n\r\n```js\r\n!!null;\r\nnull === 0 // false\r\nnull == 0 // false\r\nnull === null // true\r\nnull == null // true\r\nnull \u003e 0 // false\r\nnull \u003c 0 // false\r\nnull \u003e= 0 // true\r\nnull \u003c= 0 // true\r\nnull === undefined; // false\r\nnull == undefined; // true\r\nnull === null; // true\r\nnull == null; // true\r\n!null; // true \r\nNumber.isNaN(1 + null); // false\r\nNumber.isNaN(1 + undefined)\r\n```\r\n\r\n***\r\n\r\n```js\r\nvar a = null; \r\n!a \u0026\u0026 typeof a === \"object\"; // true\r\n```\r\n\r\ninitially a is null which is falsy value  \r\n!a making a true when is true with \u0026\u0026 operator\r\n***\r\n\u003c!-- Todo --\u003e\r\n```js\r\n\r\n// (function() {\r\n//     return (function(){}) === (function(){});\r\n// })();\r\n```\r\n\r\n### Implicit Type Coercion\r\n\r\n```js\r\n\r\nlet a = 0;\r\nlet b = false;\r\nconsole.log((a === b));// false ===\u003e type coercion not allowed\r\nconsole.log((a == b)); //true ===\u003e  \r\n//1 because of == type coercion happen   \r\n//2  boolean coerced to  number but when    \r\n//3 false coerced to number it become 0 and true converted to 1\r\n// but if \r\nlet c  = 41;\r\nconsole.log((c == b)); // false since c is coerced to 0 (0 == 41)\r\n\r\n\r\n```\r\n\r\n***\r\n\r\n```js\r\n\r\nlet a=[]\r\nlet b=\"\"\r\nconsole.log(a==b) // true ==\u003e with == loose equal array are coerced to string\r\n```\r\n\r\nwhy its weird 😵?  \r\nloose equal  == converts  one or both values to same type and [] is converted to \"\"\r\n\r\n***\r\n\r\n```js\r\nlet a = \"52\";\r\nlet b = 52\r\na === b // false (that's weird 🙄)\r\na ==b // true \r\ntypeof (a==b); // boolean\r\n\r\n\r\n```\r\n\r\ntrue 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\r\n\r\nwith === the coercion is not allowed  \r\n***\r\n\r\n```js\r\ntrue != 1;  // false (that's weird 🙄)  \r\ntrue !== 1; // true (that's weird 🙄)\r\n```\r\n\r\n with Inequality != operator  type coercion occurs  true becomes 1 and its false\r\n !== Strict Inequality operator type coercion is not allowed true and 1 are not same\r\n ***\r\n\r\n### Hoisting\r\n\r\n```js\r\nconsole.log(x); // undefined\r\nvar x = 5;\r\n ```\r\n\r\n* variable declaration (with var keyword)and function declaration(with function keyword) are hoisted\r\n 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 =\r\n\r\n***\r\n\r\n```js\r\nvar employeeId = '1234abe';\r\n(function(){\r\nconsole.log(employeeId);// undefined \r\nvar employeeId = '122345';\r\n})();\r\n```\r\n\r\nwhy its weird 😵?  \r\ninside 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 🙄)\r\nyes it didnt go to global scop since it find employeeId inside function scop\r\n***\r\n\r\n```js\r\n  console.log(a) // undefined ===\u003e var a is hoisted in global scop\r\n  var a;\r\n  function foo(){\r\n  console.log(a) // undefined ===\u003e looking in global scop where a is undefined \r\n  }\r\n  foo()\r\n  a = 1\r\n  console.log(a) // 1\r\n```\r\n\r\nbut if\r\n\r\n```js\r\nconsole.log(a) // ReferenceError: a is not defined because of let \r\n  let a;\r\n  ```\r\n\r\n***\r\n\r\n```js\r\nvar x = 23;\r\n(function(){\r\nvar x = 43;\r\n\r\n  (function random(){\r\n    // x is hoisted here but undefined\r\n    x++; // undefined++ \r\n    console.log(x); // NaN \r\n    var x = 21; // x = 21 initialized\r\n})();\r\n\r\n})();\r\n\r\n\r\n```\r\n\r\n## Array and Array Methods\r\n\r\n```js\r\nfunction foo(x) {\r\nx.push( 4 );\r\nx; // [1,2,3,4]\r\nx.length//4 \r\n// later\r\nx.length = 0; // empty existing array in-place\r\nx.push( 4, 5, 6, 7 );\r\nx; // [4,5,6,7]\r\n}\r\nvar a = [1,2,3];\r\na// [1,2,3];\r\nfoo( a );\r\na; // [4,5,6,7] not [1,2,3,4]\r\n```\r\n\r\n```js\r\nconst arr = [1, 2, 3];\r\narr[5] = 6;\r\nconsole.log(arr.length); //6 with two empty spaces\r\n```\r\n\r\n***\r\n\r\n```js\r\nconst arr = [1,2,3,4,5,5,,6]\r\nconst a= arr.map((x,y)=\u003e x+y)\r\n console.log(a)// [ 1, 3, 5, 7, 9, 10, \u003c1 empty item\u003e, 13 ]\r\n```\r\n\r\n***\r\n\r\n```js\r\nfunction myFun(){\r\nvar arrayNumb = [2, 8, 15, 16, 23, 42];\r\narrayNumb.sort();\r\nconsole.log(arrayNumb);// [ 15, 16, 2, 23, 42, 8 ] \r\nconst prices = [\"a\", \"b\", \"f\", \"e\", \"d\",\"c\"];\r\nprices.sort();\r\nconsole.log(prices);// [\"a\",\"b\",\"c\",\"d\",\"e\",\"f\"]\r\n}\r\nmyFun()\r\n```\r\n\r\nwhy its weird 😵?  \r\none 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 🙄)\r\n\r\n***\r\n\r\n```js\r\nlet v =[56,67,21,78,(1,2,3),(4,5,6)];\r\nlet [a,b,...c]  = v\r\nconsole.log(c); // [ 21, 78, 3, 6 ]\r\nconsole.log(a)//56\r\nconsole.log(b)//67\r\n\r\n```\r\n\r\n***\r\n\r\n```js\r\n\r\nvar greet = 'Hello World';\r\nvar toGreet = [].filter.call(greet, function(element, index) {\r\nreturn index \u003e 5;\r\n});\r\nconsole.log(toGreet);\r\n```\r\n\r\n***\r\n\r\n```js\r\n\r\na = [1, 2, 3]\r\nb = a // reference to a as array are pass by reference\r\na = a + [4] // 1,2,34 both a(reference to a) and [4]converted to string and concat\r\nconsole.log(b) // [1, 2, 3] a was assign to b before it changes it values on a = a + [4]\r\n```\r\n\r\n(that's weird 🙄)\r\n***\r\n\r\n```js\r\n\r\n const arr = [1,2,3,4,5,5,,6]\r\n const a= arr.slice()\r\n console.log(a) // [ 1, 2, 3, 4, 5, 5, \u003c1 empty item\u003e, 6 ]\r\n```\r\n\r\n***\r\n\r\n```js\r\n\r\nlet numbers = [1, 2, 3, 4, NaN];\r\nconsole.log(numbers.indexOf(NaN), typeof numbers[numbers.length-1], number[-1] )// -1 ,\"number\" 'undefined'\r\n```\r\n\r\n***\r\n\r\n## Recursion\r\n\r\n```js\r\n\r\nfunction test(x){\r\nif(x \u003e 0){\r\ntest(x-1)// Recursion function runs until x \u003e 0 but every time function runs x-1\r\n}\r\nconsole.log(x)// 0 1 2 3 4 5\r\n}\r\nlet data = 5\r\ntest(data);\r\n```\r\n\r\nwhy its weird 😵?\r\n\r\n***\r\n\r\n## Objects\r\n\r\n```js\r\nconst props = [\r\n{ id: 1, name: \"John\"},\r\n{ id: 2, name: \"Jack\"},\r\n{ id: 3, name: \"Tom\"}\r\n];\r\nconst [, , { name }] = props; \r\nconsole.log(name); \"Tom\"\r\n```\r\n\r\nfirst two objects are skipped and ```{ id: 3, name: \"Tom\"}``` is destructed ```{name}``` thus  name = Tom\r\n\r\n***\r\n\r\n```js\r\nconst obj1 = { a: 0 };\r\nconst obj2 = Object.assign({}, obj1);\r\n\r\nobj1.a = 2;\r\nconsole.log(obj1, obj2);// { a: 2 } { a: 0 }\r\n```\r\n\r\nwhy its weird 😵?  \r\nobj2 have all the the value of it and add new obj1 so its { a: 0 }  \r\nlater obj1 value of property a was changed but not in the obj2\r\n***\r\n\r\n```js\r\nconst a = {};\r\nconst b = { key: 'b' };\r\nconst c = { key: 'c' };\r\n\r\na[b] = 123; \r\na[c] = 456;\r\n\r\nconsole.log(a[b]);// 456 (that's weird 🙄 😭)\r\n```\r\n\r\nwhy its weird 😵?\r\nin js objects can be passed as a keys to another object but they are coerced to string  \r\n==\u003e In ```a[b] = 123;``` since `b` is object it becomes a[\"object object\"]  \r\n==\u003e a[\"object object\"] = 123\r\n==\u003e in `a[c] = 456;` again a[c] becomes a[\"object object\"]  \r\n==\u003e and so a[c] 456 since a[\"object object\"]  \r\n***\r\n\r\n```js\r\nlet x= {}, y = {name:\"Ronny\"},z = {name:\"John\"};\r\nx[z] = {name:\"Jene\"};\r\nx[y] = {name:\"Jenney\"};// assigning a property/key y with value {name:\"Jenney\"} to variable x (which is empty object)    \r\n// x['object Object'] = {name:\"Jenney\"} OR\r\n\r\nconsole.log(x[y]); // {name:\"Jenney\"}\r\n\r\n```\r\n\r\n1: objects can be used as keys  \r\n2: object literals are not copied, they point to same memory location  \r\n3: objects coerced to strings when they are passed as keys  `x[y]` becomes `x['object Object']`\r\n\r\n```js\r\n x = {\r\n  \"[object Object]\": { name:\"Jenney\"}\r\n};\r\n```\r\n\r\nin 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\"}\r\n***\r\n\r\n```js\r\n// TODO ===\u003e need more attention here \r\n  let hero = {\r\n      powerLevel: 99,\r\n      getPower(){\r\n      return this.powerLevel;\r\n    }\r\n  }\r\n  let powerOfHero = hero.getPower;\r\n  let hero2 = {powerLevel:42};\r\n  console.log(powerOfHero());//undefined\r\n  console.log(powerOfHero.apply(hero2)); //42\r\n```\r\n\r\n***\r\n\r\n```js\r\n  const someFunction = function(){\r\n    console.log(this); //global/ window object \r\n    const b = {\r\n      func1: function(){\r\n      console.log(this); //b object\r\n      }\r\n  }\r\n  const c = {\r\n    func2: ()=\u003e{\r\n    console.log(this); // window because of arrow function \r\n    }\r\n  }\r\n  b.func1();\r\n  c.func2();\r\n  }\r\n someFunction();\r\n\r\n```\r\n\r\n```js\r\nvar set = new Set();\r\nset.add(\"+0\").add(\"-0\").add(NaN).add(undefined).add(NaN);\r\nconsole.log(set);\r\n/*Set(4) {  \r\n  '+0',  \r\n  '-0',   \r\n  NaN,  \r\n  undefined   \r\n  }*/\r\n\r\n```\r\n\r\n## this keyword\r\n\r\n```js\r\nfunction myFunc(){\r\nconsole.log(this.message);// undefined\r\n}//(that's weird 🙄)\r\nmyFunc.message = \"Hi John\";// setting a property to function \r\nmyFunc()\r\n```\r\n\r\nwhy its weird 😵?  \r\nbut properties in function are not directly accessible\r\n***\r\n\r\n```js\r\n  const b = {\r\n    name:\"John\",\r\n    itsFun : function(){\r\n      var self = this;\r\n      console.log(this.name); // \"John\"\r\n\r\n        (function(){\r\n          console.log(this.name); // undefined \r\n          console.log(self.name); // \"John\"\r\n        })();\r\n\r\n      }\r\n  }\r\n  b.itsFun();\r\n\r\n```\r\n\r\n***\r\n\r\n## Scope and Closure\r\n\r\n```js\r\nfunction sayHi() {\r\n  return (() =\u003e 0)();\r\n}\r\n\r\nconsole.log(typeof sayHi());\r\n```\r\n\r\n```js\r\nfor (var i = 1; i \u003c= 5; i++) {\r\n  setTimeout(function timer() {\r\n    console.log(i)///6 6 6 6 6(that's weird 🙄)  \r\n  }, i * 1000)\r\n}\r\n```\r\n\r\nbecause of var i is global  \r\nsetTimeout because of its async behavior  decide to run after    ```i * 1000```  time so the\r\nfor 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 !\u003c= 5``` i = 6 resides in the global scope for setTime out  \r\nwhen set time out run it triggers the i which is 6 for 5 times with execution of loop\r\n***\r\n\r\n```js\r\n  (function(a){\r\n    return (function(){\r\n      console.log(a);// 45 ===\u003e because of Closure inner function have access to parent function\r\n      a = 23;\r\n    })()\r\n  })(45);\r\n\r\n// Simpler ⬇️\r\n  function outer(a){\r\n    return function inner(){\r\n    console.log(a)\r\n      a = 23;\r\n      console.log(a)\r\n    }\r\n }\r\n const parent = outer(45)\r\n parent()\r\n\r\n\r\n```\r\n\r\n***\r\n\r\n```js\r\nfunction bigFunc() {\r\n  let newArray = new Array(700).fill('♥');\r\n  return (element) =\u003e newArray[element];\r\n}\r\nlet getElement = bigFunc(); // Array is created only once\r\ngetElement(599);\r\ngetElement(670);\r\n// without Closure ⬇️\r\n  function bigFunc(element){\r\n    let newArray = new Array(700).fill('♥');\r\n    return newArray[element];\r\n    }\r\n    console.log(bigFunc(599)); // Array is created on every function call\r\n  console.log(bigFunc(670));\r\n```\r\n\r\n***\r\n\r\n```js\r\n  function randomFunc(){\r\n  for(let i = 0; i \u003c= 5; i++){\r\n    (function(){\r\n        let j = i\r\n      setTimeout(()=\u003econsole.log(j),1000)// 0 ,1 , 2 , 3 , 4 ,5\r\n      })()  \r\n    }\r\n  }\r\n const fun =  randomFunc();\r\n \r\n\r\n  function randomFunc(){\r\n    for(let i = 0; i \u003c=5; i++){\r\n      setTimeout(()=\u003e console.log(i),1000);// 0 ,1 , 2 , 3 , 4 ,5 \r\n    }\r\n  }\r\n  randomFunc();\r\n\r\n```\r\n\r\nbecause of let declaration block scope  \r\n***\r\n\r\n## async js\r\n\r\n```js\r\nsetTimeout(()=\u003e{console.log(\"second\")},0)\r\nconsole.log(\"first\")\r\n\r\n```\r\n\r\n\"first\"  \r\n\"second\"\r\nset time out  is Asynchronous  \r\n***\r\n\r\n```js\r\n\r\nconsole.log(\"hello\");\r\n\r\nsetTimeout(() =\u003e console.log(\"world\"), 0);\r\n\r\nconsole.log(\"hi\");\r\n\r\n\r\n```\r\n\r\n(that's weird 🙄)  \r\n\"hello\"  \r\n\"hi\"  \r\n\"world\"  \r\nwhy its weird 😵?\r\nsetTimeout is async function and it give space to other code to execute first even  it set to 0\r\n\r\n***\r\n\r\n```js\r\nfunction randomFunc(){\r\nfor(var i = 0; i \u003c 2; i++){\r\nsetTimeout(()=\u003e console.log(i),1000); // 2 ,2\r\n}\r\n}\r\nrandomFunc();\r\n\r\n\r\n```\r\n\r\nvar i is global variable when set time out run after the loop it triggers 2 from the value of i before condition false\r\n\r\n```js\r\nfunction someFun(){\r\nsetTimeout(()=\u003e{\r\nconsole.log(x); // 2 \r\nconsole.log(y); // 12\r\n},3000);\r\nvar x = 2;\r\nlet y = 12;\r\n}\r\nsomeFun()\r\n```\r\n\r\nbecause 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\r\n***\r\n\r\n```js\r\n(function(){\r\nsetTimeout(()=\u003e console.log(1),2000);\r\nconsole.log(2);\r\nsetTimeout(()=\u003e console.log(3),0);\r\nconsole.log(4);\r\n})();\r\n```\r\n\r\noutput is  \r\n2  ===\u003e executes immediately  \r\n4  ===\u003e executes immediately  \r\n3  ===\u003e runs after 0 seconds had to give place to rest of the code  \r\n1 ===\u003e runs after 3 seconds  \r\n***\r\n\r\n```js\r\nbutton.addEventListener(\"click\",()=\u003e{\r\nPromise.resolve().then(()=\u003econsole.log(\"promise\"))\r\nconsole.log(\"eventListener\")\r\n})\r\n```\r\n\r\n1: \"eventListener\"  \r\n2: \"promise\"\r\n\r\n***\r\n\r\n## event Delegation\r\n\r\n```html\r\n\u003cdiv onclick=\"console.log('first div')\"\u003e\r\n  \u003cdiv onclick=\"console.log('second div')\"\u003e\r\n    \u003cbutton onclick=\"console.log('button')\"\u003e\r\n      Click!\r\n    \u003c/button\u003e\r\n  \u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c!-- event.stopPropagation --\u003e\r\n```\r\n\r\nbutton\r\nsecond div  \r\nfirst div\r\nWhen 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.\r\n\r\nDuring 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.\r\ntechnical term of this behavior is called event delegation\r\n| Capturing    | Targeting       | bubbling   |\r\n| ---------    |----------       |----------  |\r\n|⬇️first div  | ➡️button *Click!* |⬆️ button |\r\n|⬇️second div |                  |⬆️ second div|\r\n|⬇️button     |                  |⬆️ first div |  \r\n\r\n`Notice the arrows`\r\n***\r\n\r\n```js\r\n(() =\u003e {\r\n  let x, y;\r\n  try {\r\n    throw new Error();\r\n  } catch (x) {\r\n    (x = 1), (y = 2);\r\n    console.log(x);\r\n  }\r\n  console.log(x);\r\n  console.log(y);\r\n})();\r\n```\r\n\r\n```js\r\n(![] + [])[+[]] +\r\n  (![] + [])[+!+[]] +\r\n  ([![]] + [][[]])[+!+[] + [+[]]] +\r\n  (![] + [])[!+[] + !+[]];\r\n```\r\n\r\n***\r\n\r\n### spread operator\r\n\r\n```js\r\n\r\nconst value = { number: 10 };\r\n\r\nconst multiply = (x = { ...value }) =\u003e {\r\n  console.log((x.number *= 2));\r\n};\r\n\r\nmultiply();\r\nmultiply();\r\nmultiply(value);\r\nmultiply(value);\r\n```\r\n\r\nJavascript is not yet done......  \r\n continue...  \r\n (that's weird 🙄)\r\n ***\r\n\r\n### Since you are here and if you find\r\n\r\n* wrong explanation\r\n* wrong term used\r\n* typo\r\n* things are not clear or need more explanation   \r\nPlease open a [Issue](https://github.com/MaryRichelle/weird-JavaScript/issues)   \r\nor lets open a [Discussion](https://github.com/MaryRichelle/weird-JavaScript/issues)   \r\n\r\n### if you find it helpful don't forget to ⭐ the repo\r\n\r\nThanks 😁\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaryrichelle%2Fweird-javascript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaryrichelle%2Fweird-javascript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaryrichelle%2Fweird-javascript/lists"}