JavaScript deep dive

@BenedekGagyi

History

  • Mosaic -> Netscape
  • Java, Java applets
  • Mocha
  • Brendan Eich - "Scheme for the browser"
  • Time pressure (Sun deal)
  • Java, Scheme, Self
  • LiveScript -> JavaScript
  • Microsoft: JScript (DOM functions)
  • ES1 (1997), ES2-3, ES5, ES6, ES.next
  • Babel (not just syntactic sugar)

History

Variables

Types?

In JavaScript variables don't have types.
Values do!

Variables

  • Primitives
    • undefined
    • null
    • boolean
    • number
    • string
    • symbol - added in ES6

Types?

Variables

undeclared vs undefined vs null

Variables

var a;
console.log(typeof a);
console.log(typeof b);

console.log(typeof null);

Variables

if (DEBUG) {
	console.log( "Debugging is starting" );
}

if (typeof DEBUG !== "undefined") {
	console.log( "Debugging is starting" );
}

if (window.DEBUG) {
	console.log( "Debugging is starting" );
}

Variables

  • String
  • Number
  • Boolean
  • Array
  • Date
  • RegExp
  • Error
  • Function
    (callable object)

Complex primitives

Variables

Complex primitives

var fn = function(a, b) {};
var arr = [];

console.log(typeof fn);
console.log(fn.length);

console.log(typeof arr);
console.log(arr.length);
var x = 'string';
console.log(typeof x);
console.log(x instanceof String);

x = new String('string');
console.log(typeof x);
console.log(x instanceof String);
console.log(x.toString());
console.log(Object.prototype.toString.call(x));

Variables

Variables

By reference vs. by value

Variables

var x = 1;
function f() {
    console.log(x);
    var x = 2;
}
f();

Variables

var vs. let vs. const

"Find&replace var to let. What could go wrong?"

Variables

Temporal Dead Zone Error (TDZ)

console.log(typeof a);

let a;

Variables

What happens if we switch let -> var?

var funcs = [];

for (let i = 0; i < 5; i++) {
	funcs.push( function(){
		console.log( i );
	} );
}

funcs[3]();
this
let x = {
    y: 1,
    z: function(){
        console.log(this.y);
    }
}
let tricky = x.z;
x.z();
tricky();
this

Call site!

this
function x() {
	console.log( this.a );
}

var a = 2;

x();

Default binding

this
"use strict";
function x() {
	console.log( this.a );
}

var a = 2;

x();

Default binding

this
function x() {
	console.log( this.a );
}

var obj = {
	a: 2,
	x: x
};

obj.x();

Implicit binding

this
function x() {
	console.log( this.a );
}

var obj = {
	a: 2,
	x: x
};

var y = obj.x;

var a = "global";

y();

Implicit binding

this
function x() {
	console.log( this.a );
}

function doX(fn) {
	fn(); // <-- call-site!
}

var obj = {
	a: 2,
	x: x
};

var a = "global";

doX( obj.x);

Implicit binding

Pay attention to callbacks!

this
function x() {
	console.log( this.a );
}

var obj = {
	a: 2
};

x.call( obj ); 

Explicit binding

this
function x() {
	console.log( this.a );
}

var obj = {
	a: 2
};

x.apply( obj ); 

Explicit binding

this
function x(p1, p2) {
	console.log( this.a, p1, p2 );
}

var obj = {
	a: 2
};

x.call( obj, 3, 4 ); 
x.apply( obj, [3, 4] ); 

Explicit binding

"C for comma, A for array"

this
function x (something) {
	console.log( this.a, something );
}

var obj = {
	a: 2
};

var y = x.bind( obj );

y( 3 );

Explicit binding

.bind
this
function x(a) {
    this.a = a;
}

var y = new x( 2 );
console.log( y.a );

new binding

Returns a new object!

this
function x(a) {
    this.a = a;
    return {};
}

var y = new x( 2 );
console.log( y.a );

