-
Notifications
You must be signed in to change notification settings - Fork 481
Added to the scope JS 101 article #201
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
fb9ee66
Added to the scope JS 101 article
jackfranklin b9ebfc6
update article based on @rmurphey's feedback
jackfranklin 0ce4fb3
tweaks and comforming to the style guide
jackfranklin a029a3b
fix merge conflict in scope article
jackfranklin 0ba297d
update code to match style - spaces before / after parens
jackfranklin ba32ebb
Grammar tweaks
jackfranklin 1d28c53
Merge branch 'master' of github.com:jquery/learn.jquery.com into issu…
jackfranklin ce975df
Rewrite the paragraph starting with Secondly to be a bit more concise…
jackfranklin 21900b5
merge in from upstream and fix conflict
jackfranklin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,123 @@ | ||
--- | ||
title: Scope | ||
level: beginner | ||
source: http://jqfundamentals.com/legacy | ||
attribution: | ||
title: Scope | ||
level: beginner | ||
source: http://jqfundamentals.com/legacy, http://javascriptplayground.com/blog/2012/04/javascript-variable-scope-this | ||
attribution: | ||
- jQuery Fundamentals | ||
--- | ||
|
||
"Scope" refers to the variables that are available to a piece of code at a given time. A lack of understanding of scope can lead to frustrating debugging experiences. | ||
"Scope" refers to the variables that are available to a piece of code at a given time. A lack of understanding of scope can lead to frustrating debugging experiences. The idea of "scope" is that it's where certain functions or variables are accessible from in our code, and the context in which they exist and are executed in. | ||
|
||
When a variable is declared inside of a function using the `var` keyword, it is only available to code inside of that function — code outside of that function cannot access the variable. On the other hand, functions defined inside that function will have access to the declared variable. | ||
There are two types of scopes in JavaScript: Global and local. Lets talk about each of them in turn. | ||
|
||
Furthermore, variables that are declared inside a function without the `var` keyword are not local to the function — JavaScript will traverse the scope chain all the way up to the window scope to find where the variable was previously defined. If the variable wasn't previously defined, it will be defined in the global scope, which can have unexpected consequences. | ||
## Global Scope | ||
|
||
The first scope is __Global Scope__. This is very easy to define. If a variable or function is _global_, it can be accessed from anywhere within a program. In a browser, the global scope is the `window` object. If a variable declaration occurs outside of a function, then that variable exists on the global object. For example: | ||
|
||
``` | ||
// Functions have access to variables defined in the same scope | ||
var foo = "hello"; | ||
var sayHello = function() { | ||
console.log( foo ); | ||
var x = 9; | ||
``` | ||
|
||
Once that variable had been defined, it could be referenced as `window.x`, but because it exists on the global object we can simply refer to it as `x`. | ||
|
||
## Local Scope | ||
JavaScript also creates a __Local Scope__ inside each function body. For example: | ||
|
||
``` | ||
function myFunc() { | ||
var x = 5; | ||
}; | ||
console.log( x ); // ReferenceError: x is not defined | ||
``` | ||
|
||
Since `x` was initialized within `myFunc()`, it is only accessible within `myFunc()`, and we get a reference error if we try to access it outside of `myFunc()`. | ||
|
||
##A word of Caution | ||
|
||
If you declare a variable and forget to use the `var` keyword, that variable is automically made global. So this code would work: | ||
|
||
``` | ||
function myFunc() { | ||
x = 5; | ||
}); | ||
console.log( x ); // 5 | ||
``` | ||
|
||
This is a bad idea. Any variable that is global can have its value changed by any other parts of a program or any other script. This is undesirable, as it could lead to unforseen side effects. | ||
|
||
Secondly, Immediately-Invoked Funcion Expressions provide a way to avoid global variables. You'll see many libraries such as jQuery often use these: | ||
|
||
``` | ||
(function() { | ||
var jQuery = { /* all my methods go here */ }; | ||
window.jQuery = jQuery. | ||
})(); | ||
``` | ||
|
||
Wrapping everything in a function which is then immediately invoked means all the variables within that function are bound to the _local scope_. At the very end you can then expose all your methods by binding the `jQuery` object to the `window`, the _global object_. To read more about Immediatly-Invoked Functions, check out Ben Alman's [Immediately-Invoked Function Expression](http://benalman.com/news/2010/11/immediately-invoked-function-expression/) article. | ||
|
||
Because local scope works through functions, any functions defined within another have access to variables defined in the outer function: | ||
|
||
``` | ||
function outer() { | ||
var x = 5; | ||
function inner() { | ||
console.log( x ); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This example makes more sense if the |
||
|
||
inner(); // 5 | ||
} | ||
``` | ||
|
||
But the `outer()` function doesn't have access to any variables declared within `inner()`: | ||
|
||
``` | ||
function outer() { | ||
var x = 5; | ||
|
||
sayHello(); // "hello" | ||
console.log( foo ); // "hello" | ||
function inner() { | ||
console.log( x ); | ||
var y = 10; | ||
} | ||
|
||
inner(); // 5 | ||
|
||
console.log( y ); // ReferenceError: y is not defined | ||
} | ||
``` | ||
|
||
Furthermore, variables that are declared inside a function without the `var` keyword are not local to the function — JavaScript will traverse the scope chain all the way up to the window scope to find where the variable was previously defined. If the variable wasn't previously defined, it will be defined in the global scope, which can have unexpected consequences. | ||
|
||
``` | ||
// Code outside the scope in which a variable was defined does not have access to the variable | ||
// Functions have access to variables defined in the same scope | ||
var foo = "hello"; | ||
|
||
var sayHello = function() { | ||
var foo = "hello"; | ||
console.log( foo ); | ||
}; | ||
|
||
sayHello(); // hello | ||
sayHello(); // "hello" | ||
|
||
console.log( foo ); // undefined | ||
console.log( foo ); // "hello" | ||
``` | ||
|
||
Variables with the same name can exist in different scopes with different values: | ||
``` | ||
// Variables with the same name can exist in different scopes with different values | ||
var foo = "world"; | ||
|
||
var sayHello = function() { | ||
var foo = "hello"; | ||
console.log( foo ); | ||
}; | ||
|
||
sayHello(); // logs "hello" | ||
console.log( foo ); // logs "world" | ||
sayHello(); // "hello" | ||
|
||
console.log( foo ); // "world" | ||
``` | ||
|
||
When you reference a global variable within a function, that function can see changes to the variable value after the function is defined. | ||
|
||
``` | ||
// Functions can see changes in variable values after the function is defined | ||
var myFunction = function() { | ||
var foo = "hello"; | ||
var myFn = function() { | ||
|
@@ -63,32 +131,43 @@ var f = myFunction(); | |
f(); // "world" | ||
``` | ||
|
||
Here's a more complex example of scopes at play: | ||
|
||
``` | ||
// Scope insanity | ||
// a self-executing anonymous function | ||
(function() { | ||
var baz = 1; | ||
|
||
var bim = function() { | ||
alert( baz ); | ||
console.log( baz ); | ||
}; | ||
|
||
bar = function() { | ||
console.log( baz ); | ||
}; | ||
|
||
bar = function() { | ||
alert( baz ); | ||
console.log( baz ); | ||
}; | ||
|
||
})(); | ||
``` | ||
In this instance, running: | ||
|
||
``` | ||
console.log( baz ); // baz is not defined outside of the function | ||
``` | ||
|
||
Gives us a `ReferenceError`. `baz` was only defined within the function, and was never exposed to the global scope. | ||
|
||
// baz is not defined outside of the function | ||
console.log( baz ); | ||
``` | ||
bar(); // 1 | ||
``` | ||
|
||
// bar is defined outside of the anonymous function | ||
// because it wasn't declared with var; furthermore, | ||
// because it was defined in the same scope as baz, | ||
// it has access to baz even though other code | ||
// outside of the function does not | ||
bar(); | ||
`bar()` may have been defined within the anonymous function, but it was defined without the `var` keyword, which means it wasn't bound to the local scope and was instead created globally. Furthermore, it has access to the `baz` variable because `bar()` was defined within the same scope as `baz`. This means it has access to it, even though other code outside of the function does not. | ||
|
||
// bim is not defined outside of the anonymous function, | ||
// so this will result in an error | ||
bim(); | ||
|
||
``` | ||
bim(); // ReferenceError: bim is not defined | ||
``` | ||
|
||
`bim()` was only defined within the function, so does not exist on the global object as it was defined locally. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this accurate? Seems the jqf content has been largely replaced.