Act III function expression function optional name parameters Wrapped in parens Zero or more names Separated by comma body Wrapped in curly braces Zero or more statements function ID: 586696
Download Presentation The PPT/PDF document "Function the Ultimate" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
Function the Ultimate
Act IIISlide2
function expression
function
optional name
parameters
Wrapped in
parens
Zero or more names
Separated by
,
comma
body
Wrapped in curly braces
Zero or more statementsSlide3
function expressionProduces an instance of a function object.
Function objects are first class.
May be passed as an argument to a function
May be returned from a function
May assigned to a variable
May be stored in an object or array
Function objects inherit from
Function.prototype
.Slide4
function statement
function
mandatory name
parameters
Wrapped in
parens
Zero or more names
Separated by
,
comma
body
Wrapped in curly braces
Zero or more statementsSlide5
function statement
The
function
statement is a short-hand for a
var
statement with a function value.
function
foo
() {}
expands to
var
foo
= function
foo
() {};
which further expands to
var
foo
= undefined;
foo
= function
foo
() {};
It all gets hoisted to the top of the function.Slide6
function expressionv
function
statement
If the first token in a statement is
function
, then it is a function statement.Slide7
ScopeA variable declared in a block is not visible outside of the block.Slide8
Variables
const
statement makes variables in block. Prohibits assignment to the variable. Not in IE.
let
statement makes variables in block. Not in IE.
var
statement makes variables in functions. Use
var
if it must run in IE.
Do not use both
var
and
let
.Slide9
Return statement
return
expression
;
or
return;
If there is no
expression
, then the return value is
undefined
.
Except for constructors, whose default return value is
this
.Slide10
InvocationThe ()
suffix operator surrounding zero or more comma separated arguments.
The arguments will be bound to parameters.
A parameter is a variable that is initialized by the caller.Slide11
InvocationIf a function is called with too many arguments, the extra arguments are ignored.If a function is called with too few arguments, the missing values will be
undefined
. Other defaults are possible:
function foo(bar = 0) {...}
There is no implicit type checking on the arguments.Slide12
Variable number of arguments: ...All remaining arguments are assembled into an array.
function add(a, b) {
return a + b;
}
function sum(...numbers) {
return
numbers.reduce
(add);
}
var
ten = sum(1, 2, 3, 4); Slide13
Two pseudo parametersarguments
this
Neither is recommended.Slide14
arguments
When a function is invoked, in addition to its parameters, it also gets a special parameter called
arguments
.
It contains all of the arguments from the invocation.
It is an array-like object.
arguments.length
is the number of arguments passed.
Totally obsolete. Use
...
instead.Slide15
thisThe
this
parameter contains a reference to the object of invocation.
this
allows a method to know what object it is concerned with.
this
allows a single function object to service many objects.
this
is key to prototypal inheritance.Slide16
InvocationThere are four ways to call a function:
Function form
functionObject
(
arguments
)
Method form
thisObject
.
methodName
(
arguments
)
thisObject
["
methodName
"](
arguments
)
Constructor form
new
FunctionObject
(
arguments
)
Apply form
functionObject
.apply
(
thisObject
,[
arguments
])Slide17
Method formthisObject
.
methodName
(
arguments
)
thisObject
[
methodName
](
arguments
)
When a function is called in the method form,
this
is set to
thisObject
, the object of interest, containing or inheriting the function.
This allows methods to have a reference to the object of interest.Slide18
Function formfunctionObject
(
arguments
)
When a function is called in the function form,
this
is not set to an object of interest.Slide19
Constructor form
new
FunctionValue
(
arguments
)
When a function is called with the
new
operator, a new object is created and assigned to
this
.
If there is not an explicit return value, then
this
will be returned.
Used in the
Pseudoclassical
style.Slide20
new prefix operator
Function.prototype.new
=
function new(...
args
) {
var
that =
Object
.create
(
this.prototype
);
var
result =
this.apply
(that,
args
);
return (
typeof
result === "object"
&& result !== null
)
? result
: that;
}
;Slide21
Apply formfunctionObject
.apply
(
thisObject
,
arguments
)
functionObject
.call
(
thisObject
,
argument…
)
A function’s
apply
or
call
method allows for calling the function, explicitly specifying
thisObject
.
It can also take an array of parameters or a sequence of parameters.Slide22
this
this
is an bonus parameter. Its value depends on the calling form.
this
gives methods access to their objects.
this
is bound at invocation time.
Invocation form
this
function
the global object
undefined
method
the object
constructor
the new object
apply
argumentSlide23
RecursionWhen a function calls itself.Slide24
The Little Lisperhttp://javascript.crockford.com/little.htmlSlide25
The Little Schemerhttp://javascript.crockford.com/little.htmlSlide26
Tennent’s Principle of Correspondence
//
result
: variable
function factorial(n) {
var
result
= 1;
while (n > 1) {
result
*= n;
n -= 1;
}
return
result
;
}
//
result
: parameter
function factorial(n) {
return
(
function (
result
) {
while (n > 1) {
result
*= n;
n -= 1;
}
return
result
;
}(1)
)
;
}Slide27
Tennent’s Principle of Correspondence
expression
(
function () {
return
expression
;
}
())
Except:
this arguments
break continue return
Any expression or block of statements can be wrapped in an immediately invoked function without changing meaning…Slide28
ClosureLexical ScopingStatic ScopingFunctions can nest.
Functions are values.Slide29
ClosureThe context of an inner function includes the scope of the outer function.
An inner function enjoys that context even after
the outer
functions have returned.
Function scope works like block scope.Slide30
Block Scope
{
let a;
{
let b;
…
a
…
… b …
}
… a …
}Slide31
Function Scope
function
green
() {
let a;
function
yellow
() {
let b;
…
a
…
… b …
}
… a …
}Slide32
Function Scope
function
green
() {
let a;
function
yellow
() {
let b;
…
a
…
… b …
}
… a …
}
aSlide33
Closure
function
green
() {
let a;
function
yellow
() {
let b;
…
a
…
… b …
}
… a …
}
a
bSlide34
Lisp [1958]dynamic scopenested functionsfunction values
Algol
60 [1960]
lexical scope
nested functions
functions are not values
C [1972]
lexical scope
functions cannot nest
functions are valuesSlide35
The inner function can survive the outer function
function
green
() {
let a;
return
function
yellow() {
let b;
…
a
…
… b …
}
… a …
}Slide36
Global
let names = [
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"
];
let
digit_name
=
function (n) {
return
names
[n];
}
;
alert(
digit_name
(3)); // "three"Slide37
Slow
let
digit_name
=
function (n) {
var
names = [
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"
];
return names[n];
}
;
alert(
digit_name
(3)); // "three"Slide38
Closure
let
digit_name
= (
function (n) {
var
names = [
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"
];
return
function (n) {
return
names
[n];
}
;
}
());
alert(
digit_name
(3)); // "three"Slide39
Start Over
let names = [
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"
];
let
digit_name
=
function (n) {
return
names
[n];
}
;
alert(
digit_name
(3)); // "three"Slide40
Immediate function returns a function
let names = [
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"
];
let
digit_name
= (
function () {
return
function (n) {
return
names
[n];
}
;
}
());
alert(
digit_name
(3)); // "three"Slide41
Closure
let
digit_name
= (
function () {
var
names = [
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"
];
return
function (n) {
return
names
[n];
}
;
}
());
alert(
digit_name
(3)); // "three"Slide42
function
fade
(id) {
const
dom
=
document.getElementById
(id);
let level = 1;
function
step
() {
const
h =
level
.toString
(16);
dom
.style.backgroundColor
=
"#FFFF" + h + h;
if (
level
< 15) {
level
+= 1;
setTimeout
(
step
, 100);
}
}
setTimeout
(step, 100);
}Slide43
Pseudoclassical
function
Gizmo
(id) {
this.id = id;
}
Gizmo.prototype.toString
=
function () {
return "gizmo " + this.id;
}
;Slide44
prototype
function
Gizmo
(id) {
this.id = id;
}
constructor
toString
function
prototype
constructor
Gizmo
ObjectSlide45
prototype
function
Gizmo
(id) {
this.id = id;
}
Gizmo.prototype.toString
=
function () {
return "gizmo " + this.id;
}
;
constructor
toString
function
prototype
constructor
toString
function
Gizmo
ObjectSlide46
prototype
function
Gizmo
(id) {
this.id = id;
}
Gizmo.prototype.toString
=
function () {
return "gizmo " + this.id;
}
;
constructor
toString
function
prototype
constructor
toString
function
Gizmo
ObjectSlide47
function
Gizmo
(id) {
this.id = id;
}
Gizmo.prototype.toString
=
function () {
return "gizmo " + this.id;
}
;
prototype
id
string
constructor
toString
function
prototype
constructor
toString
function
new Gizmo(
string
)
Gizmo
ObjectSlide48
Pseudoclassical InheritanceIf we replace the original prototype object, then we can inherit another object's stuff.Slide49
function
Hoozit
(id) {
this.id = id;
}
Hoozit.prototype
= new Gizmo
();
Hoozit.prototype.test
=
function (id) {
return this.id === id;
}
;Slide50
prototype
prototype
function
Hoozit
(id) {
this.id = id;
}
constructor
constructor
toString
function
Hoozit
GizmoSlide51
prototype
prototype
function
Hoozit
(id) {
this.id = id;
}
Hoozit.prototype
= new Gizmo
();
Hoozit.prototype.test
=
function (id) {
return this.id === id;
}
;
test
function
constructor
constructor
toString
function
Hoozit
GizmoSlide52
prototype
prototype
function
Hoozit
(id) {
this.id = id;
}
Hoozit.prototype
= new Gizmo
();
Hoozit.prototype.test
=
function (id) {
return this.id === id;
}
;
test
function
constructor
toString
function
id
string
new
Hoozit
(
string
)
Hoozit
GizmoSlide53
Pseudoclassical Inheritancefunction
Gizmo
(id) {
this.id = id;
}
Gizmo.prototype.toString
=
function () {
return "gizmo " + this.id;
}
;
function
Hoozit
(id) {
this.id = id;
}
Hoozit.prototype
= new Gizmo();
Hoozit.prototype.test
=
function (id) {
return this.id === id;
}
;Slide54
Prototypal Inheritancevar
gizmo =
new_constructor
(Object,
function (id) {
this.id = id;
}
, {
toString
:
function () {
return "gizmo " + this.id;
}
});
var
hoozit
=
new_constructor
(gizmo,
function (id) {
this.id = id;
}
, {
test:
function (id) {
return this.id === id;
}
});Slide55
function
new_constructor
(initializer, methods, extend) {
let prototype =
Object
.create
(
(
typeof
extend === "function")
?
extend.prototype
: extend
);
if (methods) {
methods.keys
().
forEach
(
function (key) {
prototype
[key] =
methods
[key];
}
);
}
function
constructor
() {
var
that =
Object
.create
(
prototype
);
if (
typeof
initializer
=== "function") {
initializer
.apply
(that, arguments);
}
return that;
}
constructor.prototype
= prototype;
prototype.constructor
= constructor;
return constructor;
}Slide56
Function as module
var
…
function …
function …
(
function () {
var
…
function …
function …
}
());Slide57
A Module Patternvar
singleton = (
function () {
var
privateVariable
;
function
privateFunction
(x) {
...
privateVariable
...
}
return {
firstMethod
:
function (a, b) {
...
privateVariable
...
}
,
secondMethod
:
function (c) {
...
privateFunction
()...
}
};
}()
);Slide58
A Module Pattern(
function () {
var
privateVariable
;
function
privateFunction
(x) {
...
privateVariable
...
}
GLOBAL
.methodical
= {
firstMethod
:
function (a, b) {
...
privateVariable
...
}
,
secondMethod
:
function (c) {
...
privateFunction
()...
}
};
}()
);Slide59
Module pattern is easily transformed into a powerful constructor pattern.Slide60
Power ConstructorsMake an object.
Object literal
new
Object.create
call another power constructorSlide61
Power ConstructorsMake an object.
Object literal,
new
,
Object.create
, call another power constructor
Define some variables and functions.
These become private members.Slide62
Power ConstructorsMake an object.
Object literal,
new
,
Object.create
, call another power constructor
Define some variables and functions.
These become private members.
Augment the object with privileged methods.Slide63
Power ConstructorsMake an object.
Object literal,
new
,
Object.create
, call another power constructor
Define some variables and functions.
These become private members.
Augment the object with privileged methods.
Return the object.Slide64
Step One
function
constructor
(spec) {
const
that =
otherMaker
(spec);
}Slide65
Step Two
function
constructor
(spec) {
const
that =
otherMaker
(spec);
let member;
}Slide66
Step Three
function
constructor
(spec) {
const
that =
otherMaker
(spec);
let member;
const
method =
function () {
//
spec
,
member
,
method
}
;
that.method
= method;
}Slide67
Step Four
function
constructor
(spec) {
const
that =
otherMaker
(spec);
let member;
const
method =
function () {
//
spec
,
member
,
method
}
;
that.method
= method;
return that;
}Slide68
Pseudoclassical Inheritancefunction
Gizmo
(id) {
this.id = id;
}
Gizmo.prototype.toString
=
function () {
return "gizmo " + this.id;
}
;
function
Hoozit
(id) {
this.id = id;
}
Hoozit.prototype
= new Gizmo();
Hoozit.prototype.test
=
function (id) {
return this.id === id;
}
;Slide69
Functional Inheritance
function
gizmo
(id) {
return {
id: id,
toString
:
function () {
return "gizmo " + this.id;
}
};
}
function
hoozit
(id) {
const
that =
gizmo
(id);
that.test
=
function (
testid
) {
return
testid
=== this.id;
}
;
return that;
}Slide70
Privacy
function
gizmo
(id) {
return {
toString
:
function () {
return "gizmo " +
id
;
}
};
}
function
hoozit
(id) {
const
that =
gizmo
(id);
that.test
=
function (
testid
) {
return
testid
===
id
;
}
;
return that;
}Slide71
function
Hoozit
(id) {
this.id = id;
}
Hoozit.prototype
= new Gizmo();
Hoozit.prototype.test
=
function (id) {
return this.id === id;
}
;
function
hoozit
(id) {
var
that = gizmo(id);
that.test
= function (
testid
) {
return
testid
=== id;
};
return that;
}
let
my_hoozit
= new
Hoozit
("success");
let test =
my_hoozit.test
;
alert(test("success"));
// B O
O
M !Slide72
function
Hoozit
(id) {
this.id = id;
}
Hoozit.prototype
= new Gizmo();
Hoozit.prototype.test
=
function (id) {
return this.id === id;
}
;
function
hoozit
(id) {
const
that = gizmo(id);
that.test
=
function (
testid
) {
return
testid
===
id
;
}
;
return that;
}
let
my_hoozit
=
hoozit
("success");
let test =
my_hoozit.test
;
alert(test("success")); // trueSlide73
Next:Episode IVThe Metamorphosis of Ajax