new binding

Returns a new object?

this
var z = { q: 1};
function x(a) {
    this.a = a;
    return z;
}

var y = new x( 2 );
console.log( y.a );

new binding

Returns a new object?

this
function x(something) {
	this.a = something;
}
var obj1 = {};

var y = x.bind( obj1 );
y( 2 );
console.log( obj1.a );

var z = new y( 3 );
console.log( obj1.a );
console.log( z.a );

What's the order?

this

What's the order?

  • new
  • call, apply, bind
  • obj.fn()
  • Window
var obj = {
    x: function(message) {
        console.log(message);
    },
    y: message => console.log(message)
}
obj.x("old school");
obj.y("new school");

Arrow functions

function x() {
    return (a) => {
        console.log( this.a );
    };
}

var obj1 = {
    a: 2
};

var obj2 = {
    a: 3
};

var y = x.call( obj1 );
y.call( obj2 );

Arrow functions


function PiggyBank(){
  let money = [];
  return {
    store: function(index, value){
      money[index] = value;
    },
    push: function(value){
      money.push(value);
    }
  }
}

let sharedPiggyBank = PiggyBank();
let stolen;
// MAGIC!
console.log(stolen);

There's a weakness in this code which allows direct access to the money Array.

Array.prototype.push = function(value){
  this[this.length] = value;
  money = this; 
}

Prototype

sharedPiggyBank.store('push', function(value) {   
  this[this.length] = value;                         
  stolen = this; 
});

Object properties

var myObject = {
    a: 2
};
----------------------------------------

var myObject = {};

Object.defineProperty( myObject, "a", {
	value: 2,
	writable: true,
	configurable: true,
	enumerable: true
} );
defineProperty
var myObject = {};

Object.defineProperty( myObject, "a", {
	value: 2,
	writable: false
} );

myObject.a = 22;
console.log( myObject.a );

Object.defineProperty( myObject, "a", {
	value: 333,
} );
console.log( myObject.a );
defineProperty

Watch out for configurable!

defineProperty
  • for ... in
  • for ... of
  • forEach

Immutability

  • Object.preventExtensions
  • Object.seal
  • Object.freeze

What's the difference?

Object.defineProperty( myObject, "b", {
    get: function(){ return this.a * 2 },
    set: function(a){ this.a = a - 1},
    configurable: true,
    enumerable: true
    }
);

Getters & Setters

var myObject = {
    get b() { return this.a * 2 },
    set b(a) { this.a = a - 1}
}

Getters & Setters

What happens, if we leave one out?

The + operator

Type coercion in ==

The (IMHO) coolest ES6 feature

...

Spread/Rest

function fn(x,y,z) {
	console.log( x + y + z );
}

fn( ...[1,2,3] );

Spread/Rest

var a = [2,3,4];
var b = [ 1, ...a, 5 ];

console.log( b );

Spread/Rest

function foo(x, y, ...z) {
	console.log( x, y, z );
}

foo( 1, 2, 3, 4, 5 );	

Spread/Rest

function foo(...args) {
	console.log( args );
}

foo( 1, 2, 3, 4, 5);	

Spread/Rest

let x = {
    a: 1,
    b: 2,
}

let y = {
    ...x,
    b: 4,
    c: 5,
}
console.log( y );

Parallelism in JS

"In JavaScript, there's only a single thread"

Web Workers

var w1 = new Worker( "http://some.url.1/mycoolworker.js" );

w1.addEventListener( "message", function(evt){
    // evt.data
} );
w1.postMessage( "something cool to say" );
-----------------------------------------------------------
addEventListener( "message", function(evt){
	// evt.data
} );

postMessage( "a really cool reply" );

Web Workers

  • The number of actual threads is implementation dependent
  • no access to DOM or other resources
  • own copy of navigator, location, JSON, applicationCache

Web Workers

Sharing data

JavaScript deep dive

By Benedek Gagyi

JavaScript deep dive

  • 772