Eirik Langholm Vullum PRO
JavaScript fanatic that loves node.js and React.
// macro (sweet.js)
syntax hi = function (ctx) {
return #`console.log('hello, world!')`;
};// macro (sweet.js)
syntax hi = function (ctx) {
return #`console.log('hello, world!')`;
};
// before compile/expansion
hi// macro (sweet.js)
syntax hi = function (ctx) {
return #`console.log('hello, world!')`;
};
// before compile/expansion
hi
// after compile/expansion
console.log('hello, world!');// macro (sweet.js)
operator >>= left 1 = (left, right) => {
return #`${left}.then(${right})`;
};// macro (sweet.js)
operator >>= left 1 = (left, right) => {
return #`${left}.then(${right})`;
};
// before compile/expansion
fetch('/foo.json') >>= resp => { return resp.json() }
>>= json => { return processJson(json) }// macro (sweet.js)
operator >>= left 1 = (left, right) => {
return #`${left}.then(${right})`;
};
// before compile/expansion
fetch('/foo.json') >>= resp => { return resp.json() }
>>= json => { return processJson(json) }
// after compile/expansion
fetch("/foo.json").then(resp => {
return resp.json();
}).then(json => {
return processJson(json);
});(before the code runs)
const hero = {
health: 100,
backpack: ['carrots', 'beer'],
weapon: 'sword'
};const hero = {
health: 100,
backpack: ['carrots', 'beer'],
weapon: 'sword'
};
const keys = Object.keys(hero);const hero = {
health: 100,
backpack: ['carrots', 'beer'],
weapon: 'sword'
};
const keys = Object.keys(hero);
console.log(keys);
// ['health', 'backpack', 'weapon']function grumpySum(a, b) {
if (a > 5) {
grumpySum = () => 0;
}
return a + b;
}function grumpySum(a, b) {
return a + b;
}function grumpySum(a, b) {
if (a > 5) {
grumpySum = () => 0;
}
return a + b;
}
console.log(grumpySum(1, 1)) // -> 2
console.log(grumpySum(10, 1)) // -> 11function grumpySum(a, b) {
if (a > 5) {
grumpySum = () => 0;
}
return a + b;
}
console.log(grumpySum(1, 1)) // -> 2
console.log(grumpySum(10, 1)) // -> 11
console.log(grumpySum(2, 3)) // -> 0function grumpySum(a, b) {
if (a > 5) {
grumpySum = () => 0;
}
return a + b;
}
console.log(grumpySum(1, 1)) // -> 2
console.log(grumpySum(10, 1)) // -> 11
console.log(grumpySum(2, 3)) // -> 0
console.log(grumpySum(2, 100)) // -> 0
function grumpySum(a, b) {
if (a > 5) {
grumpySum = () => 0;
}
return a + b;
}
console.log(grumpySum(1, 1)) // -> 2var hero = {
health: 100,
};Very limited / not very flexible
var hero = {
health: 100,
};
Object.defineProperty(hero, 'status', {
get: function() {
},
});var hero = {
health: 100,
};
Object.defineProperty(hero, 'status', {
get: function() {
if (this.health > 50) {
return 'fit like a champ'
}
},
});var hero = {
health: 100,
};
Object.defineProperty(hero, 'status', {
get: function() {
if (this.health > 50) {
return 'fit like a champ'
} else {
return 'badly hurt';
}
},
});var hero = {
health: 100,
};
Object.defineProperty(hero, 'status', {
get: function() {
if (this.health > 50) {
return 'fit like a champ'
} else {
return 'badly hurt';
}
},
});
hero.status // -> fit like a champ
(while the code runs)
(is this useful)
new Proxy(target, handler)
const proxy = new Proxy(target, handler);{}
{}
[]
{}
[]
function() {}{}
[]
function() {}
new Proxy(...){}
[]
function() {}
new Proxy(...)
// any type of objectconst proxy = new Proxy({}, {})const proxy = new Proxy({}, {})
typeof proxy === 'object'var handler = {
};var handler = {
get: function(target, name) {
return 37;
}
};var handler = {
get: function(target, name) {
return 37;
}
};
var p = new Proxy({}, handler);var handler = {
get: function(target, name) {
return 37;
}
};
var p = new Proxy({}, handler);
console.log(p.a); // 37var handler = {
get: function(target, name) {
return 37;
}
};
var p = new Proxy({}, handler);
console.log(p.a); // 37
console.log(p.b); // 37proxy = new Proxy({}, {
get: ...,
set: ...,
has: ...,
apply: ...,
construct: ...,
defineProperty: ...,
getOwnPropertyDescriptor: ...,
deleteProperty: ...,
getPrototypeOf: ...,
setPrototypeOf: ...,
isExtensible: ...,
preventExtensions: ...,
ownKeys: ...,
});const hero = { health: 100 };const hero = { health: 100 };
Reflect.get(hero, 'health'); // 100proxy = new Proxy({}, {
get: ...,
set: ...,
has: ...,
apply: ...,
construct: ...,
defineProperty: ...,
getOwnPropertyDescriptor: ...,
deleteProperty: ...,
getPrototypeOf: ...,
setPrototypeOf: ...,
isExtensible: ...,
preventExtensions: ...,
ownKeys: ...,
});proxy = new Proxy({}, {
get: Reflect.get,
set: Reflect.set,
has: Reflect.has,
apply: Reflect.apply,
construct: Reflect.construct,
defineProperty: Reflect.defineProperty,
getOwnPropertyDescriptor: Reflect.getOwnPropertyDescriptor,
deleteProperty: Reflect.deleteProperty,
getPrototypeOf: Reflect.getPrototypeOf,
setPrototypeOf: Reflect.setPrototypeOf,
isExtensible: Reflect.isExtensible,
preventExtensions: Reflect.preventExtensions,
ownKeys: Reflect.ownKeys,
});function logAccessToProperties(obj) {
}function logAccessToProperties(obj) {
return new Proxy(obj, {
});
}function logAccessToProperties(obj) {
return new Proxy(obj, {
get(target, key) {
},
});
}function logAccessToProperties(obj) {
return new Proxy(obj, {
get(target, key) {
console.log('Accessed key', key);
},
});
}function logAccessToProperties(obj) {
return new Proxy(obj, {
get(target, key) {
console.log('Accessed key', key);
return Reflect.get(target, key);
},
});
}function logAccessToProperties(obj) {
return new Proxy(obj, {
get(target, key) {
console.log('Accessed key', key);
return Reflect.get(target, key);
},
set(target, key, value) {
}
});
}function logAccessToProperties(obj) {
return new Proxy(obj, {
get(target, key) {
console.log('Accessed key', key);
return Reflect.get(target, key);
},
set(target, key, value) {
console.log('Updated key', key, 'to', value);
}
});
}function logAccessToProperties(obj) {
return new Proxy(obj, {
get(target, key) {
console.log('Accessed key', key);
return Reflect.get(target, key);
},
set(target, key, value) {
console.log('Updated key', key, 'to', value);
Reflect.set(target, key, value);
}
});
}const person = {
name: 'Eirik',
age: 30,
};const person = {
name: 'Eirik',
age: 30,
};
const personWithAccessLogging =
logAccessToProperties(person);const person = {
name: 'Eirik',
age: 30,
};
const personWithAccessLogging =
logAccessToProperties(person);
personWithAccessLogging.age;const person = {
name: 'Eirik',
age: 30,
};
const personWithAccessLogging =
logAccessToProperties(person);
personWithAccessLogging.age;
// Accessed ageconst person = {
name: 'Eirik',
age: 30,
};
const personWithAccessLogging =
logAccessToProperties(person);
personWithAccessLogging.age;
// Accessed age
personWithAccessLogging.age = 31;const person = {
name: 'Eirik',
age: 30,
};
const personWithAccessLogging =
logAccessToProperties(person);
personWithAccessLogging.age;
// Accessed age
personWithAccessLogging.age = 31;
// Updated key age to 31function observable(obj, onChange) {
}function observable(obj, onChange) {
return new Proxy(obj, {
};
}function observable(obj, onChange) {
return new Proxy(obj, {
set(target, key, value) {
}
};
}function observable(obj, onChange) {
return new Proxy(obj, {
set(target, key, value) {
Reflect.set(target, key, value);
}
};
}function observable(obj, onChange) {
return new Proxy(obj, {
set(target, key, value) {
Reflect.set(target, key, value);
onChange({ key, value });
}
};
}let person = {
name: 'Eirik',
age: 31,
};let person = {
name: 'Eirik',
age: 31,
};
person = observable(person, ({ key, value }) => {
console.log(`${key} changed to ${value}`);
});let person = {
name: 'Eirik',
age: 31,
};
person = observable(person, ({ key, value }) => {
console.log(`${key} changed to ${value}`);
});
person.name = 'Frank';let person = {
name: 'Eirik',
age: 31,
};
person = observable(person, ({ key, value }) => {
console.log(`${key} changed to ${value}`);
});
person.name = 'Frank';
// name changed to Franklet person = {
name: 'Eirik',
age: 31,
};
person = observable(person, ({ key, value }) => {
console.log(`${key} changed to ${value}`);
});
person.name = 'Frank';
// name changed to Frank
person.age = 40;let person = {
name: 'Eirik',
age: 31,
};
person = observable(person, ({ key, value }) => {
console.log(`${key} changed to ${value}`);
});
person.name = 'Frank';
// name changed to Frank
person.age = 40;
// age changed to 40const stories = [
{
id: 'story-1',
title: 'The Last Question',
author: {
$ref: 'people',
id: 'person-1'
},
liked_by: [
{ $ref: 'people', id: 'person-1' },
{ $ref: 'people', id: 'person-2' }
],
read_by: [
{ $ref: 'people', id: 'person-1' },
{ $ref: 'people', id: 'person-2' }
],
},
{
...
}
];const people = [
{
id: 'person-1',
name: 'Isaac Asimov',
authored: [
{ $ref: 'stories', id: 'story-1' },
],
read: [
{ $ref: 'stories', id: 'story-1' },
],
liked: [
{ $ref: 'stories', id: 'story-1' },
],
},
{
...
}
];const stories = [
{
id: 'story-1',
title: 'The Last Question',
author: {
$ref: 'people',
id: 'person-1'
},
liked_by: [
{ $ref: 'people', id: 'person-1' },
{ $ref: 'people', id: 'person-2' }
],
read_by: [
{ $ref: 'people', id: 'person-1' },
{ $ref: 'people', id: 'person-2' }
],
},
{
...
}
];const people = [
{
id: 'person-1',
name: 'Isaac Asimov',
authored: [
{ $ref: 'stories', id: 'story-1' },
],
read: [
{ $ref: 'stories', id: 'story-1' },
],
liked: [
{ $ref: 'stories', id: 'story-1' },
],
},
{
...
}
];const stories = [
{
id: 'story-1',
title: 'The Last Question',
author: {
$ref: 'people',
id: 'person-1'
},
liked_by: [
{ $ref: 'people', id: 'person-1' },
{ $ref: 'people', id: 'person-2' }
],
read_by: [
{ $ref: 'people', id: 'person-1' },
{ $ref: 'people', id: 'person-2' }
],
},
{
...
}
];const people = [
{
id: 'person-1',
name: 'Isaac Asimov',
authored: [
{ $ref: 'stories', id: 'story-1' },
],
read: [
{ $ref: 'stories', id: 'story-1' },
],
liked: [
{ $ref: 'stories', id: 'story-1' },
],
},
{
...
}
];const graph = {
stories: [...],
people: [...]
}Plain JSON
const nameOfFirstLiker =
const nameOfFirstLiker =
graph.stories[0].liked_byconst nameOfFirstLiker =
graph.stories[0].liked_by
.map(({ $ref, id }) => graph[$ref].find((p) => p.id === id))const nameOfFirstLiker =
graph.stories[0].liked_by
.map(({ $ref, id }) => graph[$ref].find((p) => p.id === id))[0]const nameOfFirstLiker =
graph.stories[0].liked_by
.map(({ $ref, id }) => graph[$ref].find((p) => p.id === id))[0]
.name;const nameOfFirstLiker =
graph.stories[0].liked_by
.map(({ $ref, id }) => graph[$ref].find((p) => p.id === id))[0]
.name;
const titleOfFirstLikedStoryByAuthor =const nameOfFirstLiker =
graph.stories[0].liked_by
.map(({ $ref, id }) => graph[$ref].find((p) => p.id === id))[0]
.name;
const titleOfFirstLikedStoryByAuthor =
graph[graph.stories[0].author.$ref]const nameOfFirstLiker =
graph.stories[0].liked_by
.map(({ $ref, id }) => graph[$ref].find((p) => p.id === id))[0]
.name;
const titleOfFirstLikedStoryByAuthor =
graph[graph.stories[0].author.$ref]
.find((p) => p.id === graph.stories[0].author.id))const nameOfFirstLiker =
graph.stories[0].liked_by
.map(({ $ref, id }) => graph[$ref].find((p) => p.id === id))[0]
.name;
const titleOfFirstLikedStoryByAuthor =
graph[graph.stories[0].author.$ref]
.find((p) => p.id === graph.stories[0].author.id))
.title;const nameOfFirstLiker =
graph.stories[0].liked_by[0].nameconst nameOfFirstLiker =
graph.stories[0].liked_by[0].name
const titleOfFirstLikedStoryByAuthor =
graph.stories[0].author.likes[0].title{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
}
}{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [
{ id: 'story-1', $ref: 'stories' },
]
}
}{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
},
...
}],
}
}{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [
{ id: 'story-1', $ref: 'stories' }
]
}
...
}],
}
}
const populatedNode = populate( )
const populatedNode = populate( )
const populatedNode = populate(graph, )
const populatedNode = populate(graph, node)
const populatedNode = populate(graph, node)
const populatedStory = populate(graph, graph.stories[0]){
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
}
}{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [
{ id: 'story-1', $ref: 'stories' },
]
}
}{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
},
...
}],
}
}
// Boom{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [
{ id: 'story-1', $ref: 'stories' }
]
}
...
}],
}
}{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
}
}{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [
{ id: 'story-1', $ref: 'stories' },
]
}
}{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
},
...
}],
}
}{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
name: 'Ted Chiang',
likes: [
{ id: 'story-1', $ref: 'stories' }
]
}
...
}],
}
}const stories = [
{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
}
},
{
...
}
];const people = [
{
id: 'ted-chiang-1',
name: 'Ted Chiang',
authored: [{
id: 'story-1',
$ref: 'stories'
}]
},
{
...
}
];const stories = [
{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
}
},
{
...
}
];const people = [
{
id: 'ted-chiang-1',
name: 'Ted Chiang',
authored: [{
id: 'story-1',
$ref: 'stories'
}]
},
{
...
}
];const stories = [
{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
}
},
{
...
}
];const people = [
{
id: 'ted-chiang-1',
name: 'Ted Chiang',
authored: [{
id: 'story-1',
$ref: 'stories'
}]
},
{
...
}
];const stories = [
{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
}
},
{
...
}
];const people = [
{
id: 'ted-chiang-1',
name: 'Ted Chiang',
authored: [{
id: 'story-1',
$ref: 'stories'
}]
},
{
...
}
];const stories = [
{
id: 'story-1',
name: 'Story of Your Life',
author: {
id: 'ted-chiang-1',
$ref: 'people'
}
},
{
...
}
];const people = [
{
id: 'ted-chiang-1',
name: 'Ted Chiang',
authored: [{
id: 'story-1',
$ref: 'stories'
}]
},
{
...
}
];
const nameOfFirstLiker =
graph.stories[0].liked_by.people[0].name
const titleOfFirstLikedStory =
graph.people[0].author.likes[0].titlegithub.com/eiriklv/json-populate
TypeError: undefined is not a function
TypeError: Cannot read property 'undefined' of undefined
const Undefined = new Proxy(function() {}, {
});const Undefined = new Proxy(function() {}, {
get(target, key, receiver) {
},
});const Undefined = new Proxy(function() {}, {
get(target, key, receiver) {
if (key === 'name') {
return 'Undefined';
}
return Undefined;
},
});const Undefined = new Proxy(function() {}, {
get(target, key, receiver) {
if (key === 'name') {
return 'Undefined';
}
return Undefined;
},
apply() {
},
});const Undefined = new Proxy(function() {}, {
get(target, key, receiver) {
if (key === 'name') {
return 'Undefined';
}
return Undefined;
},
apply() {
return Undefined;
},
});function seatbelt(obj) {
}function seatbelt(obj) {
return new Proxy(obj, {
});
}function seatbelt(obj) {
return new Proxy(obj, {
get(target, key) {
}
});
}function seatbelt(obj) {
return new Proxy(obj, {
get(target, key) {
const accessedProperty = Reflect.get(target, key);
}
});
}function seatbelt(obj) {
return new Proxy(obj, {
get(target, key) {
const accessedProperty = Reflect.get(target, key);
if (typeof accessedProperty === 'object') {
return seatbelt(accessedProperty);
}
}
});
}function seatbelt(obj) {
return new Proxy(obj, {
get(target, key) {
const accessedProperty = Reflect.get(target, key);
if (typeof accessedProperty === 'object') {
return seatbelt(accessedProperty);
} else {
return accessedProperty == undefined ?
Undefined :
accessedProperty;
}
}
});
}const iNeverFail = seatbelt({
});const iNeverFail = seatbelt({
foo: 'bar',
baz: {
qux: 10,
name: 'yoyo',
},
});iNeverFail.fooiNeverFail.foo
// bariNeverFail.foo
// bar
iNeverFail.baz.quxiNeverFail.foo
// bar
iNeverFail.baz.qux
// 10iNeverFail.foo
// bar
iNeverFail.baz.qux
// 10
iNeverFail.baz.nameiNeverFail.foo
// bar
iNeverFail.baz.qux
// 10
iNeverFail.baz.name
// yoyo
iNeverFail
iNeverFail.notHere
iNeverFail.notHere.notAfunction
iNeverFail.notHere.notAfunction()
iNeverFail.notHere.notAfunction().nope
iNeverFail.notHere.notAfunction().nope
// [Function: Undefined]
iNeverFail.notHere.notAfunction().nope
// [Function: Undefined]
iNeverFail.foo.b.a.g.e.d().sf().d
iNeverFail.notHere.notAfunction().nope
// [Function: Undefined]
iNeverFail.foo.b.a.g.e.d().sf().d
// [Function: Undefined]
Object.setPrototypeOf(
Object.prototype,
seatbelt({})
);/**
* Nobel prize material
*/
Object.setPrototypeOf(
Object.prototype,
seatbelt({})
);@eiriklv
By Eirik Langholm Vullum