JavaScript Enlightenment Johnathan Hebert 1
Agenda Introductions Presentation – Brief history of JavaScript – Objects in depth – Functions in depth – A few tricks Questions 2
It is (finally) getting better Invented by Brendan Netscape in 1995 Standardized by Ecma in 1997 (Ecma-262) 3 rd Edition standardized in Dec 1999 – Untouched for 10 years, this is the one you know 4 th Edition was abandoned – Vendor disagreements 5 th Edition standardized in Dec 2009 – Bug fixes, enhanced built-in objects, but no new syntax – Shipped in Chrome, Firefox, Safari, Opera and IE Edition standardized in Jun 2011 – Fixes errata in 5 th Edition, identical in content to 5 th Edition ES.next AKA Harmony (6 th ) Edition is well on its way… – Lots of new stuff 3
JavaScript Enlightenment JavaScript book by Cody Lindley – Summary of ECMA rd edition – 262,%203rd%20edition,%20December% pdf 4
What's in the book? "It was my intention to write a book to give the reader an accurate JavaScript worldview through an examination of native JavaScript objects and supporting nuances: complex values, primitive values, scope, inheritance, the head object, etc. I intend this book to be a short and digestible summary of the ECMA-262, Edition 3 specification, focused on the nature of objects in JavaScript." - Cody Lindley 5
Everything is (acts like) an object // JavaScript only has 6 types var pet = {name:'george'}, // Object type = 'monkey', // String age = 5.0, // Number curious = true, // Boolean nothing = null, // Null missing = undefined; // Undefined // what about Function, Array, Date, RegExp, etc? // they are all just objects... console.log(typeof Array.prototype); // "object" 6
Is "function" a JavaScript type? // functions are objects that implement [[call]] -- // see prescribed algorithm for the typeof operator: 7
Every object has hidden properties 8
The [[prototype]] hidden property // a hidden [[prototype]] property is created // automatically and points to the prototype of the // constructor function var pet = { name:'george', type:'monkey', description:'curious' }; pet Object. prototype 9
Prototype link is fixed // objects do not have a property named prototype, // they have a hidden property called [[prototype]] console.log(pet.prototype) // undefined // access it through the constructor property var petProto = pet.constructor.prototype; // you can add a property named prototype, but it // does not change the hidden [[prototype]] link pet.prototype = {type:'animal'}; 10
How does the prototype get there? // the hidden prototype link is fixed at the object // construction step – these are the same: var pet = {}; var pet = new Object(); // the pet object is constructed with the Object() // constructor function, which does a few things: 1. a new empty object is created in memory 2. the object gets a hidden link to Object.prototype 3. the this keyword in the Object() function points to the new empty object 4. Object() function code is executed 11
Prescribed construct algorithm 12 // see prescribed algorithm for object construction:
What does this really do? function Animal() { this.type = 'animal'; } var pet = new Animal(); 13
Built-in Object Relationships 14 Object () Object.prototype {} Function () Function.prototype () [[prototype]] prototype
Define a New Constructor Function 15 Object () Object.prototype {} Function () Function.prototype () [[prototype]] prototype function Animal() { this.type = 'animal'; }
Define a New Constructor Function 16 Object () Object.prototype {} Function () Function.prototype () [[prototype]] prototype Animal.prototype {} Animal () function Animal() { this.type = 'animal'; } constructor
Create a New Object 17 Object () Object.prototype {} Function () Function.prototype () [[prototype]] prototype Animal.prototype {} Animal ()pet {} var pet = new Animal(); constructor
Object inheritance using prototypes // create a named function via a function statement function Animal() { this.type = 'animal'; } // Animal automatically gets a prototype property console.log(typeof Animal.prototype) // 'object' // pet will have a hidden link to Animal.prototype var pet = new Animal(); pet {type:'animal'} Animal. Prototype 18 Object. prototype
Functions can be constructors // the this keyword refers to the new object function Animal() { this.type = 'animal'; }; // any function can be invoked with the new keyword // to be a constructor (invokes [[construct]]) var pet = new Animal(); console.log(pet.type); // 'animal' // No object is created without the new keyword // WARNING: this now references global object var pet = Animal(); // pet is undefined 19
Constructor function inheritance // will be used as the base constructor function function Animal() { this.type = 'animal'; }; // eventually inherit from the base constructor function function Monkey() { this.likesBananas = true; } // the magic happens here (inheritance) Monkey.prototype = new Animal(); // pet.type will refer to Animal.prototype.type var pet = new Monkey(); // pet Monkey.prototype Animal.prototype Object.prototype 20
Something is wrong! // why does this log Animal? why not Monkey? console.log(pet.constructor); // the orginal Monkey.prototype was overwritten Monkey.prototype = new Animal(); // culprit // the old Monkey.prototype had a property named // constructor – put it back: Monkey.prototype.constructor = Monkey; // fixed 21
Neat stuff with functions // start with the original constructor function function Animal() { this.type = 'animal'; }; // make the this keyword refer to another object var johnathan = {type:'person'}; // random object console.log(johnathan.type); // 'person' Animal.call(johnathan); // this === johnathan console.log(johnathan.type); // 'animal' 22
Immediate execution of functions // evaluate a function statement as an expression (function sayHello(name) { alert('Hello ' + (name || 'nobody')); })('George'); // another way to evaluate as an expression !function() { alert('hi'); }(); // parens not necessary for function expressions var result = function sayHello(name) { alert('Hello ' + (name || 'nobody')); }('George'); 23
Function closures // one function returns another function var getSecret = function() { // private var var secret = 'JavaScript has private vars'; // this function is closed over outer vars return function() { return secret; }; }(); // secret is visible to the inner function after // the outer function has returned console.log(secret); // undefined console.log(getSecret()); // in the circle of trust 24
Anonymous function tricks // anonymous functions can call themselves // (won't work in ECMAScript 5+ strict mode) (function(i) { console.log(++i); if (i < 10) { arguments.callee(i); } })(0); // anonymous functions can be constructors too var anon = new function() {this.strange = true;}(); console.log(anon.strange); // true 25
Functions can have properties // count the number of times a function was called function sayHello(name) { console.log('Hello ' + (name || 'nobody')); arguments.callee.numCalls++; } sayHello.numCalls = 0; // call the function a couple of times sayHello('Curious George'); sayHello('Man in the yellow hat'); // numCalls is like a static property console.log(sayHello.numCalls); // 2 26
Why is this stuff important? // understand the libraries you are using (function( window, undefined ) {... // the entire jQuery library })(window); // you might need it outside the browser (soon) var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello World\n'); }).listen(1337, " "); 27
Summary Everything in JavaScript is (acts like) an object Objects have hidden links to a [[prototype]] Functions are just "callable objects" Be careful with semantics – Functions have a hidden [[prototype]] property – Functions also have a visible prototype property Pay close attention to scoping – Lexical scoping by default – Scope chain can be modified at runtime 28
Questions ? 29