Post on 11-May-2015
description
javascriptas development platform
CONVENTIONSSOURCE CODE
var global = 10; function foo() { global++;}
BAD PRACTICE
(function () { var local = 10; function foo() { local++; }})();
GOOD PRACTICE
function factorial(x) { if (x <= 1) { return 1; } return x * arguments.callee(x - 1);}
LEGACY CODE
function foo() { console.log(‘foo’);}
CODE SNIPPET
WHAT IS javascript
The world`s most misunderstood programming language
SOURCES OF CONFUSIONJAVA PREFIX
Completely independent from Java
Has syntax similarities
SOURCES OF CONFUSIONSCRIPT POSTFIX
Doesn’t mean that JS isn`t real programming language Full-fledged Object Oriented language
SOURCES OF CONFUSIONWEAK LEARNING SOURCES
Standard has complicated structure makes it hard to read and understand
Internet full of bad advices and practices
Almost all books are universally bad
LEARNING SOURCESBOOKS
Javascript: the definitive guide Javascript: the GOOD parts
WHAT IS Javascript
A scripting language designed as lightweight alternative to Java for Web
history1992
James Gosling at Sun Microsystems has been working on superior language to C++ called Oak
history1992
Microsoft released Windows 3.1 and preview of Microsoft Windows NT for developers
history1995
Oak has failed as a language for interactive television and has been repurposed for Web. At this time language has been renamed to Java.
history1995
Sun Microsystems officially announced HotJava browser with support of Java-applets.
history1995
Web becomes hot and Microsoft ships Internet Explorer 1.0 and Internet Explorer 2.0 few month later
history1995
Brendan Eich at Netscape Communication Corporation begun working on lightweight and simple alternative to Java for Web browser
history1995
Later on Netscape released Netscape Navigator 2.0 with support of LiveScript and Java-applets
history1995
Anticipated by opportunity to free Web from Microsoft, Sun and Netscape formed the alliance
As the result LiveScript has been renamed to JavaScript
history1996
Microsoft reverse-engineered JavaScript and named it JScript to avoid trademark issues with Sun
history1996
Microsoft released Internet Explorer 3with support of JScript
history1996
To prevent Microsoft from mutating the language, Sun and Netscape made their way to ECMA to standardize the language
history1996
Sun and Netscape have failed and Microsoft gathered full control on standardization process. Microsoft insisted on preserving some design errors in the language
history1998
ECMA International introduces ECMA-262 1st + 2nd edition of JavaScript language
STANDARDECMA 262
VIEW STANDARD
ECMA-262 is active standard that defines JavaScript
Uses term ECMAScriptStructured in a way that makes it hard to read
STANDARDTIMELINE
VIEW STANDARD
1st edition
June
1997 1998
2nd edition
June
1999
3rd edition
December
2000-2009
4th edition
2009
5th edition
December
Future
Harmony edition
WHAT IS javascript
One of the most popular programming languages
Javascript POPULARITY
One of the most popular programming languages
AS OF BEGINNING OF 2013
KEY personsBrendan eich
Inventor of JavaScript language at Netscape
KEY personsDOUGLAS CROCKFORD
Active member of JavaScript community
Author of JSLint and JSMin
Inventor of JSON data format
WHAT IS Javascript
A programming language designed to be simple and flexible
DESIGN PRINCIPLESPROGRAMMING
Lightweight & SimpleScriptingDynamic
Multi-paradigm
DESIGN PRINCIPLESTARGET AUDIENCE
WEB AUTHORS Professional programmers
DESIGN PRINCIPLESSCALABILITY
Limited scalabilityLack of modularityLinkage through global spaceDynamicity over static typing
DESIGN PRINCIPLESMULTI-PARADIGM language
OBJECT ORIENTED FUNCTIONAL Imperative
DESIGN PRINCIPLESOBJECT ORIENTED LANGUAGE
OBJECT ORIENTEDfunction Plane(mass) { this.mass = mass;};
var lightPlane = new Plane(10), heavyPlane = new Plane(1000);
CODE SNIPPET
DESIGN PRINCIPLESFunctional language
var combine = function (a, b) { return function () { a(); b(); }; },
combined = combine( function () { console.log('Logging'); }, function () { alert('Alerting'); } );
combined();
CODE SNIPPETFUNCTIONAL
DESIGN PRINCIPLESOBJECT ORIENTED LANGUAGE
function bound(x, min, max) { var value = x;
value = Math.min(value, max); value = Math.max(value, min);
return value;}
CODE SNIPPETImperative
WHAT IS Javascript
A programming language that is more than just a Web toy
RuntimeHost environments
JAVASCRIPT ENGINE
HOST SPECIFIC API
JavaScript executes in a context of Engine
Host environment powers JavaScript Engine
HOST ENVIRONMENTSTYPES
WEB BROWSER OUT OF BROWSER
HOST ENVIRONMENTS RESPOSIBILITIES
REPOSNSIBLE FOR NOT RESPONSIBLE FOR
Input/OutputGraphics Storage Networking Host specific API
Memory management
Code execution
WHAT IS Javascript
JavaScript is a primary language of Web browser
HOST ENVIRONMENTSWEB BROWSER
JAVASCRIPT ENGINE
WEB BROWSER HOST
DOCUMENT OBJECT MODEL BROWSER Object MODEL
HOST SPECIFIC API
WEB BROWSERDOCUMENT OBJECT MODEL
Representation of document as objects hierarchy
Language & browser independentStandardized by W3C
Revisions are called DOM levels
WEB BROWSERBROWSER Object MODEL
API for interfacing native browser functionality
Deals with windows and frames
All functions and object starting at window
No corresponding standard
WEB BROWSERBROWSER Object MODEL
Window object
Navigatorobject
Frames[]array
Documentobject
Forms[]array
links[]array
images[]array
screenobject
ENGINE RUNTIMEESSENTIALS
Interpreted (no compilation step)Dynamically typed
Garbage collected
Class-freeRuntime extensibilityDuck typing
ENGINE RUNTIMEEXECUTION
Single threaded
Asynchrony via message loop
Linkage through global variables
ENGINE RUNTIMEScript distribution
Script are consumed as plain textInterpreted or compiled in-place
*.js is a format for script files
Mime-type:Officially: application/javascript
Practically: text/javascript or no MIME type at all
ENGINE RUNTIMEScript compression
Less traffic consumption
WHY?
Faster load time
techniques
GZipMinificationObfuscation
Runtime engineScript inclusion
Statically<script> tag
Runtime evaluation
Dynamically DOM API
Static inclusionScript tag
Script can be put anywhereon a page with <script> tag
<script src="path/to/script.js" type="text/javascript"></script>
CODE SNIPPET
Static inclusionType attribute
<script> tag should have matching </script> tag, except when document has application/xhtml+xml MIME type
<script src="path/to/script.js" type="text/javascript"/>
BAD PRACTICE
<script src="path/to/script.js" type="text/javascript"></script>
GOOD PRACTICE
Static inclusionXhtml validation
Type attribute is optional, but required for XHTML validation
<script src="path/to/script.js"></script>
CODE SNIPPET
static inclusionInline scripts
<script> tag supports inlining, but generally it is considered as bad practice
<script>console.log('Inline script');
</script>
CODE SNIPPET
static inclusionExecution ordering
Scripts attached in that way execute in order, even if script2 got loaded sooner
<script src="path/to/script1.js" type="text/javascript"></script><script src="path/to/script2.js" type="text/javascript"></script>
CODE SNIPPET
static inclusionExecution ordering
Same holds for inline scripts
<script src="path/to/script1.js" type="text/javascript"></script>
<script>console.log('Inline script');
</script>
CODE SNIPPET
static inclusionrendering
Script loading and execution blocks page rendering
<script src="link/to/script.js"></script>
<a id="link" href="url/to/somewhere.html">Link</a>
CODE SNIPPET var link = document.getElementById('link');
console.log(link != null); // false
Script.js
static inclusionrendering
Consider moving script to the bottom of the document
<body> <div class="page-content">Ipsum lerrra conde ir salle.</div>
<script src="js/script1.js"></script> <script src="js/script2.js"></script></body>
GOOD PRACTICE
Not every script can be moved
static inclusionAsync loading
Scripts can be loaded asynchronously using async attribute
<script src="link/to/script.js" async></script>
CODE SNIPPET
Script loading does not block rendering
Static inclusionASYNC loading
Ordering will not be preserved
<script src="link/to/script1.js" async></script><script src="link/to/script2.js" async></script>
CODE SNIPPET
No execution time guarantee
All async scripts are guaranteed to execute sometime before window load event
Static inclusiondefer loading
Scripts can be loaded in defer manner using defer attribute
<script src="link/to/script.js" defer></script>
CODE SNIPPET
Script loading does not block rendering
STATIC INCLUSIONdefer loading
Ordering will be preserved
<script src="link/to/script1.js" defer></script><script src="link/to/script2.js" defer></script>
CODE SNIPPET
Scripts are guaranteed to start execution right before DOMContentLoaded event
static INCLUSIONAsync+defer loading
Causes legacy browsers to fallback to defer if async is not supported
<script src="link/to/script1.js" async defer></script>
CODE SNIPPET
Modern browsers treat defer + async as async
static INCLUSIONLOADING TIMELINE
<script>
<script async>
<script defer>
Scripting
HTML Parser
Scripting
HTML Parser
Scripting
HTML Parser
Networking Execution Parsing
dynamic inclusionDOM API
Script can be attached programmatically using DOM API
DYNAMIC INCLUSIONasynchronous
var head = document.getElementsByTagName('head')[0], script = document.createElement('script');
script.src = 'script.js';head.appendChild(script);
CODE SNIPPET
AsynchronousScript ordering will not be preserved
Dynamic inclusionasynchronous
var head = document.getElementsByTagName('head')[0], script = document.createElement('script');
script.async = false;script.src = 'script.js';head.appendChild(script);
CODE SNIPPET
AsynchronousScript ordering will be preserved
Older browsers require tricky solutions
DYNAMIC INCLUSIONDEFERRED
var head = document.getElementsByTagName('head')[0], script = document.createElement('script');
script.src = 'script.js';script.defer = 'defer';head.appendChild(script);
CODE SNIPPET
DeferredHas no effect when loaded via DOM API
DYNAMIC INCLUSIONRuntime evaluation
Scripts can be evaluated at Runtime with Eval
Eval is “EVIL”
Compromises security
Hurts performance
Makes code hard to debug
script INCLUSIONParallel loading
Number of parallel HTTP connections per hostname is limited
Typically varies from 2 ~ 6
Consider CDN and subdomain usage
VIEW More
WHAT IS Javascript
JavaScript is a language that has many design errors
ENGINE RUNTIMEStrict EXECUTION Mode
Allows to opt-out to strict variant of JavaScript
Intended to correct initial design errors
Prohibits usage of error-prone and insecure features
Standardized in ECMA 262-5
STRICT Modeactivation
Activated with a Use Strict Directive in a Directive Prologue
'use strict';
var f = function () { console.log('Execution under strict mode');};
f();
CODE SNIPPET
STRICT Modescoping
Applied to a code unit 'use strict';
eval = 10; // SyntaxError
var f = function () { eval = 20; // SyntaxError};
CODE SNIPPET
To a Function
To a code file
Affects all inner contexts
Defined lexically (statically)eval = 10; // 10var f = function () { 'use strict'; eval = 20; // SyntaxError};
CODE SNIPPET
STRICT Modeinheritance
Directly Evaled code inherits Strict Mode
Functions created via new Function () dont inherit Strict Mode
Indirectly Evaled code doesn`t inherit Strict Mode
STRICT ModeError checking
'use strict';
eval = 10; // SyntaxError
var f = function () { eval = 20; // SyntaxError};
CODE SNIPPET
Compile time runtime
(function () { 'use strict'; global_variable = 10; // Reference Error})();
CODE SNIPPET
STRICT Moderestrictions
Reserved words
Implements
Interface
Let
Package
Private
Protected
Public
Static
Yield
"use strict"; var let = 10; // SyntaxError
CODE SNIPPET
STRICT Moderestrictions
Octal literals are not allowed
"use strict"; var x = 010; // SyntaxError
CODE SNIPPET
Assignment to an undeclared identifier
"use strict";a = 10; // ReferenceError
CODE SNIPPET
STRICT Moderestrictions
Assignment to read-only property
"use strict";
var foo = Object.defineProperties({}, { bar: { value: 10, writable: false // by default }, baz: { get: function () { return "baz is read-only"; } }});
foo.bar = 20; // TypeErrorfoo.baz = 30; // TypeError
CODE SNIPPET
STRICT Moderestrictions
Shadowing of inherited read-only properties
"use strict";
var foo = Object.defineProperty({}, "x", { value: 10, writable: false});
var bar = Object.create(foo);bar.x = 20; // TypeError
CODE SNIPPET
STRICT Moderestrictions
Eval and arguments
"use strict"; // SyntaxError in both casesvar arguments;var eval; // also SyntaxErrorfunction eval() {}var foo = function arguments() {};
CODE SNIPPET
Cannot appear as variable declaration of function name
STRICT Moderestrictions
Eval and arguments
"use strict"; // SyntaxErrorfunction foo(eval, arguments) {}
CODE SNIPPET
Not allowed as argument names
Not assignable
(function (x) { alert(arguments[0]); // 30 arguments = 40; // TypeError})(30);
CODE SNIPPET
STRICT Moderestrictions
Argument and callee properties
"use strict";
function foo() { alert(foo.arguments); // SyntaxError alert(foo.caller); // SyntaxError}
CODE SNIPPET
STRICT Moderestrictions
delete operator restrictions
"use strict"; var foo = {}; function bar(x) { delete x; // SyntaxError} bar(10); // SyntaxError delete foo; // SyntaxErrordelete bar; // SyntaxError
CODE SNIPPET
STRICT Moderestrictions
With statement
"use strict"; // SyntaxErrorwith ({a: 10}) { alert(a);}
CODE SNIPPET
this value
"use strict";
function foo() { console.log(this); // undefined}
foo();
CODE SNIPPET
Null no longer coerced to window
STRICT Moderestrictions
this value
"use strict";
function foo() { console.log(this); // undefined}
foo();
CODE SNIPPET
Null and undefined are no longer coerced to window
"use strict";
Number.prototype.test = function () { console.log(typeof this); // number};
(1).test(); // number
CODE SNIPPET
Primitives are not converted to wrapper objects
STRICT Moderestrictions
this valueHelps to avoid missing new
keyword issues
"use strict";
function A(x) { this.x = x;}
// forget "new" keyword,// error, because undefined.x = 10var a = A(10);
var b = new A(10); // OK
CODE SNIPPET
STRICT ModeUsage guidelines
Do not apply strict mode to whole script file blindly
Will not work when concatenated with some other scriptCan break other scripts if after concatenation put firstEvaled code will inherit Strict Mode
Consider wrapping your scripts with self-calling function
WHAT IS Javascript
JavaScript is a language that has simple but flexible type system
Type systemessentials
Class-free type system
Loose typingEverything is an object
Technically JavaScript has primitive types but they can be programmed as real objects
Type systemessentials
Two groups of typesPrimitive typesObject types
Primitives are not real objectsSome primitives has object wrapper
Type systemTypes
Primitive types Object types
NumberString
Booleannull
undefined
Object
Array
FunctionRegExp
Date
numbersessentials
Single type represents integer and floating point numbers
IEEE 754 64 bit numbers
Be aware of floating point errors0.1 + 0.2 !== 0.3Can be avoided by scaling
numbersruntime
Number object wrapper
var foobar = 0.5;typeof foobar; // "number"var foobar = 1;typeof foobar; // "number"
CODE SNIPPET
Runtime type
var a = 10;var b = new Number(a);
console.log(typeof b); // object
CODE SNIPPET
numbersSpecial values
Special valuesNaN
-Infinity
Infinity
numbersnan
var foobar = NaN;typeof foobar; // "number"
CODE SNIPPET
Paradoxical type
Watch out, easy to overwrite!
var NaN = "string";typeof NaN; // "string"
CODE SNIPPET
numbersnan
var foobar = "string" * 2, bar = "string" / 2;var foo = +"string", barfoo = +[1, 2, 3], foobar2 = undefined – 2;
CODE SNIPPET
Getting NaN
stringsessentials
Unicode UTF-16
ImmutableZero-based indexing
Built-in string manipulation routines don't take surrogate pairs into account
No dedicated Char type
stringsdeclaration
Literal declaration
var a = "string";var b = 'string';
CODE SNIPPET
stringsruntime
String object wrapper
Runtime type
var a = 'foo';var b = new String(a);
console.log(typeof b); // object
CODE SNIPPETvar foobar = "variable types";typeof foobar; // "string"
CODE SNIPPET
booleanessentials
Two possible predefined values
Generally Boolean produced by comparisons
truefalse
a === 1
Any value can be converted to Boolean
BooleanFalsy values
undefinednull0-0NaNEmpty string
var falsyValue = 0;if (!falsyValue) { alert("falsy value!");}
var falsyValue = "";if (!falsyValue) { alert("falsy value!");}
var falsyValue = NaN;if (!falsyValue) { alert("falsy value!");}
CODE SNIPPET
Booleanruntime
Boolean object wrapper
Runtime type
var a = true;var b = new Boolean(a);
console.log(typeof b); // object
CODE SNIPPETvar foobar = true;typeof foobar; // "boolean"
CODE SNIPPET
Nullessentials
Language keywordIndicates absence of value JavaScript never sets uninitialized variables to null
Nullruntime
Has no object wrapper
Runtime type
var foobar = null;typeof foobar; // "object"
CODE SNIPPET
undefinedessentials
IndicatesVariable is not defined Variable is defined, but has no value assigned
undefinedruntime
Has no object wrapper
Runtime type
var foobar;typeof foobar; // "undefined"
CODE SNIPPET
Undefinedruntime
Producing undefined value
(function (undefined) { console.log(typeof undefined);})();
CODE SNIPPET
Can be overridden
(function () { var undefined = 10; console.log(typeof undefined);})();
CODE SNIPPET
objectessentials
Unordered collection of key-value pairs
Fundamental data type
Have no fixed schemaRuntime extendable
Linked with another object via prototype
ENGINE RUNTIMEObject originators
Host objects NATIVE OBJECTS User-defined
Object originatorsHost objects
Host objects
Host objects are objects that are supplied to JavaScript by the browser environment
Examples of these are window, document, forms, etc
Poorly defined
Object originatorsNative objects
Native objects are those objects supplied by JavaScript runtime
Examples of these are String, Number, Array, Image, Date, Math, etc
Be very cautious extending these
NATIVE OBJECTS
Object originatorsUser-defined objects
User-defined object are defined by programmer
Full control
User-defined
OK to extend these
objectInternal layout
[[prototype]] referenceClass discriminator
Extensible flag
Can`t be set for user-defined objects
Defined in ES5
objectdeclaration
Object literal syntax
var person = { firstName: 'Douglas', lastName: 'Crockford', age: 45};
CODE SNIPPET
var person = {};person.firstName = 'Douglas';person.lastName = 'Crockford';person.age = 45;
CODE SNIPPET
objectdeclaration
Constructor function
var person = new Object();person.firstName = 'Douglas';person.lastName = 'Crockford';person.age = 45;
BAD PRACTICEvar person = Object.create(Object.prototype, { firstName: { writable: true, configurable: true, value: 'Douglas' }, lastName: { writable: true, configurable: true, value: 'Crockford' }, age: { writable: true, configurable: true, value: 45 }});
CODE SNIPPET
Object.create
objectProperty assessors
obj['property'];obj.property;
CODE SNIPPET
Two ways to access the object’s property
objectConstructor property
Constructor property points to constructor function
Can be messed up at runtime
var object = {};console.log(object.constructor === Object);
CODE SNIPPET
objectprototype
Prototype links object with another object
Simple form of inheritance
Internal [[prototype]] field
Set at creation based on Function.prototype value
No schema (classes) involved
Object inherits directly from another object
prototypechaining
{}
[[prototype]]
Object.prototype
[[prototype]]
NULL
prototypeProperty resolution
Search for property in current object
If not found search in a prototype
Move along prototype chain until null is reached
prototypeProperty resolution
Example
var object = {};console.log(object.toString());
CODE SNIPPET
toString is not declared in object but rather in Object.prototype
prototypeinspection
Undocumented field
Constructor`s prototype
var object = {};console.log(object.constructor.prototype);
CODE SNIPPET
getPrototypeOf
var object = {};console.log(object.__proto__);
BAD PRACTICE
var object = {};console.log(Object.getPrototypeOf(object));
CODE SNIPPET
objectreflection
for in
var obj = { property: "foobar", method: function() {}};for (var i in obj) { alert("The value of key " + i +" is " + obj[i]);}
CODE SNIPPET
hasOwnProperty
for (var i in obj) { if (obj.hasOwnProperty(i)) { alert("The value of key " + i +
" is " + obj[i]); }}
CODE SNIPPET
objectreflection
__count__
var obj = { property: "foobar", method: function() {}};obj.__count__; // 2
BAD PRACTICE
in
var obj = { a: 10};
var hasProperty = ('a' in obj);
CODE SNIPPET
arrayessentials
Zero-based 32bit indexing
Ordered collection of values
DynamicNo need for memory reallocation
Specialized form of objects with length property
Arrayruntime
Runtime type
var array = [1, 2, 3];typeof array; // object
CODE SNIPPET
Arrayruntime
The most reliable way of array detection
Object.prototype.toString.call(array) === "[object Array]"
CODE SNIPPET
Array detection (fails in multi-frame scenario)
array instanceof Array
CODE SNIPPET
arraydeclaration
Array literal
var array = [];
CODE SNIPPETvar array = new Array();
BAD PRACTICE
Array constructor
arraybehavior
Dynamic grow & shrink
var array = [1, 2, 3];array.push(4);array.pop(); // 4
CODE SNIPPET
Length property
var array = [1, 2, 3];console.log(array.length); // 3
CODE SNIPPET
arrayperformance
JavaScript arrays are special type of objectMuch slower than real arrays
operatorsoperator =
var foobar = 1;var foo = 2;var bar = foo = foobar = 3; // bar == 3, foo == 3, foobar == 3
CODE SNIPPET
“=“Multiple assignment
Assignment order is from right to left
Operators operator +
var foobar = "This " + "is " + "a variable.";CODE SNIPPET
String concatenation
Casting to number
var foobar = +true; // 1var foobar = +false; // 0
CODE SNIPPET
Operators operator +
var foobar = 5 + 1; // 6CODE SNIPPET
Adding
String priority
var foobar = "1" + 0; // 10 !typeof foobar; // "string"var foobar = 0 + "1"; // 01typeof foobar; // "string"
CODE SNIPPETvar foobar = function() {};var foobar2string = "" + foobar; //"function() {}"typeof foobar2string; // "string"
CODE SNIPPET
Operators operators += and ++
var foobar = 1;foobar += 1; // 2
CODE SNIPPET
Addition Casting to string
var foobar = "1";foobar += 5; // "15"
CODE SNIPPET
var foobar = "5";foobar++;typeof foobar; // "number"
CODE SNIPPET
Casting to number
Operators operators += and ++
var foo = 1;var bar = 2;foo += bar += 3; // foo == 6; bar == 5;
CODE SNIPPET
Multiple assignments
var foo = "1";var bar = "2";foo += bar += " is a string";// foo == "12 is a string; // bar == "2 is a string";
CODE SNIPPET
Operators operators -= and --
var foobar = 1;foobar -= 1; // 0
CODE SNIPPET
Decrement
-= does not behave like +=
var foobar = "1";foobar -= 5; // -4 (number)
CODE SNIPPETvar foobar = "5";foobar--;// 4typeof foobar; // "number"
CODE SNIPPET
Operators operators -= and --
var foo = 3;var bar = 2;foo -= bar -= 1; // foo == 2; bar == 1;
CODE SNIPPET
Multiple assignments
var foo = "1";var bar = "2";foo -= bar -= " is a string";// foo == NaN// bar == NaN
CODE SNIPPET
Operators operator | |
var foo = false;var bar = function() {};var foobar = foo || bar; // foobar === barfoobar();
CODE SNIPPET
Assignment
var foo = false;var bar = false;var barfoo = 5;var foobar = foo || bar || barfoo; // foobar === 5
CODE SNIPPET
var foo = true;var bar = function() {};var foobar = foo || bar; // foobar === truefoobar(); // error
CODE SNIPPET
Operators operator &&
var foo = true;var bar = function() {};var foobar = foo && bar; // foobar === barfoobar();
CODE SNIPPET
Assignment
var foo = true;var bar = function() { alert("hello world!"); };foo && bar(); // hello word!
CODE SNIPPET
var foo = false;var bar = function() {};var foobar = foo && bar; // foobar === falsefoobar(); // error
CODE SNIPPET
Inline conditions
Operators operators && and | |
var foo = true;var bar = false;var barfoo = false;var foobar = foo && bar || barfoo || 5; // foobar === 5
CODE SNIPPET
Good order makes a difference
OperatorsOperator !
Negation
var foo = 5;!foo; // falsevar foo = 0;!foo; // truevar foo = "0";!foo; // falsevar foo = "1";!foo; // false
CODE SNIPPET
Double negation (converts to Boolean)
var foo = 5;!!foo; // true
CODE SNIPPET
Operatorsoperator ~
var foo = 5.743534;~~foo; // 5typeof ~~foo; // "number"
CODE SNIPPET
Bitwise operator
var foo = -1;~foo; // 0
CODE SNIPPET
-(n + 1) when “n” is an integer
Numbers rounding
Operatorscomparison operators ( > , >= , <, <=, ==, ===, !=, !==)
var a = 0, b = 5, c = a || b > a
alert(c); // "true"
CODE SNIPPET
Return value of Boolean type
Can be used as part of more complex expression
OperatorsString comparison
Strings are compared using alphabetical order“Alphabetical order” is defined by the numerical order of the 16-bit Unicode values that make up the strings
alert("b" > "a"); // "true"
CODE SNIPPET
alert("cat" > "cats"); // "false"
CODE SNIPPET
OperatorsComparison of Different types
Values are converted to numbers except for the case when both values are strings
alert("2" > 1); // "true"alert("02" == 2); // "true"alert(0 == false); // "true"
CODE SNIPPET
OperatorsStrict Equality(===, !==)
Usual equality check can't distinguish the values that belong to different types but have the same number representationStrict equality operator is used to check equality without type conversion
alert("02" === 2); // "false"alert(0 === false); // "false"
CODE SNIPPET
OperatorsComparison with NULL and Undefined
null and undefined are not equal to 0 in comparisonsnull and undefined are equal only to each other
alert(null > 0); // "false"alert(null == 0); // "false"alert(null >= 0); // "true"
CODE SNIPPET
When converted to a numbernull is 0 undefined is NaN
alert(undefined > 0); // "false"alert(undefined < 0); // "false"alert(undefined == 0); // "false"
CODE SNIPPET
OperatorsObject Conversion
toString and valueOf are methods for string and number conversion respectively
String and number conversion can be overridden
If the operation requires a primitive value the object is converted to the primitive first and then operation is performed
Number conversion is used to convert object to primitive (exception is built-in Date object)
Operatorsstring Conversion of objects
toString is declared in Object.prototypetoString can be overridden in user-defined objecttoString should return any primitive value, otherwise it will cause an error
var user = { firstName: "John"};
alert(user) // "[object Object]"
CODE SNIPPET
alert(user); // [object Object]
var user = { firstName: "John", toString: function () { return "user " + this.firstName }};
alert(user) // "user John"
CODE SNIPPET
OperatorsString conversion of objects
Built-in objects have their own implementation of toString
alert([1, 2]); // toString for Arrays – list of elements "1, 2"alert(new Date()); // toString for Date – string representation of datealert(function () {}); // toString for Function – source code of function
CODE SNIPPET
OperatorsNumber conversion of objects
valueOf is declared in Object.prototype but it returns object itself and therefore is ignored
valueOf can be overridden in user-defined objectvalueOf should return any primitive value, otherwise it will be ignored
In case valueOf is ignored or not declared toString method is used instead
OperatorsNumber conversion of objects
Most built-in objects don't have valueOf implementation and therefore string and number conversion gives the same results (exception is Date object which supports both string and number conversion)
alert(new Date()); // toString - string representation of datealert(+new Date()); // valueOf – number of milliseconds from 01.01.1970
CODE SNIPPET
OperatorsComparisons with objects
If both operands are objects operators (==, !=) check if operands are or aren't references to the same object In all other cases number conversion is used to get primitive type and then perform operation (this is also true for arithmetic operators)
var a = {}, b = {}, c = a; alert(a == b); // "false"alert(a == c); // "true"
CODE SNIPPET
OperatorsComparisons with objects
var obj = { valueOf: function () { return 1; }}; alert(obj == true); // "true"alert(obj + "test"); // "1test"
CODE SNIPPETvar a = { valueOf: function () { return 1; }};
var b = { valueOf: function () { return 2; }}; alert(b > a); // "true"
CODE SNIPPET
WHAT IS Javascript
JavaScript is a language that has unique execution nuances
ENGINE RUNTIMEExecution Context
Abstract concept for differentiation of executable code
Defined in ECMA-262
Every time when control is transferred to executable code, control enters an execution context.
Consistent concept, but multiple implementations
Execution contextTypes of executable code
There are 3 types of JavaScript codeGlobal code
Function code
Eval code
Every code is evaluated in its context
Execution contextProgram runtime
Program Runtime represented as stack of EC
EC0
EC1
EC2
EC3
EC4
active EC
GLOBAL EC
Pushed every time on entering a function
Execution contextFunction code
(function foo(flag) { if (flag) { return; } foo(true);})(false);
CODE SNIPPET// first activation of fooECStack = [ <foo> functionContext globalContext]; // recursive activation of fooECStack = [ <foo> functionContext – recursively <foo> functionContextglobalContext];
CODE SNIPPET
Executable code EC stack
Execution contextEval code
Very special type of codeExecutes in its own context but affects calling context
In Strict Mode evaled code evaluates in its own sandbox
Execution contextEval code
// influence global contexteval('var x = 10');
(function foo() { // and here, variable "y" is // created in the local context // of "foo" function eval('var y = 20');})();
alert(x); // 10alert(y); // "y" is not defined
CODE SNIPPETECStack = [ globalContext]; // eval('var x = 10');ECStack.push({ context: evalContext, callingContext: globalContext}); ECStack.pop(); // eval exited contextECStack.push(<foo> functionContext); // foo function call
// eval('var y = 20');ECStack.push({ context: evalContext, callingContext: <foo> functionContext}); ECStack.pop(); // return from eval ECStack.pop(); // return from foo
CODE SNIPPET
Executable code EC stack
Execution contextLOGICAL layout
EC may be represented as simple object
Execution context
VARIABLE OBJECT
Scope chain
THIS VALUE
Execution contextVariable object
A Variable Object (VO) is tied to ECAbstract store for
Variables (var, VariableDeclaration)
Function declarations (FunctionDeclaration, FD)Function format parameters
Variable ObjectLogical layout
Declaration
var a = 10;
function test(x) { var b = 20;};
test(30);
CODE SNIPPET// Variable object of the global contextVO(globalContext) = { a: 10, test: <reference to function>}; // Variable object of the "test" function contextVO(test functionContext) = { x: 30, b: 20};
CODE SNIPPET
Variable Object
Variable Objecttypes
GLOBAL context VO
(vo ===this===global)
Function context VO
(VO === AO, <arguments> object and <formal parameters>
are added)
Variable ObjectGlobal context vo
Allows indirect referencing through window object
Singleton
Lifetime tied to application lifetime
global = { Math: <...>, String: <...> ... ... window: global};
CODE SNIPPET
Variable Objectfunction context vo
Doesn`t allow indirect referencing
VO(functionContext) === AO;
CODE SNIPPET
VO`s role plays Activation ObjectAn activation object is created on entering the
context of a function and initialized by property arguments which value is the Arguments object
Variable ObjectActivation object
AO = { arguments: <ArgO>};
CODE SNIPPETArguments containscallee - the reference to the current functionlength - quantity of real passed argumentsproperties-indexes
Variable ObjectActivation object
function foo(x, y, z) { alert(foo.length); // 3 alert(arguments.length); // 2
// reference of a function to itself alert(arguments.callee === foo); // true
// parameters sharing alert(x === arguments[0]); // true alert(x); // 10
arguments[0] = 20; alert(x); // 20
x = 30; alert(arguments[0]); // 30
z = 40; alert(arguments[2]); // undefined
arguments[2] = 50; alert(z); // 40}
foo(10, 20);
CODE SNIPPET
Variable number of parameters
Runtime function inspection
Execution contextExecution stages
Two stages of code handlingEntering the context where all the data are created
The code execution stage
Formal parameter initialization
Function declaration
Variable declaration
Execution contextEntering Execution context
For each formal parameterProperty of the VO with a name and value of formal parameter is created
For not passed parameters — property of VO with a name of formal parameter and value undefined is created
Execution contextEntering Execution context
For each function declaration
A property of the variable object with a name and value of a function-object is created
If the variable object already contains a property with the same name, replace its value and attributes
Execution contextEntering Execution context
For each variable declaration
a property of the variable object with a variable name and value undefined is created
if the variable name is already declared, declaration does not disturb the existing property.
Execution contextEntering Execution context
Executable code
function test(a, b) { var c = 10; function d() { } var e = function _e() { }; (function x() { });}
test(10); // call
CODE SNIPPETAO(test) = { a: 10, b: undefined, c: undefined, d: <reference to FunctionDeclaration "d"> e: undefined, arguments: <Args>};
CODE SNIPPET
Activation Object
Execution contextExecution phase
Variables and function declarations are hoisted, but not assignments
foo();
function foo() { console.log(bar);}
var bar = 10;
CODE SNIPPETvar bar;
function foo() { alert(bar);}
foo();
bar = 10;
CODE SNIPPET
Original source Internal representation
Execution contextFunction -level scoping
ES3 has no block-level scoping definedVariable declared in a block visible everywhere in
a function
(function () { { var a = 10; }
console.log(a); // 10})();
CODE SNIPPET
Execution contextFunction -level scoping
ES6 Harmony allows block-level scoping with let keyword
(function () { { let a = 10; }
console.log(a); // Reference error})();
CODE SNIPPET
Execution contextLOGICAL layout
EC may be represented as simple object
Execution context
VARIABLE OBJECT
Scope CHAIN
THIS VALUE
Execution contextScope chain
List of all (parent) variable objects for the inner contexts
Created at function call
Consists ofVariable Object of currently executing code unit
Internal [[Scope]] field
Scope chainLogical layout
Used for identifier lookup
activeExecutionContext = { VO: {...}, // or AO this: thisValue, Scope: [ // Scope chain // list of all variable objects // for identifiers lookup ] }
CODE SNIPPET
Scope = AO + [[Scope]]
CODE SNIPPET
Traversing scope chain2D lookup with prototypes
Scope chain[[scope]] property
[[Scope]] is a chain of all parent VO, which are above the current function context
[[Scope]] is saved to the function at its creationImplements Lexical (Static) Scoping
Scope chainscoping
var x = 10;
function foo() { var y = 20;
function bar() { var z = 30; alert(x + y + z); }
bar();}
foo(); // 60
CODE SNIPPETbarContext.Scope = barContext.AO + bar.[[Scope]] // i.e.: barContext.Scope = [ barContext.AO, fooContext.AO, globalContext.VO];
CODE SNIPPET
Executable code Scope chain
Scope chainclosure
Closure is a functional concept
Consist of 2 partsFunction or function pointer
Referencing environment – a table of references to variables form outer scope
Closureexample
var f = function outer() { var a = 10;
return function inner() { return a; }};
f1 = f();console.log(f1()); // 10
CODE SNIPPET
Inner is a function
Scope of outer function forms referencing environment
Closurenuances
Referencing environment consist of references to outer variables
Closures on iterator variables work in counterintuitive way
Closurenuances
var array = [0, 1, 2];
for (var i = 0; i < array.length; i++) { array[i] = function () { console.log(i); };}
array[0](); // 3
CODE SNIPPET
incorrect Correct
var array = [0, 1, 2];
for (var i = 0; i < array.length; i++) { (function (i) { array[i] = function () { console.log(i); }; })(i);}
array[0](); // 0
CODE SNIPPET
Closurenuances
Watch out for context switches
var person = { firstName: 'Douglas', say: function () { function sayName() { console.log(this); // window or undefined return this.firstName; }
return sayName(); }};
person.say();
CODE SNIPPETvar person = { firstName: 'Douglas', say: function () { var me = this;
function sayName() { return me.firstName; } return sayName(); }};
person.say();
CODE SNIPPET
Execution contextLOGICAL layout
EC may be represented as simple object
Execution context
VARIABLE OBJECT
Scope chain
THIS VALUE
Execution contextThis value
Special context objectNot tied to particular object
Can be set at runtime
Property of ECNever participates in identifier lookup
Determined only once when entering EC
Immutable
This valueGlobal scope
Executable code
// explicit property definition of the global objectthis.a = 10; // global.a = 10alert(a); // 10
// implicit definition via assigning to unqualified identifierb = 20;alert(this.b); // 20
// also implicit via variable declaration because variable object of the global context// is the global object itselfvar c = 30;alert(this.c); // 30
CODE SNIPPET
This valueCall expression
Value of this is determined by the form of a call expression
function foo() { alert(this);}
foo(); // global or undefined (strict mode)
alert(foo === foo.prototype.constructor); // true
// but with another form of the call expression// of the same function, this value is different
foo.prototype.constructor(); // foo.prototype
CODE SNIPPET
This valueCall expression
Manual setting of ThisValueFunction.prototype.call
Function.prototype.apply
Function.prototype.bind
ThisValue as first parameter
This valueCALL
ThisValue as first parameterComma-separated list of parameters
function a(c) { alert(this.b); alert(c);}
// this === {b: 20}, this.b == 20, c == 30a.call({ b: 20 }, 30);
CODE SNIPPET
Executes a function
This valueapply
ThisValue as first parameter
function a(c) { alert(this.b); alert(c);}
// this === {b: 30}, this.b == 30, c == 40a.apply({ b: 30 }, [40])
CODE SNIPPET
Executes a function
Array of parameters
This valuebind
ThisValue as first parameter
function a(c) { alert(this.b); alert(c);}
// this === {b: 30}, this.b == 30, c == 40(a.bind({ b: 30 }, 40))();
CODE SNIPPET
Returns a function
Comma-separated list of parameters
WHAT IS Javascript
JavaScript is a language that has unique implementation of OOP
patterns & practicesmodularity
Modules are building blocks of the app
Key propertiesLoose coupling
High cohesion
Facilitate clean and flexible architecture
patterns & practicesmodularity
Language has no built-in concept of modulesModules are simulated using
Functions
Local variables
Closures
Dozen of design patterns available
modularityModule pattern
Provides encapsulation forPrivacy
State
Structure
Physical shielding of private and public members
modularityModule pattern
Language features usedSelf-calling functions
Closures
var MY_APP_ONE = (function () { // Private variables var secret1 = 'Hello'; var secret2 = 'World'; // Private functions var privateFoo = function() { };
// Publicly exposed return { foo: function() { // Do stuff }, bar: function() { // Do stuff } };})();
CODE SNIPPET
modularityModule pattern
pros cons
Clean syntaxPrivate members
Hard to refactorHard to extend
Hard to overrideNo way of dependency management
modularityREVEALING Module pattern
Very similar to Module Pattern
All members declared as privatePublic members then “revealed” by return statement
modularityRevealing Module pattern
Language features usedSelf-calling functions
Closures
var MY_APP_ONE = (function () { // Private variables var secret1 = 'Hello'; var secret2 = 'World';
// Private functions var privateFoo = function () {};
var publicFoo = function () {}; var publicBar = function() {};
// Publicly exposed return { foo: publicFoo, bar: publicBar };})();
CODE SNIPPET
modularityModule revealing pattern
pros cons
Clean syntaxPrivate members
Hard to extend
Even harder to overrideCommon syntax for
accessing private and public members
No way of dependency management
modularityAMD
Developed as standard for async module loading
On demand async module loading
Built-in dependency management
Has corresponding specification
modularityAMD
Concise APIdefine
require
Namespace-free architecture
Modules referred to by name or path
modularityAMD
Language features usedSelf-calling
functionsClosures
// shirt.jsdefine({ color: "black", size: "large"});
// logger.jsdefine(["shirt"], function (shirt) { return { logTheShirt: function () { console.log( "color: " + shirt.color + ", size: " + shirt.size ); } };});
CODE SNIPPET
modularityAMD
pros cons
Clean syntaxAsync loading
Async nature may lead to spaghetti codeDependency management Requires build tool to be used in minified file
modularityCommonjs modules 1.1
Developed as part of CommonJS project
On demand synchronous module loading
Built-in dependency managementHas corresponding specification
modularityCommonjs modules 1.1
Concise APIrequire
module.exports
Modules referred to by name or path
One module one script file mappingCan`t be used in minification scenarios
modularityCommonjs modules 1.1
Language features usedClosure
s
// hello.jsexports.hello = function () { return 'Hello World';};
//app.jsvar example = require('./example.js');example.hello();
CODE SNIPPET
modularityCommonjs modules 1.1
pros cons
Clean syntax
Sync loading is inappropriate in Web browser
Dependency management
Doesn`t support minification scenarios
patterns & practicesinheritance
No classical inheritanceLots of ways to achieve inheritance
Pseudo-classical
Prototypal
Functional
Don’t try to pretend you`re programming on some other language
inheritancePseudo-classical
Invented to make classical style inheritance possible
Native JavaScript objects follow this pattern
Pseudo-classical patternKey ideas
Key ideasThe object is created by a constructor function
Methods and default properties are put into prototype
Properties are put into constructor function
Pseudo-classical patternBase class
Examplefunction Animal(name) { this.name = name} Animal.prototype = { constructor: Animal, canWalk: true, sit: function() { this.canWalk = false alert(this.name + ' sits down.') }} var animal = new Animal('Pet') // (1)
CODE SNIPPET
canWalk property will be overridden in concrete instanceConstructor assignment makes instanceof operator work
Pseudo-classical patternBase class
Initially
{ canWalk: ‘true’, sit: function}
Animal.prototype
{ name: ‘Pet’}
instance
[[prototype]]
{ canWalk: ‘true’, sit: function}
Animal.prototype
{ name: ‘Pet’, canWalk: ‘false’}
instance
[[prototype]]
After sit
Pseudo-classical patternInheritance function
Inherit base class prototypeand allow extensibility
function extend(Child, Parent) { var F = function () { }; F.prototype = Parent.prototype;
Child.prototype = new F(); Child.prototype.constructor = Child; Child.superclass = Parent.prototype;}
CODE SNIPPET
Pseudo-classical patternDerived class
Example function Rabbit(name) { Rabbit.superclass.constructor.apply(this, arguments);}
extend(Rabbit, Animal);
Rabbit.prototype.jump = function () { this.canWalk = true; alert(this.name + ' is jumping.');};
CODE SNIPPET
Superclass constructor called to initialize properties defined in base class
Pseudo-classical patternMethod overriding
Superclass call
Rabbit.prototype.sit = function () { alert(this.name + ' is about to sit!'); Rabbit.superclass.sit.apply(this, arguments);};
CODE SNIPPET
Pseudo-classical patternencapsulation
Convention based encapsulation
Animal.prototype.walk = function () { alert('walking');};
Animal.prototype._run = function () { alert('running');}
CODE SNIPPET
Common practice is to prefix protected members with _
Pseudo-classical patternstatics
Static properties and functions
function Animal() { Animal.count++}
Animal.count = 0
new Animal()new Animal()
alert(Animal.count); // 2
CODE SNIPPET
Assigned directly to the constructor
inheritanceprototypal
Prototypal inheritance is native to JavaScript
May or may not use concept of class
PrototypalKey ideas
Key ideasThe object is created by special function
Freedom of choice where to put properties and methods
This function links object with prototype
PrototypalObject creation
Links empty object with specified prototype
function object(o) { function F() { } F.prototype = o; return new F();}
CODE SNIPPET
ES5 has dedicated function
Object.create(prototype, propertyDescriptors)
CODE SNIPPET
Prototypalexample
Derived object inherits from base via prototype
var base = { a: 1};
var derived = object(base);
derived.print = function() { console.log(this.a);};
derived.print();
CODE SNIPPET
inheritanceParasitic
Object inherits base class properties by extending it
May or may not use concept of class
parasiticKey ideas
Key ideasDerived object extends base object
Fast property resolution
Prototype is not used at all
WHAT IS Javascript
JavaScript is a script language distant from actual hardware
Performance optimizationreasoning
Premature optimization is EvilPerformance optimizations needs to based on actual profiling data
Pareto principle: 90/10Consider algorithmic optimizations first
Performance optimizationFunction calls
Avoid intensive functions calling
while (i) { fn(i); var i = fn2(); fn3(i);};
CODE SNIPPET
Performance optimizationLocal variables
Use local variables
var fn = function() { var events = library.utils.events; var proxy = library.services.proxy;};
CODE SNIPPET
Performance optimizationLICM
Loop invariant code motion
var arr = [1, 2, 3, 4];for (var i = 0; i < arr.length; i++) {};
CODE SNIPPET var arr = [1, 2, 3, 4];for (var i = 0, j = arr.length; i < j; i++) {};
CODE SNIPPET
var arr = [1, 2, 3, 4];var i = arr.length;while(i--) {};
CODE SNIPPET
Performance optimizationMemoization
Memoization
var arr = [1, 2, 3, 4, 4, 2, 3, 1, 2, 3, 4, 5, 6, 1];var fn = function fn(i) { fn.cache = fn.cache || {};
if (i in fn.cache) { return fn.cache[i]; } return (fn.cache[i] = Math.cos(i));};
CODE SNIPPET
Performance optimizationCode optimization
Yielding
Avoid try {} catch() {}
Avoid bit operators
Performance optimizationKeep it simple
Simpler - faster
var min = Math.min(a, b);arr.push(val);
CODE SNIPPET
Slow
Fast
var min = a < b ? a : b;arr[arr.length] = val;
CODE SNIPPET
Special thanksReviewers & inspirations
Damian WielgosikHis amazing depth knowledge of JS inspired my presentation. Check out his Just Advanced JavaScript on SlideShare.
Pavel HizhukHis amazing understanding of type casting and comparisons reflected directly in this presentation.
Special thanksReviewers & inspirations
My GirlfriendFor constant support and patience in listening my crazy saying about how badly something implemented, for sleepless nights and funny jokes :)
The end