meta-meta-programming?
© 2016 Last Minute Panic ProductionsTech Lead at Norse Corp
Angularhead, stream processing hacker
Version | Year |
1 | 1997 |
2 | 1998 |
3 | 1999 |
5 | 2009 |
5.1 | 2011 |
6 | 2015 |
// ES5
Randall.on('stress', function () {
// handle stress (badly);
});
['Odin', 'Thor', 'Bob'].map(function () {
// ...
});
fetch('https://rkoutnik.com')
.then(function (data) {
// Brilliant programming articles!
})
.catch(function (error) {
// Works on my machine
});
// ES6
Randall.on('stress', () => {
// handle stress (badly);
});
['Odin', 'Thor', 'Bob'].map(() => {
// ...
});
fetch('https://rkoutnik.com')
.then((data) => {
// Brilliant programming articles!
})
.catch((error) => {
// Works on my machine
});
var that = this;
var _this = this;
var that_or_this = this;
this.on('stress', function () {
that.handleStress();
});
this.on('stress', () => {
this.handleStress();
});
// You can omit the parens when you have a single arg
['bill', 'bob', 'jeb', 'valentina'].map(kerb => {
return kerb.intoSpace();
});
// Heck, with a single instruction, you can drop the brackets
['bill', 'bob', 'jeb', 'valentina'].map(kerb => kerb.intoSpace());
// Noop
() => {}
// Constant function
() => 42
let str = 'Hello, ' + person.name + '!';
let str = `Hello, ${person.name}!`;
let str = `----- PERSON -----
name: ${person.name}
hobby: ${person.hobby}
salary: $${person.salary.toLocaleString()}`;
console.log(`
----- ${name.toUpperCase()} RESULTS -----
${MESSAGES} messages sent in ${(time / 1000).toLocaleString()} seconds
${(MESSAGES / (time / 1000)).toLocaleString()} messages/sec
`);
let myTag = (strings, ...values) => {
return strings.reduce((prev, next, idx) => {
let val = values[idx];
if (val && Number(val) === val) {
val = val.toLocaleString();
}
return prev + next + val;
}, '');
}
console.log(myTag`
----- ${name.toUpperCase()} RESULTS -----
${MESSAGES} messages sent in ${time / 1000} seconds
${MESSAGES / (time / 1000)} messages/sec
`);
We're all grown up like Java
function Cat (name) {
this.name = name;
}
Cat.prototype.introduce = function () {
return 'Hi everyone! I\'m'
+ this.name;
};
function Fuzz () {
Cat.call(this, 'Fuzz');
}
Fuzz.prototype = Object.create(Cat.prototype);
Fuzz.prototype.sayHi = function sayHi() {
return Cat.prototype.sayHi.call(this)
+ ', and I'd like some food';
};
var fuzz = new Fuzz();
fuzz.sayHi();
class Cat {
constructor (name) {
this.name = name;
}
sayHi () {
return `Hi everyone. I'm ${this.name}`
}
}
class Fuzz extends Cat {
constructor () {
super('Fuzz');
}
sayHi () {
return `${super.sayHi()} and I'd like some food!`;
}
}
let fuzz = new Fuzz;
fuzz.sayHi();
(Even more Java-like)
function Cat (name) {
this._name = name;
Object.defineProperty(this, 'name', {
get: function () {
return this._name;
},
set: function (newName) {
this._name = newName;
}
});
}
class Cat {
constructor (name) {
this._name = name;
}
get name () {
return this._name;
}
set name (newName) {
this._name = newName;
}
}
var id = getNextId();
var employee = getEmployeeById(id);
var employeeOptions = {
id: id
};
employeeOptions[employee.name] = employee;
var id = getNextId();
var employee = getEmployeeById(id);
var employeeOptions = {
id,
[employee.name]: employee
};
(I can haz Python)
var getThings = () => {
// Some data munging
return [thing1, thing2];
};
var [myThing1, myThing2] = getThings();
console.log(myThing1);
...back to Java
function example() {
if (exampleIsFunny) {
var meta = true;
}
console.log(meta); // true
}
function example() {
if (exampleIsFunny) {
let meta = true;
}
console.log(meta); // error
}
for(var i = 0; i < 10; i++) {
setTimeout(() => console.log(i), 10);
}
for(let i = 0; i < 10; i++) {
setTimeout(() => console.log(i), 10);
}
(function () {
'use strict';
console.log(bill); // undefined
var bill = 'llama';
})();
(function () {
'use strict';
console.log(bill); // error
let bill = 'llama';
})();
const name = 'Randall';
name = 'hackerman'; // throws
const person = {
name: 'Randall'
};
person.name = 'hackerman'; // throws?
if (youShouldNotDoThis) {
function agh() {}
}
agh(); // throws
JavaScript goes "splat"
function build (what) {
what = what || 'presentation';
return what; // Say 'what' again
}
build(); // 'presentation'
function build (what = 'presentation') {
return what;
}
build(); // 'presentation'
let f = () => {
console.log(arguments); // error!
});
f(1,2,3);
let f = (...args) => {
console.log(args); // [1,2,3]
});
f(1,2,3);
let f = (firstName, lastName) => {
console.log(firstName, lastName); // 'Randall', 'Koutnik'
});
let nameArr = ['Randall', 'Koutnik'];
f(...nameArr);
A tower of code!
Because JS needs types!
let register = (type: string, name: string, factory): INodeFactory => {
export interface INodeFactory {
(...config: any[]): symbol;
}
Any questions before we move on?
No, not the kind that get you past the firewall
let target = {};
let handler = {};
let prox = new Proxy(target, handler);
prox.world = 'hello';
console.log(target.world); // Hello
let handler = {
get (target, key) {
return target[key] + '!';
}
}
let target = {};
let proxy = new Proxy(target, handler);
proxy.world = 'hello';
console.log(proxy.world); // 'hello!'
let handler = {
get (target, key) {
return target[key] + '!';
}
set (target, key, value) {
if (typeof key !== 'string') {
throw new Error(`Tried to set ${key} to non-string value ${value}`);
}
target[key] = value;
return true;
}
}
let target = {};
let proxy = new Proxy(target, handler);
proxy.world = 'hello';
console.log(proxy.world); // 'hello!'
proxy.bad = {}; // Throws!
let ng = (function () {
let handler = {
get (target, key) {
if (key.indexOf('$$') === 0) {
throw new Error(`Don't go touching the internals!`);
}
return target[key];
}
set (target, key, value) {
if (key.indexOf('$') === 0) {
throw new Error(`Don't go touching the internals!`);
}
target[key] = value;
return true;
}
}
let target = angular;
return new Proxy(target, handler);
})();
questions@rkoutnik.com
github.com/SomeKittens