Download - JavaScript for ABAP Programmers - 4/7 Scope
JavaScript for ABAP Programmers Scope Chris Whealy / The RIG
ABAP JavaScript Strongly typed Weakly typed Syntax similar to COBOL Syntax derived from Java Block Scope Lexical Scope No equivalent concept Functions are 1st class citizens OO using class based inheritance OO using referential inheritance Imperative programming Imperative or Functional programming
Execution Contexts
© 2013 SAP AG. All rights reserved. 4
Execution Contexts
All JavaScript code is executed within a runtime container known as an "execution context”. There are 3 different execution contexts: • The Global Context : created once for the entire JavaScript runtime environment
© 2013 SAP AG. All rights reserved. 5
Execution Contexts
All JavaScript code is executed within a runtime container known as an "execution context”. There are 3 different execution contexts: • The Global Context : created once for the entire JavaScript runtime environment • A Function Context : created each time a JavaScript function is called
© 2013 SAP AG. All rights reserved. 6
Execution Contexts
All JavaScript code is executed within a runtime container known as an "execution context”. There are 3 different execution contexts: • The Global Context : created once for the entire JavaScript runtime environment • A Function Context : created each time a JavaScript function is called • An eval Context : created when the eval statement is used*
* This is more specialised and will not be covered in this presentation
© 2013 SAP AG. All rights reserved. 7
Execution Contexts
All JavaScript code is executed within a runtime container known as an "execution context”. There are 3 different execution contexts: • The Global Context : created once for the entire JavaScript runtime environment • A Function Context : created each time a JavaScript function is called • An eval Context : created when the eval statement is used*
Each of these execution contexts uses an internal object called VariableObject as a container for storing all its properties, variables and formal parameters.
© 2013 SAP AG. All rights reserved. 8
Execution Contexts
All JavaScript code is executed within a runtime container known as an "execution context”. There are 3 different execution contexts: • The Global Context : created once for the entire JavaScript runtime environment • A Function Context : created each time a JavaScript function is called • An eval Context : created when the eval statement is used*
Each of these execution contexts uses an internal object called VariableObject as a container for storing all its properties, variables and formal parameters. JavaScript does not give any direct access to VariableObject as a named object in the coding; however, the contents of this object are accessible through specially created proxy objects such as window or this.
Declarations The Global Context Variables, Properties and the difference between them
© 2013 SAP AG. All rights reserved. 10
The Global Context
The global context is the runtime container belonging to the entire JavaScript runtime environment. You will also see the term ‘global scope’ used.
Global Context
© 2013 SAP AG. All rights reserved. 11
The Global Context
The global context is the runtime container belonging to the entire JavaScript runtime environment. You will also see the term ‘global scope’ used.
In a browser, the VariableObject belonging to the global context is accessible via a proxy object called window. This is a general purpose “bucket” in which all data not belonging to user defined functions is stored.
document parent top localStorage sessionStorage location history etc...
Global Context: window
document parent top localStorage sessionStorage location history etc...
© 2013 SAP AG. All rights reserved. 12
Declarations: Variables and Properties in the Global Context 1/2
Since all properties must belong to an object, if a property is created without specifying the object name, then it automatically belongs to the VariableObject of the Global Context (I.E. in a browser, this is the window object) and is visible in every execution context. // Create a global property
Global Context: window
document parent top localStorage sessionStorage location history etc...
foobar
foobar = "Phluff 'n' stuff";
© 2013 SAP AG. All rights reserved. 13
Declarations: Variables and Properties in the Global Context 1/2
Since all properties must belong to an object, if a property is created without specifying the object name, then it automatically belongs to the VariableObject of the Global Context (I.E. in a browser, this is the window object) and is visible in every execution context. // Create a global property foobar; // à "Phluff 'n' stuff" window.foobar; // à "Phluff 'n' stuff"
Global Context: window
document parent top localStorage sessionStorage location history etc...
foobar
foobar = "Phluff 'n' stuff";
Global properties can be accessed either by direct reference to the property name
© 2013 SAP AG. All rights reserved. 14
Declarations: Variables and Properties in the Global Context 1/2
Since all properties must belong to an object, if a property is created without specifying the object name, then it automatically belongs to the VariableObject of the Global Context (I.E. in a browser, this is the window object) and is visible in every execution context. // Create a global property foobar; // à "Phluff 'n' stuff" window.foobar; // à "Phluff 'n' stuff"
Global Context: window
document parent top localStorage sessionStorage location history etc...
foobar
foobar = "Phluff 'n' stuff";
Or via their parent object and the refinement operator “.”
© 2013 SAP AG. All rights reserved. 15
// Create a global property foobar = "Phluff 'n' stuff"; foobar; // à "Phluff 'n' stuff" window.foobar; // à "Phluff 'n' stuff" // Create a global variable var barfoo = "Chicken soup";
Declarations: Variables and Properties in the Global Context 2/2
The keyword var causes a variable to be created. Unfortunately, when a variable is declared in the Global Context, the misleading impression is formed that the variable is no different from any other property of the window object.
Global Context: window
document parent top localStorage sessionStorage location history etc...
barfoo foobar
© 2013 SAP AG. All rights reserved. 16
// Create a global property foobar = "Phluff 'n' stuff"; foobar; // à "Phluff 'n' stuff" window.foobar; // à "Phluff 'n' stuff" // Create a global variable var barfoo = "Chicken soup"; barfoo; // à "Chicken soup"
Declarations: Variables and Properties in the Global Context 2/2
The keyword var causes a variable to be created. Unfortunately, when a variable is declared in the Global Context, the misleading impression is formed that the variable is no different from any other property of the window object.
Global Context: window
document parent top localStorage sessionStorage location history etc...
barfoo
Global variables are accessed by direct reference to the variable name
foobar
© 2013 SAP AG. All rights reserved. 17
// Create a global property foobar = "Phluff 'n' stuff"; foobar; // à "Phluff 'n' stuff" window.foobar; // à "Phluff 'n' stuff" // Create a global variable var barfoo = "Chicken soup"; barfoo; // à "Chicken soup" window.barfoo; // à "Chicken soup"
Declarations: Variables and Properties in the Global Context 2/2
The keyword var causes a variable to be created. Unfortunately, when a variable is declared in the Global Context, the misleading impression is formed that the variable is no different from any other property of the window object.
Global Context: window
document parent top localStorage sessionStorage location history etc...
barfoo
This unfortunately makes the variable look just like a property…
foobar
© 2013 SAP AG. All rights reserved. 18
// Create a global property foobar = "Phluff 'n' stuff"; foobar; // à "Phluff 'n' stuff" window.foobar; // à "Phluff 'n' stuff" // Create a global variable var barfoo = "Chicken soup"; barfoo; // à "Chicken soup" window.barfoo; // à "Chicken soup"
Declarations: Variables and Properties in the Global Context 2/2
The keyword var causes a variable to be created. Unfortunately, when a variable is declared in the Global Context, the misleading impression is formed that the variable is no different from any other property of the window object.
Global Context: window
document parent top localStorage sessionStorage location history etc...
barfoo foobar
A property always belongs to an object and, unless you say otherwise, that object will be the global context.
© 2013 SAP AG. All rights reserved. 19
// Create a global property foobar = "Phluff 'n' stuff"; foobar; // à "Phluff 'n' stuff" window.foobar; // à "Phluff 'n' stuff" // Create a global variable var barfoo = "Chicken soup"; barfoo; // à "Chicken soup" window.barfoo; // à "Chicken soup"
Declarations: Variables and Properties in the Global Context 2/2
The keyword var causes a variable to be created. Unfortunately, when a variable is declared in the Global Context, the misleading impression is formed that the variable is no different from any other property of the window object.
Global Context: window
document parent top localStorage sessionStorage location history etc...
barfoo foobar
A property always belongs to an object and, unless you say otherwise, that object will be the global context. A variable always belongs to an execution context; however, in the global context, the execution context and the global context are the same thing.
© 2013 SAP AG. All rights reserved. 20
// Create a global property foobar = "Phluff 'n' stuff"; foobar; // à "Phluff 'n' stuff" window.foobar; // à "Phluff 'n' stuff" // Create a global variable var barfoo = "Chicken soup"; barfoo; // à "Chicken soup" window.barfoo; // à "Chicken soup"
Declarations: Variables and Properties in the Global Context 2/2
The keyword var causes a variable to be created. Unfortunately, when a variable is declared in the Global Context, the misleading impression is formed that the variable is no different from any other property of the window object.
Global Context: window
document parent top localStorage sessionStorage location history etc...
barfoo foobar
A property always belongs to an object and, unless you say otherwise, that object will be the global context. A variable always belongs to an execution context; however, in the global context, the execution context and the global context are the same thing. Therefore the misleading impression is created that global variables are the same as global properties.
© 2013 SAP AG. All rights reserved. 21
// Create a global property foobar = "Phluff 'n' stuff"; foobar; // à "Phluff 'n' stuff" window.foobar; // à "Phluff 'n' stuff" // Create a global variable var barfoo = "Chicken soup"; barfoo; // à "Chicken soup" window.barfoo; // à "Chicken soup"
Declarations: Variables and Properties in the Global Context 2/2
The keyword var causes a variable to be created. Unfortunately, when a variable is declared in the Global Context, the misleading impression is formed that the variable is no different from any other property of the window object.
Global Context: window
document parent top localStorage sessionStorage location history etc...
barfoo foobar
A property always belongs to an object and, unless you say otherwise, that object will be the global context. A variable always belongs to an execution context; however, in the global context, the execution context and the global context are the same thing. Therefore the misleading impression is created that global variables are the same as global properties. Important This impression exists only for variables in the global context! In function contexts, it does not apply.
Declarations Variable Hoisting
© 2013 SAP AG. All rights reserved. 23
Declarations: Variables Are Hoisted!
Understanding the difference between variables and properties is important because it has an impact on the way you should write your code. A variable is any named value declared using the var keyword.
© 2013 SAP AG. All rights reserved. 24
Declarations: Variables Are Hoisted!
Understanding the difference between variables and properties is important because it has an impact on the way you should write your code. A variable is any named value declared using the var keyword. When an execution context starts (I.E. a function is called), JavaScript scans the source code in that execution context looking for any use of the var keyword (I.E. variable declarations). Any variables it finds have their names defined immediately – before any statements of that function are executed.
© 2013 SAP AG. All rights reserved. 25
Declarations: Variables Are Hoisted!
Understanding the difference between variables and properties is important because it has an impact on the way you should write your code. A variable is any named value declared using the var keyword. When an execution context starts (I.E. a function is called), JavaScript scans the source code in that execution context looking for any use of the var keyword (I.E. variable declarations). Any variables it finds have their names defined immediately – before any statements of that function are executed. However, the variable will not be assigned a value until execution reaches that statement!
© 2013 SAP AG. All rights reserved. 26
Declarations: Variables Are Hoisted!
Understanding the difference between variables and properties is important because it has an impact on the way you should write your code. A variable is any named value declared using the var keyword. When an execution context starts (I.E. a function is called), JavaScript scans the source code in that execution context looking for any use of the var keyword (I.E. variable declarations). Any variables it finds have their names defined immediately – before any statements of that function are executed. However, the variable will not be assigned a value until execution reaches that statement! // Doing things backwards, but getting away with it (kinda) alert(someNumber); // à undefined. Because of hoisting the variable name is known, but has no value yet var someNumber = 10; // Now assign it a value alert(someNumber); // à 10
© 2013 SAP AG. All rights reserved. 27
Declarations: Variables Are Hoisted!
Understanding the difference between variables and properties is important because it has an impact on the way you should write your code. A variable is any named value declared using the var keyword. When an execution context starts (I.E. a function is called), JavaScript scans the source code in that execution context looking for any use of the var keyword (I.E. variable declarations). Any variables it finds have their names defined immediately – before any statements of that function are executed. However, the variable will not be assigned a value until execution reaches that statement!
This situation is known as "hoisting" because JavaScript behaves is as if all variable declarations are lifted (or hoisted) to the top of the function’s source code.
// Doing things backwards, but getting away with it (kinda) alert(someNumber); // à undefined. Because of hoisting the variable name is known, but has no value yet var someNumber = 10; // Now assign it a value alert(someNumber); // à 10
© 2013 SAP AG. All rights reserved. 28
Declarations: Properties Are Created Sequentially!
A property is created simply by assigning a value to a name. However, unlike variable name declarations, properties are not hoisted. Their creation takes place in a strictly sequentially manner. The property name will remain unknown to JavaScript until execution reaches the statement. Depending on how the property is referenced, this might result in a runtime reference error.
// Doing things backwards and not always getting away with it alert(window.someProperty); // à undefined. The window object is known, but the property name isn't
© 2013 SAP AG. All rights reserved. 29
Declarations: Properties Are Created Sequentially!
A property is created simply by assigning a value to a name. However, unlike variable name declarations, properties are not hoisted. Their creation takes place in a strictly sequentially manner. The property name will remain unknown to JavaScript until execution reaches the statement. Depending on how the property is referenced, this might result in a runtime reference error.
// Doing things backwards and not always getting away with it alert(window.someProperty); // à undefined. The window object is known, but the property name isn't alert(someProperty); // à KABOOM! (Reference error) The unqualified property name is unknown!
© 2013 SAP AG. All rights reserved. 30
Declarations: Properties Are Created Sequentially!
A property is created simply by assigning a value to a name. However, unlike variable name declarations, properties are not hoisted. Their creation takes place in a strictly sequentially manner. The property name will remain unknown to JavaScript until execution reaches the statement. Depending on how the property is referenced, this might result in a runtime reference error.
// Doing things backwards and not always getting away with it alert(window.someProperty); // à undefined. The window object is known, but the property name isn't alert(someProperty); // à KABOOM! (Reference error) The unqualified property name is unknown! someProperty = 10; // This statement both creates the global property and assigns it a value
© 2013 SAP AG. All rights reserved. 31
Declarations: Properties Are Created Sequentially!
A property is created simply by assigning a value to a name. However, unlike variable name declarations, properties are not hoisted. Their creation takes place in a strictly sequentially manner. The property name will remain unknown to JavaScript until execution reaches the statement. Depending on how the property is referenced, this might result in a runtime reference error.
// Doing things backwards and not always getting away with it alert(window.someProperty); // à undefined. The window object is known, but the property name isn't alert(someProperty); // à KABOOM! (Reference error) The unqualified property name is unknown! someProperty = 10; // This statement both creates the global property and assigns it a value alert(someProperty); // à 10
© 2013 SAP AG. All rights reserved. 32
Declarations: Consequences of Hoisting 1/2
Due to the fact that all JavaScript variables are hoisted, the location of a variable’s declaration within the source code of a function is not important.
function test() { var a = 10; for (var i=0; i<5; i++) { console.log("a + i = " + (a + i)); } }
Variable a is both declared and assigned a value in a single statement.
© 2013 SAP AG. All rights reserved. 33
Declarations: Consequences of Hoisting 1/2
Due to the fact that all JavaScript variables are hoisted, the location of a variable’s declaration within the source code of a function is not important.
function test() { var a = 10; for (var i=0; i<5; i++) { console.log("a + i = " + (a + i)); } }
This gives the expected runtime results
© 2013 SAP AG. All rights reserved. 34
Declarations: Consequences of Hoisting 2/2
However due to the effects of hoisting, the location of the first assignment to a variable could have serious consequences for the logic of your coding!
function test() { for (var i=0; i<5; i++) { console.log("a + i = " + (a + i)); } var a = 10; }
Moving the declaration to the end of the function has no impact on whether JavaScript
“knows” the name of this variable…
© 2013 SAP AG. All rights reserved. 35
Declarations: Consequences of Hoisting 2/2
However due to the effects of hoisting, the location of the first assignment to a variable could have serious consequences for the logic of your coding!
function test() { for (var i=0; i<5; i++) { console.log("a + i = " + (a + i)); } var a = 10; }
However, the assignment of the variable’s value has also been moved.
The logic of the coding is now broken!
© 2013 SAP AG. All rights reserved. 36
Declarations: Consequences of Hoisting 2/2
However due to the effects of hoisting, the location of the first assignment to a variable could have serious consequences for the logic of your coding!
function test() { for (var i=0; i<5; i++) { console.log("a + i = " + (a + i)); } var a = 10; }
IMPORTANT! Even though JavaScript knows about all the declared variables in a function before the first statement of the function is executed, the value of those variables will always be undefined until the flow of execution reaches a statement that assigns the variable a value!
Declarations Named and Anonymous Functions Automatic Function Execution
© 2013 SAP AG. All rights reserved. 38
Declarations: Creating Named and Anonymous Functions
A function can be created using syntax similar to that seen in other programming languages such as Java and C. Here, a function object is created that has the explicit name of person.
// Create a named function function person() { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = ["swimming ","cycling"]; var getHobby = function(n) { return firstName + " likes " + hobbies[n]; } }
© 2013 SAP AG. All rights reserved. 39
Declarations: Creating Named and Anonymous Functions
A function can be created using syntax similar to that seen in other programming languages such as Java and C. Here, a function object is created that has the explicit name of person. However, there is a subtle variation that allows a more generic approach to be taken. This is where an anonymous function object is first created, then stored in a variable that happens to be called person. // Create a named function function person() { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = ["swimming ","cycling"]; var getHobby = function(n) { return firstName + " likes " + hobbies[n]; } }
// Create an anonymous function and assign it to // a variable var person = function() { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = ["swimming ","cycling"]; var getHobby = function(n) { return firstName + " likes " + hobbies[n]; } }
© 2013 SAP AG. All rights reserved. 40
Declarations: Creating Named and Anonymous Functions
A function can be created using syntax similar to that seen in other programming languages such as Java and C. Here, a function object is created that has the explicit name of person. However, there is a subtle variation that allows a more generic approach to be taken. This is where an anonymous function object is first created, then stored in a variable that happens to be called person. // Create a named function function person() { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = ["swimming ","cycling"]; var getHobby = function(n) { return firstName + " likes " + hobbies[n]; } }
// Create an anonymous function and assign it to // a variable var person = function() { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = ["swimming ","cycling"]; var getHobby = function(n) { return firstName + " likes " + hobbies[n]; } }
IMPORTANT A JavaScript function is an object like any other object that additionally has “an executable part”.
© 2013 SAP AG. All rights reserved. 41
Automatic Execution of Functions 1/4
As a consequence of a JavaScript function being nothing more than an object that happens to have an executable part, we need some means of distinguishing between the “function as data” and the “function as an executable unit of code”. This is where the invocation operator () is used. Here we see that the function is first defined // Set variable 'person' equal to an anonymous function var person = function(fName,lName,hobbies) { var firstName = fName || ""; var lastName = lName || ""; var hobbies = hobbies || []; return { firstName: firstName, lastName : lastName, hobbies : hobbies } }
© 2013 SAP AG. All rights reserved. 42
Automatic Execution of Functions 2/4
As a consequence of a JavaScript function being nothing more than an object that happens to have an executable part, we need some means of distinguishing between the “function as data” and the “function as an executable unit of code”. This is where the invocation operator () is used. Here we see that the function is first defined // Set variable 'person' equal to an anonymous function var person = function(fName,lName,hobbies) { var firstName = fName || ""; var lastName = lName || ""; var hobbies = hobbies || []; return { firstName: firstName, lastName : lastName, hobbies : hobbies } } // Invoke function person to obtain the required object var someGuy = person("Harry", "Hawk", ["swimming ","cycling"]);
, then in a separate statement, is invoked.
© 2013 SAP AG. All rights reserved. 43
Automatic Execution of Functions 3/4
The previous approach is inconvenient in that we might not care about keeping a reference to the function that generated the person object. Also, the function must be declared and invoked in separate statements. It would be much more convenient if we could have a direct assignment of the required object by invoking the function automatically.
// Set variable 'person' equal to an anonymous function var someGuy = function(fName,lName,hobbies) { var firstName = fName || ""; var lastName = lName || ""; var hobbies = hobbies || []; return { firstName: firstName, lastName : lastName, hobbies : hobbies } }
(
)
First, the entire function definition is placed within parentheses. Here, parentheses are being used as the “grouping operator”
© 2013 SAP AG. All rights reserved. 44
Automatic Execution of Functions 4/4
The previous approach is inconvenient in that we might not care about keeping a reference to the function that generated the person object. Also, the function must be declared and invoked in separate statements. It would be much more convenient if we could have a direct assignment of the required object by invoking the function automatically.
// Set variable 'person' equal to an anonymous function var someGuy = function(fName,lName,hobbies) { var firstName = fName || ""; var lastName = lName || ""; var hobbies = hobbies || []; return { firstName: firstName, lastName : lastName, hobbies : hobbies } }
Second, the anonymous function inside the parentheses is invoked immediately using the invocation operator plus the
relevant parameters
("Harry", "Hawk", ["swimming ","cycling"]);
(
)
Declarations Function Context and Lexical Scope
© 2013 SAP AG. All rights reserved. 46
Function Context 1/2
Each time a JavaScript function is called, a new function context is created. This is a private runtime container that has its own VariableObject.
Global Context: window
document parent top localStorage sessionStorage location history etc...
function() { }
Function Context:
© 2013 SAP AG. All rights reserved. 47
Function Context 1/2
Each time a JavaScript function is called, a new function context is created. This is a private runtime container that has its own VariableObject. The key difference from the global context is that there is no object equivalent to window that would give you access to the function context's VariableObject.
Global Context: window
document parent top localStorage sessionStorage location history etc...
function() { var localVar = "local"; }
Function Context:
localVar
© 2013 SAP AG. All rights reserved. 48
Function Context 1/2
Each time a JavaScript function is called, a new function context is created. This is a private runtime container that has its own VariableObject. The key difference from the global context is that there is no object equivalent to window that would give you access to the function context's VariableObject. This means that you cannot create function properties using the same syntax as for global properties.
Global Context: window
document parent top localStorage sessionStorage location history etc...
function() { var localVar = "local"; }
Function Context:
localVar
© 2013 SAP AG. All rights reserved. 49
Function Context 1/2
Each time a JavaScript function is called, a new function context is created. This is a private runtime container that has its own VariableObject. The key difference from the global context is that there is no object equivalent to window that would give you access to the function context's VariableObject. This means that you cannot create function properties using the same syntax as for global properties.
Global Context: window
document parent top localStorage sessionStorage location history etc...
function() { var localVar = "local"; globalProp = "global"; }
Function Context: globalProp
If you try to create a local property using the syntax seen here, you will end up creating a global property!
localVar
© 2013 SAP AG. All rights reserved. 50
Function Context 2/2
If you wish to create a property that belongs to a function object, then the assignment must identify the local execution context via the special object this.
BUT BE CAREFUL! The execution context to which this refers changes depending on how the function is invoked! (But more about this later)
Global Context: window
document parent top localStorage sessionStorage location history etc...
function() { var localVar = "local"; this.localProp = "local"; }
Function Context:
localVar localProp
© 2013 SAP AG. All rights reserved. 51
Variable and Object Property Visibility
JavaScript does not directly allow you to specify the visibility of an object’s properties. In other words, there is no direct concept of a public or private object property.
© 2013 SAP AG. All rights reserved. 52
Variable and Object Property Visibility
JavaScript does not directly allow you to specify the visibility of an object’s properties. In other words, there is no direct concept of a public or private object property.
As long as you remember to use the var keyword, then all variables declared inside a function will be private to that function's execution context. Remember If you forget to use the var keyword, then you’ll end up creating (or overwriting) a property of the global object!
© 2013 SAP AG. All rights reserved. 53
Variable and Object Property Visibility
JavaScript does not directly allow you to specify the visibility of an object’s properties. In other words, there is no direct concept of a public or private object property.
As long as you remember to use the var keyword, then all variables declared inside a function will be private to that function's execution context. Remember If you forget to use the var keyword, then you’ll end up creating (or overwriting) a property of the global object!
All variables defined as properties of an object are public. Any coding using that object has full access to all of its properties.
© 2013 SAP AG. All rights reserved. 54
Variable and Object Property Visibility
JavaScript does not directly allow you to specify the visibility of an object’s properties. In other words, there is no direct concept of a public or private object property.
As long as you remember to use the var keyword, then all variables declared inside a function will be private to that function's execution context. Remember If you forget to use the var keyword, then you’ll end up creating (or overwriting) a property of the global object!
All variables defined as properties of an object are public. Any coding using that object has full access to all of its properties.
This fact has important consequences for how we design JavaScript objects…
© 2013 SAP AG. All rights reserved. 55
Lexical Scope 1/2
function outer() { }
The ‘lexical scope’ of an object or variable is statically defined by the physical placement of the declaration within the source code. Nested function declarations therefore create scope hierarchies.
Global Context: window
document parent top localStorage sessionStorage location history etc...
Function Context: outer
© 2013 SAP AG. All rights reserved. 56
Lexical Scope 1/2
function outer() { function inner() { } return inner(); }
The ‘lexical scope’ of an object or variable is statically defined by the physical placement of the declaration within the source code. Nested function declarations therefore create scope hierarchies.
Global Context: window
document parent top localStorage sessionStorage location history etc...
Function Context: outer Function Context: inner
© 2013 SAP AG. All rights reserved. 57
Lexical Scope 1/2
function outer() { function inner() { var sillyJoke1 = 'I''ve just started a band called "1023Mb"'; var sillyJoke2 = 'We don''t have a gig yet'; return sillyJoke1 + "\n" + sillyJoke2; } return inner(); }
The ‘lexical scope’ of an object or variable is statically defined by the physical placement of the declaration within the source code. Nested function declarations therefore create scope hierarchies.
Global Context: window
document parent top localStorage sessionStorage location history etc...
Function Context: outer Function Context: inner
sillyJoke1 sillyJoke2
© 2013 SAP AG. All rights reserved. 58
Lexical Scope 2/2
Any variable declared using the var keyword belongs to the lexical scope of the execution context within which it was declared, and is private to that execution context!
Global Context: window
document parent top localStorage sessionStorage location history etc...
function giggle() { var sillyJoke1 = 'I\'ve just started a band called "1023Mb"'; var sillyJoke2 = 'We don\'t have a gig yet'; return sillyJoke1 + "\n" + sillyJoke2; } sillyJoke1; // à Undefined. This variable is not visible outside the scope of the function
Function Context: outer Function Context: inner
sillyJoke1 sillyJoke2
© 2013 SAP AG. All rights reserved. 59
Lexical Scope: Understanding the Meaning of this 1/3
Each time a JavaScript function is invoked, a new function context is created within the scope of the current execution context. This is the runtime container within which (among other things) all the variables used by that function exist. A special object called this gives access to all the variables in your current execution context. // Direct reference to 'this' from code running within the global scope this; // à window
In the above example, a direct reference is made to this from coding outside the scope of a user created function; therefore, this refers to JavaScript’s global scope (in a browser, this will be the window object).
© 2013 SAP AG. All rights reserved. 60
Lexical Scope: Understanding the Meaning of this 2/3
Remember that JavaScript functions are simply objects that “have an executable part”. The value of this always points to a function’s execution context; however, the exact identity of the execution context varies according to how the function is invoked!
function someFun() { return this; } someFun(); // à window. The function was invoked directly, therefore 'this' is bound to the global context
© 2013 SAP AG. All rights reserved. 61
Lexical Scope: Understanding the Meaning of this 2/3
Remember that JavaScript functions are simply objects that “have an executable part”. The value of this always points to a function’s execution context; however, the exact identity of the execution context varies according to how the function is invoked!
function someFun() { return this; } someFun(); // à window. The function was invoked directly, therefore 'this' is bound to the global context
In this case, function someFun() has been called without reference to any other object. This is known as a baseless function call and means that any references within that function to the variable this will refer to the Global Context.
© 2013 SAP AG. All rights reserved. 62
Lexical Scope: Understanding the Meaning of this 3/3
When an object property is defined as a function, then that function is known as a method. In this example, the whatsThis property is a function (or method) belonging to the object myObj. The parent object myObj can now act as the execution context for function whatsThis.
var myObj = { whatsThis : function() { return this; } } // Two different ways of calling method whatsThis(). Both refer to the method via object myObj myObj.whatsThis(); // à myObj -‐ because myObj is the execution context of function whatsThis myObj['whatsThis'](); // à myObj
As long as method whatsThis() is called via the object myObj, then this will resolve to myObj.
© 2013 SAP AG. All rights reserved. 63
Lexical Scope: Flexibility in the Meaning of this
However, it is perfectly possible to call a method using some other object as the execution context. This gives you great flexibility – especially in the area of code reuse. However, you must be very clear in your mind to ensure that the meaning of this resolves to the intended object! For example: var myObj = { whatsThis : function() { return this; } }
© 2013 SAP AG. All rights reserved. 64
Lexical Scope: Flexibility in the Meaning of this
However, it is perfectly possible to call a method using some other object as the execution context. This gives you great flexibility – especially in the area of code reuse. However, you must be very clear in your mind to ensure that the meaning of this resolves to the intended object! For example: var myObj = { whatsThis : function() { return this; } } // Create some other object that contains a method that refers to the whatsThis method of object myObj var someOtherObject = {}; someOtherObject.anotherFunction = myObj.whatsThis; someOtherObject.anotherFunction(); // à someOtherObject. Called from the execution context of someOtherObject
© 2013 SAP AG. All rights reserved. 65
Lexical Scope: Flexibility in the Meaning of this
However, it is perfectly possible to call a method using some other object as the execution context. This gives you great flexibility – especially in the area of code reuse. However, you must be very clear in your mind to ensure that the meaning of this resolves to the intended object! For example: var myObj = { whatsThis : function() { return this; } } // Create some other object that contains a method that refers to the whatsThis method of object myObj var someOtherObject = {}; someOtherObject.anotherFunction = myObj.whatsThis; someOtherObject.anotherFunction(); // à someOtherObject. Called from the execution context of someOtherObject // Create a global variable whose value is a reference to the whatsThis method of object myObj var aGlobalVariable = myObj.whatsThis; aGlobalVariable(); // à window. Called from the global context
© 2013 SAP AG. All rights reserved. 66
Lexical Scope: Flexibility in the Meaning of this
However, it is perfectly possible to call a method using some other object as the execution context. This gives you great flexibility – especially in the area of code reuse. However, you must be very clear in your mind to ensure that the meaning of this resolves to the intended object! For example: var myObj = { whatsThis : function() { return this; } } // Create some other object that contains a method that refers to the whatsThis method of object myObj var someOtherObject = {}; someOtherObject.anotherFunction = myObj.whatsThis; someOtherObject.anotherFunction(); // à someOtherObject. Called from the execution context of someOtherObject // Create a global variable whose value is a reference to the whatsThis method of object myObj var aGlobalVariable = myObj.whatsThis; aGlobalVariable(); // à window. Called from the global context // And just to prove that nothing has changed in the original object... myObj.whatsThis(); // à myObj. Called from the execution context of myObj
© 2013 SAP AG. All rights reserved. 67
Lexical Scope: Deliberate Alteration of the Meaning of this
“Delegation” is a technique by which you can implement dynamic inheritance. This means you can call a method in some object and, for the duration of that method’s execution, you can deliberately alter the value of this. The methods Function.apply() and Function.call() are used here and both take as their first parameter, the object to which this should refer.
var myObj = { whatsThis : function() { return this.a + this.b; // Huh? But properties 'a' and 'b' haven't been defined anywhere... // (Don't worry, we'll sort it out at runtime) } } // Create some other objects that will provide the meaning of 'this' var obj1 = { a:1, b:2 }; var obj2 = { a:3, b:4 };
© 2013 SAP AG. All rights reserved. 68
Lexical Scope: Deliberate Alteration of the Meaning of this
“Delegation” is a technique by which you can implement dynamic inheritance. This means you can call a method in some object and, for the duration of that method’s execution, you can deliberately alter the value of this. The methods Function.apply() and Function.call() are used here and both take as their first parameter, the object to which this should refer.
var myObj = { whatsThis : function() { return this.a + this.b; // Huh? But properties 'a' and 'b' haven't been defined anywhere... // (Don't worry, we'll sort it out at runtime) } } // Create some other objects that will provide the meaning of 'this' var obj1 = { a:1, b:2 }; var obj2 = { a:3, b:4 }; // Invoke method whatsThis using different objects for the value of 'this' myObj.whatsThis.apply(obj1); // à 3 because obj1 provides the values for 'a' and 'b' via object 'this' myObj.whatsThis.call(obj2); // à 7 because obj2 provides the values for 'a' and 'b' via object 'this'
© 2013 SAP AG. All rights reserved. 69
Lexical Scope: Deliberate Alteration of the Meaning of this
“Delegation” is a technique by which you can implement dynamic inheritance. This means you can call a method in some object and, for the duration of that method’s execution, you can deliberately alter the value of this. The methods Function.apply() and Function.call() are used here and both take as their first parameter, the object to which this should refer.
var myObj = { whatsThis : function() { return this.a + this.b; // Huh? But properties 'a' and 'b' haven't been defined anywhere... // (Don't worry, we'll sort it out at runtime) } } // Create some other objects that will provide the meaning of 'this' var obj1 = { a:1, b:2 }; var obj2 = { a:3, b:4 }; // Invoke method whatsThis using different objects for the value of 'this' myObj.whatsThis.apply(obj1); // à 3 because obj1 provides the values for 'a' and 'b' via object 'this' myObj.whatsThis.call(obj2); // à 7 because obj2 provides the values for 'a' and 'b' via object 'this'
Within each execution context of method whatsThis(), the value of this is temporarily reassigned to the object passed as the first parameter to either apply() or call().
© 2013 SAP AG. All rights reserved. 70
Lexical Scope: Variables Declared Inside Functions 1/2
Global Context: window
When one function (known as the “outer” function) has another function (known as the “inner” function) declared within it, the scope of the outer function is always accessible to the inner function. This is an example of ‘scope chaining’ and it applies even if the “outer” function is the Global Context.
document parent top localStorage sessionStorage location history etc...
var person = function() { var firstName = "Harry"; var lastName = "Hawk"; }
© 2013 SAP AG. All rights reserved. 71
Lexical Scope: Variables Declared Inside Functions 1/2
Global Context: window Function Context: person()
firstName lastName
When one function (known as the “outer” function) has another function (known as the “inner” function) declared within it, the scope of the outer function is always accessible to the inner function. This is an example of ‘scope chaining’ and it applies even if the “outer” function is the Global Context.
document parent top localStorage sessionStorage location history etc...
var person = function() { var firstName = "Harry"; var lastName = "Hawk"; }
All variables and properties of the Global Context are visible to the coding running inside function person.
© 2013 SAP AG. All rights reserved. 72
Lexical Scope: Variables Declared Inside Functions 2/2
Global Context: window Function Context: person()
var person = function() { var firstName = "Harry"; var lastName = "Hawk"; }
firstName lastName
The scopes of two sibling functions are not visible to each other, neither can code running in the scope of an outer function gain direct access to the variables within the scope of its inner functions.
document parent top localStorage sessionStorage location history etc...
Function Context: vehicle()
make model
var vehicle = function() { var make = "Honda"; var model = "Civic"; }
Declarations Use of the return statement in functions
© 2013 SAP AG. All rights reserved. 74
Using the return Statement
Generally speaking, a function is called because you require some value to be calculated that will then take the place of the function call in your sequence of instructions. (This is known as “referential transparency”, but more about that later).
JavaScript uses the keyword return to define two things: • An exit point. If present, return is always the last statement executed by a function. • The value to be returned to the calling program
function doSomething(a,b) { if (typeof a === 'number' && typeof b === 'number') { return a * b; } else { return a + b; } }
© 2013 SAP AG. All rights reserved. 75
Using the return Statement
Generally speaking, a function is called because you require some value to be calculated that will then take the place of the function call in your sequence of instructions. (This is known as “referential transparency”, but more about that later).
JavaScript uses the keyword return to define two things: • An exit point. If present, return is always the last statement executed by a function. • The value to be returned to the calling program
function doSomething(a,b) { if (typeof a === 'number' && typeof b === 'number') { return a * b; } else { return a + b; } }
Whilst it is perfectly possible for a function to use multiple return statements, this should be avoided as a matter of good coding practice. In terms of unit testing and quality assurance of code, a function should only ever have one exit point.
© 2013 SAP AG. All rights reserved. 76
Using the return Statement
Generally speaking, a function is called because you require some value to be calculated that will then take the place of the function call in your sequence of instructions. (This is known as “referential transparency”, but more about that later).
JavaScript uses the keyword return to define two things: • An exit point. If present, return is always the last statement executed by a function. • The value to be returned to the calling program
function doSomething(a,b) { var answer = a + b; if (typeof a === 'number' && typeof b === 'number') { answer = a * b; } return answer; }
This coding structure is preferable because the function now has one and only one exit point.
© 2013 SAP AG. All rights reserved. 77
Functions where return isn't needed
Some functions performs tasks that specifically rely on side-effect behaviour. Therefore, the desired outcome of calling the function is the behaviour of the side-effect, rather than some explicit value returned from the function. In this case, there is no need to use the return statement. If the return keyword is either missing or used with no parameter, then the value undefined will be returned to the calling program.
© 2013 SAP AG. All rights reserved. 78
Functions where return isn't needed
Some functions performs tasks that specifically rely on side-effect behaviour. Therefore, the desired outcome of calling the function is the behaviour of the side-effect, rather than some explicit value returned from the function. In this case, there is no need to use the return statement. If the return keyword is either missing or used with no parameter, then the value undefined will be returned to the calling program.
function callLater(fun, args, ctx) { setTimeout(function() { fun.apply(ctx,args); }, 2000); }
In this case, the callLater() function is being called because it has desirable side-effects – it will call the specified function after a delay of 2000 milliseconds.
© 2013 SAP AG. All rights reserved. 79
Functions where return isn't needed
Some functions performs tasks that specifically rely on side-effect behaviour. Therefore, the desired outcome of calling the function is the behaviour of the side-effect, rather than some explicit value returned from the function. In this case, there is no need to use the return statement. If the return keyword is either missing or used with no parameter, then the value undefined will be returned to the calling program.
function callLater(fun, args, ctx) { setTimeout(function() { fun.apply(ctx,args); }, 2000); } var value = callLater(alert, ['hello']); (After a 2 second delay)
In this case, the callLater() function is being called because it has desirable side-effects – it will call the specified function after a delay of 2000 milliseconds.
© 2013 SAP AG. All rights reserved. 80
Functions where return isn't needed
Some functions performs tasks that specifically rely on side-effect behaviour. Therefore, the desired outcome of calling the function is the behaviour of the side-effect, rather than some explicit value returned from the function. In this case, there is no need to use the return statement. If the return keyword is either missing or used with no parameter, then the value undefined will be returned to the calling program.
function callLater(fun, args, ctx) { setTimeout(function() { fun.apply(ctx,args); }, 2000); } var value = callLater(alert, ['hello']); value; // à undefined (After a 2 second delay)
In this case, the callLater() function is being called because it has desirable side-effects – it will call the specified function after a delay of 2000 milliseconds. In this particular case, the return value of function callLater() is not important.
© 2013 SAP AG. All rights reserved. 81
Return Values from Functions: Returning this 1/2
It is also possible that a function returns a reference to its own execution scope. For instance, if you are referencing an HTML button in a browser window, then although the following code is perfectly correct, it is more verbose than is necessary.
var myButton = jQuery('#myButton'); myButton.text('Click here'); myButton.css('color', '#F80'); myButton.bind('click', function() { alert('Hi there!'); });
© 2013 SAP AG. All rights reserved. 82
Return Values from Functions: Returning this 2/2
Frameworks such as jQuery and SAPUI5 are setup so that functions handling DOM elements return a reference to their own execution scope. In other words, these functions return a reference to the DOM element currently being manipulated, identified by the variable this. Returning this allows you to concatenate method calls in a technique know either as “cascading” or “method chaining”. jQuery('#myButton') .text('Click here') .css('color', '#F80') .bind('click', function() { alert('Hi there!'); });
Declarations Scope Chaining and Variable Lifespan
© 2013 SAP AG. All rights reserved. 84
Scope Chaining 1/2
var person = function() { var firstName = "Harry"; var lastName = "Hawk"; }
Within the person object, we have now created an inner function called getHobby(). Through scope chaining, the coding in getHobby() can access the variables firstName and lastName, but the coding in person() cannot directly access the hobbies array.
Global Context: window Function Context: person()
document parent top localStorage sessionStorage location history etc...
Function Context: getHobby()
hobbies
var getHobby = function(n) { var hobbies = ["swimming ","cycling"]; return firstName + " likes " + hobbies[n]; }
firstName lastName
© 2013 SAP AG. All rights reserved. 85
Scope Chaining 2/2
var person = function() { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = ["swimming ","cycling"]; }
From a software design perspective, this is not a good situation since the coding in function person() will probably need access to the hobbies array. However, scope chaining allows us to move the declaration of the hobbies array out of the getHobby() function and into the person() function without any problem.
Global Context: window Function Context: person()
document parent top localStorage sessionStorage location history etc...
Function Context: getHobby()
hobbies
var getHobby = function(n) { return firstName + " likes " + hobbies[n]; }
firstName lastName
© 2013 SAP AG. All rights reserved. 86
Scope Chaining and Variable Lifespan 1/3
All variables declared inside a function are private to that function's scope, making them invisible to the code that called the function.
var someGuy = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; })();
The variables firstName, lastName and hobbies are visible only within the scope of this anonymous function.
Notice that this anonymous function is invoked automatically.
© 2013 SAP AG. All rights reserved. 87
Scope Chaining and Variable Lifespan 1/3
All variables declared inside a function are private to that function's scope, making them invisible to the code that called the function. However, these private variables can be exposed by returning an object that references them.
var someGuy = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })();
© 2013 SAP AG. All rights reserved. 88
Scope Chaining and Variable Lifespan 1/3
All variables declared inside a function are private to that function's scope, making them invisible to the code that called the function. However, these private variables can be exposed by returning an object that references them.
var someGuy = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })();
© 2013 SAP AG. All rights reserved. 89
Scope Chaining and Variable Lifespan 1/3
All variables declared inside a function are private to that function's scope, making them invisible to the code that called the function. However, these private variables can be exposed by returning an object that references them.
var someGuy = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })(); someGuy.firstName; // à Harry someGuy.lastName; // à Hawk
© 2013 SAP AG. All rights reserved. 90
Scope Chaining and Variable Lifespan 2/3
In addition to returning a simple reference, scope chaining allows you to return an inner function that references a variable in the scope of the outer function.
var someGuy = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })();
© 2013 SAP AG. All rights reserved. 91
Scope Chaining and Variable Lifespan 2/3
In addition to returning a simple reference, scope chaining allows you to return an inner function that references a variable in the scope of the outer function. In this example, methods getHobby and setHobby of the returned object are inner functions that reference the hobbies variable in the scope of the outer anonymous function. var someGuy = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })();
© 2013 SAP AG. All rights reserved. 92
Scope Chaining and Variable Lifespan 2/3
In addition to returning a simple reference, scope chaining allows you to return an inner function that references a variable in the scope of the outer function. In this example, methods getHobby and setHobby of the returned object are inner functions that reference the hobbies variable in the scope of the outer anonymous function. var someGuy = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })(); someGuy.getHobby(1); // à "cycling" someGuy.setHobby("hiking"); // à [ "swimming", "cycling", "hiking"]
© 2013 SAP AG. All rights reserved. 93
Scope Chaining and Variable Lifespan 3/3
You might look at this coding and wonder why it works; after all, when a function terminates, don’t all the variables within that function’s scope cease to exist? Here we’re using an anonymous function to generate a person object. The returned object is stored in a variable called someGuy, then the anonymous function terminates and its scope disappears... var someGuy = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })(); someGuy.getHobby(1); // à "cycling" someGuy.setHobby("hiking"); // à [ "swimming", "cycling", "hiking"]
© 2013 SAP AG. All rights reserved. 94
Scope Chaining and Variable Lifespan 3/3
You might look at this coding and wonder why it works; after all, when a function terminates, don’t all the variables within that function’s scope cease to exist? Here we’re using an anonymous function to generate a person object. The returned object is stored in a variable called someGuy, then the anonymous function terminates and its scope disappears... var someGuy = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })(); someGuy.getHobby(1); // à "cycling" someGuy.setHobby("hiking"); // à [ "swimming", "cycling", "hiking"]
Yet, in spite of this apparent contradiction, the values belonging to the scope of a
terminated function are still alive and well…
Declarations Creating Public and Private Object Properties
© 2013 SAP AG. All rights reserved. 96
Creating Public and Private Object Properties: Closure
As soon as a function is called, the lexical scope of the calling function (which could well be the Global Context) must be preserved. When an inner function makes reference to a variable in the outer function’s lexical scope, the inner function is said to have “closed over” that variable. Any “closed over” variables will not be garbage collected when the outer function terminates.
Anonymous Function Context (Invoked Automatically)
Returned anonymous object
Function Context: setHobby()
Function Context: getHobby()
hobbies firstName lastName
© 2013 SAP AG. All rights reserved. 97
Creating Public and Private Object Properties: Closure
As soon as a function is called, the lexical scope of the calling function (which could well be the Global Context) must be preserved. When an inner function makes reference to a variable in the outer function’s lexical scope, the inner function is said to have “closed over” that variable. Any “closed over” variables will not be garbage collected when the outer function terminates.
Returned anonymous object
Function Context: setHobby()
Function Context: getHobby()
The outer function now terminates, but the “closed over” over variables are preserved and remain accessible in a container known as a closure.
Closure
hobbies firstName lastName
© 2013 SAP AG. All rights reserved. 98
Creating Public and Private Object Properties: Closure
As soon as a function is called, the lexical scope of the calling function (which could well be the Global Context) must be preserved. When an inner function makes reference to a variable in the outer function’s lexical scope, the inner function is said to have “closed over” that variable. Any “closed over” variables will not be garbage collected when the outer function terminates.
The outer function now terminates, but the “closed over” over variables are preserved and remain accessible in a container known as a closure. The use of closures is considered a fundamental design technique in many scripting languages such JavaScript, Python, Ruby and SmallTalk, or functional programming languages such as Haskell and OCaml. Closures are also possible in Java by means of anonymous inner functions.
Returned anonymous object
Function Context: setHobby()
Function Context: getHobby()
Closure
hobbies firstName lastName
© 2013 SAP AG. All rights reserved. 99
Creating Public and Private Object Properties: Closure
As soon as a function is called, the lexical scope of the calling function (which could well be the Global Context) must be preserved. When an inner function makes reference to a variable in the outer function’s lexical scope, the inner function is said to have “closed over” that variable. Any “closed over” variables will not be garbage collected when the outer function terminates.
The outer function now terminates, but the “closed over” over variables are preserved and remain accessible in a container known as a closure. The use of closures is considered a fundamental design technique in many scripting languages such JavaScript, Python, Ruby and SmallTalk, or functional programming languages such as Haskell and OCaml. Closures are also possible in Java by means of anonymous inner functions.
ABAP has no concept of closures…
Returned anonymous object
Function Context: setHobby()
Function Context: getHobby()
Closure
hobbies firstName lastName
© 2013 SAP AG. All rights reserved. 100
Closure and The Module Pattern 1/3
Remember that in JavaScript, there is no explicit mechanism to define the visibility an object property. However, we often find ourselves needing to create an object in which some properties are public and some are private (accessible only through getter and setter methods). The "Module Pattern" is where a closure is used to act as a container for these “private” properties.
var person = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; })();
© 2013 SAP AG. All rights reserved. 101
Closure and The Module Pattern 1/3
Remember that in JavaScript, there is no explicit mechanism to define the visibility an object property. However, we often find ourselves needing to create an object in which some properties are public and some are private (accessible only through getter and setter methods). The "Module Pattern" is where a closure is used to act as a container for these “private” properties.
var person = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; })();
Anonymous Function Context (Invoked Automatically)
hobbies firstName lastName
The execution scope of the outer function will become the closure that contains those variables we wish to keep private.
© 2013 SAP AG. All rights reserved. 102
Closure and The Module Pattern 2/3
The outer function then returns an anonymous object.
var person = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { } })();
Anonymous Function Context (Invoked Automatically)
Returned Anonymous Object
hobbies firstName lastName
© 2013 SAP AG. All rights reserved. 103
Closure and The Module Pattern 2/3
The outer function then returns an anonymous object. The properties of this anonymous object “close over” the variables in the outer function’s scope.
var person = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, } })();
Anonymous Function Context (Invoked Automatically)
Returned Anonymous Object
hobbies firstName lastName
© 2013 SAP AG. All rights reserved. 104
Closure and The Module Pattern 3/3
The anonymous object also returns two inner functions that both “close over” the same array in the outer function’s scope.
var person = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })();
Anonymous Function Context (Invoked Automatically)
Returned Anonymous Object
hobbies firstName lastName
© 2013 SAP AG. All rights reserved. 105
Closure and The Module Pattern 3/3
The anonymous object also returns two inner functions that both “close over” the same array in the outer function’s scope. When the outer function terminates, any “closed over” variables are not garbage collected. The closure acts as the container within which all our “private” variables live.
var person = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })();
Returned Anonymous Object
Function Context: setHobby()
Function Context: getHobby()
Closure
hobbies firstName lastName
© 2013 SAP AG. All rights reserved. 106
Closure and The Module Pattern 3/3
The anonymous object also returns two inner functions that both “close over” the same array in the outer function’s scope. When the outer function terminates, any “closed over” variables are not garbage collected. The closure acts as the container within which all our “private” variables live.
var person = (function () { var firstName = "Harry"; var lastName = "Hawk"; var hobbies = [ "swimming", "cycling" ]; return { firstName: firstName, lastName : lastName, getHobby : function(n) { return hobbies[n]; }, setHobby : function(h) { hobbies.push(h); } } })();
Returned Anonymous Object
Function Context: setHobby()
Function Context: getHobby()
Closure
hobbies firstName lastName
So even though JavaScript has no explicit means of defining the visibility of object properties, we can use a closure as a private container within which we can hide any number of properties.
(used to create a private scope)
© 2013 SAP AG. All rights reserved. 107
Appendix: Busting Some Closure Myths
There are many misconceptions surrounding closures, and each item in the following list is wrong! Do not believe anyone who tries to convince you that: • Closures are only created by calling inner functions
No. A closure is created as soon as a function is called. It does not matter whether an outer function calls an inner function, or a function is called from the global context: a closure is created whenever a function is called.
• Closures are created only if an outer function returns an inner function No. A closure is created independently of whether the outer function use the return keyword or not
• The value of "closed over" variables become fixed once a closure is created No. The scope of the outer function is preserved and any closed over variables are references to real, mutable objects, not references to static values
• Closures can only be created by anonymous functions Hmmm, really? Go directly to jail. Do not pass Go. Do not collect £/$/€ 200
• Closures cause memory leaks Earlier versions of Internet Explorer were famous for their memory leaks and the use of closures usually got the blame. In reality, the usual culprit was a situation in which a function referenced a DOM element, and then an attribute of that same DOM element referenced a variable in the lexical scope of the function, creating a circular reference. Its actually very difficult to create a circular references between a variable in a closure and the coding that references the closed over variables
© 2013 SAP AG. All rights reserved. 108
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP AG. The information contained herein may be changed without prior notice.
Some software products marketed by SAP AG and its distributors contain proprietary software components of other software vendors.
Microsoft, Windows, Excel, Outlook, PowerPoint, Silverlight, and Visual Studio are registered trademarks of Microsoft Corporation.
IBM, DB2, DB2 Universal Database, System i, System i5, System p, System p5, System x, System z, System z10, z10, z/VM, z/OS, OS/390, zEnterprise, PowerVM, Power Architecture, Power Systems, POWER7, POWER6+, POWER6, POWER, PowerHA, pureScale, PowerPC, BladeCenter, System Storage, Storwize, XIV, GPFS, HACMP, RETAIN, DB2 Connect, RACF, Redbooks, OS/2, AIX, Intelligent Miner, WebSphere, Tivoli, Informix, and Smarter Planet are trademarks or registered trademarks of IBM Corporation.
Linux is the registered trademark of Linus Torvalds in the United States and other countries.
Adobe, the Adobe logo, Acrobat, PostScript, and Reader are trademarks or registered trademarks of Adobe Systems Incorporated in the United States and other countries.
Oracle and Java are registered trademarks of Oracle and its affiliates.
UNIX, X/Open, OSF/1, and Motif are registered trademarks of the Open Group.
Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, and MultiWin are trademarks or registered trademarks of Citrix Systems Inc.
HTML, XML, XHTML, and W3C are trademarks or registered trademarks of W3C®, World Wide Web Consortium, Massachusetts Institute of Technology.
Apple, App Store, iBooks, iPad, iPhone, iPhoto, iPod, iTunes, Multi-Touch, Objective-C, Retina, Safari, Siri, and Xcode are trademarks or registered trademarks of Apple Inc.
IOS is a registered trademark of Cisco Systems Inc.
RIM, BlackBerry, BBM, BlackBerry Curve, BlackBerry Bold, BlackBerry Pearl, BlackBerry Torch, BlackBerry Storm, BlackBerry Storm2, BlackBerry PlayBook, and BlackBerry App World are trademarks or registered trademarks of Research in Motion Limited.
© 2014 SAP AG. All rights reserved.
Google App Engine, Google Apps, Google Checkout, Google Data API, Google Maps, Google Mobile Ads, Google Mobile Updater, Google Mobile, Google Store, Google Sync, Google Updater, Google Voice, Google Mail, Gmail, YouTube, Dalvik and Android are trademarks or registered trademarks of Google Inc.
INTERMEC is a registered trademark of Intermec Technologies Corporation.
Wi-Fi is a registered trademark of Wi-Fi Alliance.
Bluetooth is a registered trademark of Bluetooth SIG Inc.
Motorola is a registered trademark of Motorola Trademark Holdings LLC.
Computop is a registered trademark of Computop Wirtschaftsinformatik GmbH.
SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP BusinessObjects Explorer, StreamWork, SAP HANA, and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and other countries.
Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius, and other Business Objects products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of Business Objects Software Ltd. Business Objects is an SAP company.
Sybase and Adaptive Server, iAnywhere, Sybase 365, SQL Anywhere, and other Sybase products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of Sybase Inc. Sybase is an SAP company.
Crossgate, m@gic EDDY, B2B 360°, and B2B 360° Services are registered trademarks of Crossgate AG in Germany and other countries. Crossgate is an SAP company.
All other product and service names mentioned are the trademarks of their respective companies. Data contained in this document serves informational purposes only. National product specifications may vary.
The information in this document is proprietary to SAP. No part of this document may be reproduced, copied, or transmitted in any form or for any purpose without the express prior written permission of SAP AG.
© 2013 SAP AG. All rights reserved. 109
© 2014 SAP AG. Alle Rechte vorbehalten.
Weitergabe und Vervielfältigung dieser Publikation oder von Teilen daraus sind, zu welchem Zweck und in welcher Form auch immer, ohne die ausdrückliche schriftliche Genehmigung durch SAP AG nicht gestattet. In dieser Publikation enthaltene Informationen können ohne vorherige Ankündigung geändert werden.
Die von SAP AG oder deren Vertriebsfirmen angebotenen Softwareprodukte können Softwarekomponenten auch anderer Softwarehersteller enthalten.
Microsoft, Windows, Excel, Outlook, und PowerPoint sind eingetragene Marken der Microsoft Corporation.
IBM, DB2, DB2 Universal Database, System i, System i5, System p, System p5, System x, System z, System z10, z10, z/VM, z/OS, OS/390, zEnterprise, PowerVM, Power Architecture, Power Systems, POWER7, POWER6+, POWER6, POWER, PowerHA, pureScale, PowerPC, BladeCenter, System Storage, Storwize, XIV, GPFS, HACMP, RETAIN, DB2 Connect, RACF, Redbooks, OS/2, AIX, Intelligent Miner, WebSphere, Tivoli, Informix und Smarter Planet sind Marken oder eingetragene Marken der IBM Corporation.
Linux ist eine eingetragene Marke von Linus Torvalds in den USA und anderen Ländern.
Adobe, das Adobe-Logo, Acrobat, PostScript und Reader sind Marken oder eingetragene Marken von Adobe Systems Incorporated in den USA und/oder anderen Ländern.
Oracle und Java sind eingetragene Marken von Oracle und/oder ihrer Tochtergesellschaften.
UNIX, X/Open, OSF/1 und Motif sind eingetragene Marken der Open Group.
Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame und MultiWin sind Marken oder eingetragene Marken von Citrix Systems, Inc.
HTML, XML, XHTML und W3C sind Marken oder eingetragene Marken des W3C®, World Wide Web Consortium, Massachusetts Institute of Technology.
Apple, App Store, iBooks, iPad, iPhone, iPhoto, iPod, iTunes, Multi-Touch, Objective-C, Retina, Safari, Siri und Xcode sind Marken oder eingetragene Marken der Apple Inc.
IOS ist eine eingetragene Marke von Cisco Systems Inc.
RIM, BlackBerry, BBM, BlackBerry Curve, BlackBerry Bold, BlackBerry Pearl, BlackBerry Torch, BlackBerry Storm, BlackBerry Storm2, BlackBerry PlayBook und BlackBerry App World sind Marken oder eingetragene Marken von Research in Motion Limited.
Google App Engine, Google Apps, Google Checkout, Google Data API, Google Maps, Google Mobile Ads, Google Mobile Updater, Google Mobile, Google Store, Google Sync, Google Updater, Google Voice, Google Mail, Gmail, YouTube, Dalvik und Android sind Marken oder eingetragene Marken von Google Inc.
INTERMEC ist eine eingetragene Marke der Intermec Technologies Corporation.
Wi-Fi ist eine eingetragene Marke der Wi-Fi Alliance.
Bluetooth ist eine eingetragene Marke von Bluetooth SIG Inc.
Motorola ist eine eingetragene Marke von Motorola Trademark Holdings, LLC.
Computop ist eine eingetragene Marke der Computop Wirtschaftsinformatik GmbH.
SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP BusinessObjects Explorer, StreamWork, SAP HANA und weitere im Text erwähnte SAP-Produkte und -Dienstleistungen sowie die entsprechenden Logos sind Marken oder eingetragene Marken der SAP AG in Deutschland und anderen Ländern.
Business Objects und das Business-Objects-Logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius und andere im Text erwähnte Business-Objects-Produkte und -Dienstleistungen sowie die entsprechenden Logos sind Marken oder eingetragene Marken der Business Objects Software Ltd. Business Objects ist ein Unternehmen der SAP AG.
Sybase und Adaptive Server, iAnywhere, Sybase 365, SQL Anywhere und weitere im Text erwähnte Sybase-Produkte und -Dienstleistungen sowie die entsprechenden Logos sind Marken oder eingetragene Marken der Sybase Inc. Sybase ist ein Unternehmen der SAP AG.
Crossgate, m@gic EDDY, B2B 360°, B2B 360° Services sind eingetragene Marken der Crossgate AG in Deutschland und anderen Ländern. Crossgate ist ein Unternehmen der SAP AG.
Alle anderen Namen von Produkten und Dienstleistungen sind Marken der jeweiligen Firmen. Die Angaben im Text sind unverbindlich und dienen lediglich zu Informationszwecken. Produkte können länderspezifische Unterschiede aufweisen.
Die in dieser Publikation enthaltene Information ist Eigentum der SAP. Weitergabe und Vervielfältigung dieser Publikation oder von Teilen daraus sind, zu welchem Zweck und in welcher Form auch immer, nur mit ausdrücklicher schriftlicher Genehmigung durch SAP AG gestattet.