{"resource":{"author":{"id":"h2so9H8jPMmgUKGghoNl","name":"Yomesh Gupta","username":"yomeshgupta"},"content":{"link":null,"difficulty":4,"domain":1,"type":1,"isInternal":true,"body":"JavaScript is one of the most popular languages. There are a lot of resources on the web teaching JavaScript and its concepts. Our aim with this series is to share a concise, useful, and quality list of questions with their answers. We don't want to add to the noise but rather be the source of clarity.\r\n\r\n## Explain Scope in JavaScript\r\n\r\nIn the most simple terms, scoping/scope is the area in which a variable is accessible. Scoping of a variable is controlled by the location of its declaration. Let us consider an example.\r\n\r\n```js\r\nfunction init() {\r\n  var name = \"Devtools Tech\";\r\n  console.log(name); // logs Devtools Tech\r\n}\r\nconsole.log(name); // ReferenceError\r\n```\r\n\r\nIn the above code snippet, variable `name` is declared inside the function `init` i.e. anywhere inside this function we can get or set the value of the variable. However, accessing the same variable outside the function would lead to `ReferenceError: name is not defined`. Let us understand why this happens!\r\n\r\n## Types of Scoping\r\n\r\n### Block Scope\r\n\r\nIt is the scope created by a code block in JavaScript. Now, you must be wondering what is a `code block`?\r\n\r\n> A (code) block is used to group zero or more statements i.e. any code written inside a pair of curly brackets.\r\n\r\n```js\r\nif (true) {\r\n  // code block\r\n  let name = \"Devtools Tech\";\r\n  let link = \"youtube.com/c/devtoolstech\";\r\n}\r\n\r\nfor (let i = 0; i < 4; i++) {\r\n  // code block\r\n  console.log(i);\r\n}\r\n```\r\n\r\nVariables declared using `let` and `const` are block-scoped. They are not accessible outside the code block they are declared in. For example --\r\n\r\n```js\r\nif (true) {\r\n  let name = \"Devtools Tech\";\r\n  let link = \"youtube.com/c/devtoolstech\";\r\n\r\n  // logs Devtools Tech youtube.com/c/devtoolstech\r\n  console.log(name, link);\r\n}\r\nconsole.log(name, link); // Reference Error\r\n```\r\n\r\nIn the above code snippet, the variable `name` and `link` are only accessible inside the scope created by the `if` statement. The second `console.log(name, link)` throws a `Reference Error` because variables are accessed outside of their scope i.e. the variables doesn't exist there.\r\n\r\nThe keywords `if`, `for`, `while` create their respective block scope. In JavaScript, we can define standalone code blocks too.\r\n\r\n```js\r\n{\r\n  // Block Scoped\r\n  let name = \"Devtools Tech\";\r\n  const link = \"youtube.com/c/devtoolstech\";\r\n}\r\nconsole.log(name, link); // Reference Error\r\n```\r\n\r\nWe talked about how `let` and `const` are block-scoped variables. However, variables declared using `var` are not limited to block scope but rather function-scoped. Let us understand more in the next section.\r\n\r\n### Function Scope\r\n\r\nAny function in JavaScript defines a scope for variables declared inside it. The variables could be defined either using `var`, `let`, or `const`.\r\n\r\n```js\r\nfunction init() {\r\n  var name = \"Devtools tech\";\r\n  const link = \"youtube.com/c/devtoolstech\";\r\n\r\n  if (true) {\r\n    console.log(name, link); // logs the values\r\n\r\n    if (true) {\r\n      console.log(name, link); // logs the values\r\n    }\r\n  }\r\n\r\n  console.log(name, link); // logs the values\r\n}\r\n\r\nconsole.log(name, link); // ReferenceError\r\n```\r\n\r\nThe variables are accessible anywhere inside the function, no matter how deep inside the function they are used. However, if we try to access the same variables outside the function then we would get the `ReferenceError` as they simply don't exist there.\r\n\r\nIn some cases, `function scope` can be considered as the parent scope of the `block scope` with uni-directional scope access.\r\n\r\n```js\r\nfunction init() {\r\n  // function scope\r\n  const name = \"Devtools Tech\";\r\n\r\n  if (true) {\r\n    // block scope\r\n    const link = \"youtube.com/c/devtoolstech\";\r\n\r\n    console.log(name, link); // logs both the values\r\n  }\r\n\r\n  console.log(name); // logs the value\r\n  console.log(link); // ReferenceError\r\n}\r\n```\r\n\r\nIn the above code snippet, the variable `name` is declared in the function scope so it is accessible inside the code block created by the `if` statement. However, vice versa is not true. The variable `link` created inside the `if` statement is block-scoped and cannot be accessed outside. Hence, `function scope` is acting as the parent scope and you can only access variables in one direction i.e. top to bottom.\r\n\r\n### Curious Case of var keyword\r\n\r\nThe variables declared via `var` bypass the above-mentioned rule. No matter how deep you declare a variable using `var`. It is always scoped to the nearest function declaration i.e.\r\n\r\n```js\r\nfunction init() {\r\n  if (true) {\r\n    if (true) {\r\n      if (true) {\r\n        if (true) {\r\n          if (true) {\r\n            var name = \"Devtools Tech\";\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  // logs Devtools Tech as name is scoped to the function `init`\r\n  console.log(name);\r\n}\r\n```\r\n\r\n### Global Scope\r\n\r\nIt is the outermost scope. Any variable defined in the global scope is accessible inside any other scope. In a browser environment, any file loaded using the `script` tag is a global scope.\r\n\r\n```js\r\n// file: videos.js\r\n\r\n// global scoped variable\r\nfunction getChannelLink() {\r\n  return \"youtube.com/c/devtoolstech\";\r\n}\r\n...\r\n```\r\n\r\n```js\r\n<script src=\"video.js\"></script>\r\n<script type=\"text/javascript\">\r\n  // logs the value\r\n  // getChannelLink is accessible here because it is a global variable\r\n  console.log(getChannelLink());\r\n</script>\r\n```\r\n\r\nDifferent JavaScript runtimes provide different global variables. The browser provides `document` and `window` global variables whereas the Node environment provides global variables like `process`.\r\n\r\n## Lexical Scope\r\n\r\nLet us first take a look at an example\r\n\r\n```js\r\n// global scope\r\n\r\nfunction analytics() {\r\n  // outer scope\r\n  const category = \"Devtools Tech\";\r\n\r\n  function track(action) {\r\n    // inner scope\r\n    window.ga(\"send\", {\r\n      eventCategory: category,\r\n      eventAction: action,\r\n    });\r\n  }\r\n\r\n  return track;\r\n}\r\n\r\nconst track = analytics();\r\ntrack(\"Question Clicked\");\r\n```\r\n\r\nIn the above code snippet, the function `track` invocation happens outside the `analytics` function scope. Yet, it is still able to access and understand the `category` variable that is defined inside the scope of the `analytics` function.\r\n\r\nThis is due to lexical scoping. JavaScript implements a scoping mechanism called lexical/static scoping. It means that the accessibility of variables are determined by their position within the nested function scopes i.e.\r\n\r\n1. When the JavaScript engine checks for the `category` variable inside the `track` function then it first checks its local scope. If found then use it.\r\n2. If the variable is not found in the local scope then it checks the outer scope. If found then use it.\r\n3. If not found in the outer scope then it traverses upwards till it either finds the variable or reaches the global scope.\r\n\r\nThis is what is also known as `closure`. The lexical scope of the `track` function consists of the scope of the `analytics` function.\r\n\r\n### Added benefits of Scoping\r\n\r\nOne direct benefit of scoping and using it well is that you can reuse variable names without conflicts.\r\n\r\n```js\r\nfunction iterate(arr) {\r\n  const count = 0;\r\n\r\n  while (count !== arr.length) {\r\n    console.log(arr[count]);\r\n    count++;\r\n  }\r\n}\r\n\r\nfunction counter(limit) {\r\n  const count = 1;\r\n\r\n  while (count !== limit) {\r\n    console.log(count);\r\n    count++;\r\n  }\r\n}\r\n```\r\n\r\nIn the above code snippet, we are using the variable name `count` in both functions. Since both variables are blocked scope, there won't be any conflict issues.\r\n\r\n## Final Thoughts\r\n\r\nUnderstanding scoping is essential to write error-free code. It is a fundamental concept. Learning about different scopes and how they impact each other leads to more robust codebases and makes your life easier. I hope this post was useful to you. Do share it with others and help them too! :D\r\n","languages":[],"editorConfig":{}},"stats":{"views":15715,"used":0,"likes":0},"description":"","published":true,"isActive":true,"tags":["javascript","frontend","coding","scoping","closure","lexcial scope","devtools","tutorial","js fundamentals"],"slug":"scoping-in-javascript-explained-or-javascript-interview-questions---rid---Iahbvfkg5H86a6KL8yBD","isPremium":false,"categories":[],"requires":[],"_id":"61fe386fe12bce537863cbb4","title":"Scoping in JavaScript Explained | JavaScript Interview Questions","resourceId":"Iahbvfkg5H86a6KL8yBD","createdAt":1644050543859,"modifiedAt":1644050543859},"currentUser":null,"isOwner":false,"recommendations":{"questions":[{"_id":"67698d4e1216f11205443050","content":{"languages":["react","html"],"difficulty":2},"tags":["javascript","react","ui","frontend","coding challenge","ux","game","devtools tech"],"slug":"build-a-two-player-line-board-game---qid---lIas2ZwR8dMHDjbpxICA","title":"Build a Two-Player Line Board Game","questionId":"lIas2ZwR8dMHDjbpxICA"},{"_id":"635255c59efd8c366a2e8658","content":{"languages":["javascript","typescript"],"difficulty":1},"tags":["","javascript","arrays","javascript polyfills","interview question","frontend","coding","devtools tech","programming","codedamn","frontend masters","egghead","razorpay","hotstar","tata1mg","swiggy","zomato","array","array lastIndexOf"],"slug":"how-to-implement-array-prototype-lastindexof-javascript-interview-question-or-problem-solving-or-javascript-polyfills---qid---4YvjhwHcr7jlT3xLybgs","title":"How to implement Array.prototype.lastIndexOf? JavaScript Interview Question | Problem Solving | JavaScript Polyfills","questionId":"4YvjhwHcr7jlT3xLybgs"},{"_id":"69c6c5807fa48f2af9fefb80","content":{"languages":["html"],"difficulty":1},"tags":["javascript","ui","ux","devtools tech","interview question","atlassian","frontend coding","ui challenges"],"slug":"real-time-comment-feed---qid---gxnubQDhcOkUH6VxaJra","title":"Real-Time Comment Feed","questionId":"gxnubQDhcOkUH6VxaJra"},{"_id":"5eb7d8943f4a621665113a3d","content":{"difficulty":1,"languages":"javascript"},"tags":["node.js","javascript","delete operator","frontend fundamentals","javascript fundamentals","web development"],"title":"Output question based on the delete operator in JavaScript","questionId":"TO3XSXEbx9FW3cbnrfvK","slug":"output-question-based-on-the-delete-operator-in-javascript---qid---TO3XSXEbx9FW3cbnrfvK"},{"_id":"5f521c836d3cda64e470c3eb","content":{"difficulty":4,"languages":"javascript"},"tags":["javascript","prototype","frontend fundamentals","prototype chain"],"slug":"what-would-be-the-output-different-ways-of-prototype-calls---qid---oRjYJXGzxi50NhQNWZ8g","title":"What would be the output? (Different ways of Prototype calls)","questionId":"oRjYJXGzxi50NhQNWZ8g"}],"resources":[{"_id":"6341cada42e7761bfac1a074","content":{"difficulty":2,"domain":2,"type":2,"isInternal":false},"tags":["frontend","devtools tech","tutorials","eslint","custom eslint rules","webpack","code commit","pre commit","commit hook","tooling","developer experience","remix","code masters","codechef","frontend masters","codedamn","egghead"],"slug":"how-to-improve-your-codebase-or-custom-eslint-rules-or-advanced-javascript-or-devtools-tech---rid---KgSipm8RngCFwwtI7bh2","title":"How to Improve Your Codebase!? | Custom ESLint Rules | Advanced JavaScript | Devtools Tech","resourceId":"KgSipm8RngCFwwtI7bh2"},{"_id":"61eeae76c596de5b12fea561","content":{"difficulty":4,"domain":2,"type":1,"isInternal":true},"tags":["remix","js framework","dev tooling","sass","css","styling","frontend"],"slug":"setting-up-sass-with-remix-run---rid---lXDyMjDSdDZDXxNcJ2ep","title":"Setting Up SASS With Remix Run","resourceId":"lXDyMjDSdDZDXxNcJ2ep"},{"_id":"6967584e132ce4e954b254eb","content":{"difficulty":4,"domain":2,"type":1,"isInternal":true,"languages":[]},"tags":["javascript","ui","ux","devtools tech","coding","blinkit","interview experience","frontend"],"slug":"blinkit-frontend-interview-experience-sde-1---rid---j7MSrpMfo09YVcBzRXYa","title":"Blinkit Frontend Interview Experience (SDE 1)","resourceId":"j7MSrpMfo09YVcBzRXYa"},{"_id":"61fe386fe12bce537863cbb4","content":{"difficulty":4,"domain":1,"type":1,"isInternal":true},"tags":["javascript","frontend","coding","scoping","closure","lexcial scope","devtools","tutorial","js fundamentals"],"slug":"scoping-in-javascript-explained-or-javascript-interview-questions---rid---Iahbvfkg5H86a6KL8yBD","title":"Scoping in JavaScript Explained | JavaScript Interview Questions","resourceId":"Iahbvfkg5H86a6KL8yBD"},{"_id":"6310505a77f9961d5b7ce983","content":{"difficulty":2,"domain":1,"type":2,"isInternal":false},"tags":["javascript","redux","react","youtube","interviews","frontend","interview preparation","tooling","state management"],"slug":"build-your-own-redux-or-part-1-or-advanced-frontend---rid---MNkFAzvLnmds66wD3JV0","title":"Build Your Own Redux | Part 1 | Advanced Frontend","resourceId":"MNkFAzvLnmds66wD3JV0"}]}}