際際滷

際際滷Share a Scribd company logo
Metaprogramowanie w JS
Spojrzenie na interesujce wewntrzne mechanizmy
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Achtung! Danger! Uwaga!
Metaprogramowanie w JS
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Zajawka
Metaprogramowanie w JS
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Zajawka
Metaprogramowanie w JS
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Zajawka
Metaprogramowanie w JS
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Zajawka
Metaprogramowanie w JS
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Zajawka
Metaprogramowanie w JS
What the Hack? 
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
What the Hack?
What the Hack?
What the Hack?
Agenda
Metaprogramowanie w JS
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
 Czym jest metaprogramowanie?
 Metaprogramming API
 Podstawowe symbole
 Proxy
Czym jest metaprogramowanie?
Czyli kilka s坦w teorii
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Why do JS developers wear glasses?
Because they dont C#
De鍖nicja
Czym jest metaprogramowanie?
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
 Program, kt坦ry tworzy lub mody鍖kuje inny program - metaprogram
 Program, kt坦ry mody鍖kuje samego siebie
De鍖nicja
Czym jest metaprogramowanie?
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
 Program, kt坦ry tworzy lub mody鍖kuje inny program - metaprogram
 Kompilatory - np. parsowanie i optymalizacja kodu
 Transpilery - np. mody鍖kacja kodu 甜eby by zgodny z urzdzeniem
 IDE - np. analiza JSDoc
 Program, kt坦ry mody鍖kuje samego siebie
 Mechanizmy re鍖eksji
De鍖nicja
Czym jest metaprogramowanie?
 Program, kt坦ry tworzy lub mody鍖kuje inny program - metaprogram
 Kompilatory - np. parsowanie i optymalizacja kodu
 Transpilery - np. mody鍖kacja kodu 甜eby by zgodny z urzdzeniem
 IDE - np. analiza JSDoc
 Program, kt坦ry mody鍖kuje samego siebie
 Mechanizmy re鍖eksji
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Mody鍖kacja programu innym programem
Czym jest metaprogramowanie?
 Program, kt坦ry tworzy lub mody鍖kuje inny program - metaprogram
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
#define true false
#define private public
Robienie zamieszania w C dziki makrom / Zy kod nie zale甜y od jzyka
Programowanie re鍖eksyjne
Czym jest metaprogramowanie?
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
 Introspekcja - czytanie struktury programu
 Mody鍖kacja - zmiana struktury programu
 Intercesja - wchodzenie pomidzy - zmiana semantyki jzyka/programu
Przykady metaprogramowania
Co mo甜emy dziki temu osign?
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
SQL query goes into a bar, walks up to
two tables and asks "Can I join you?"
Przeci甜anie operator坦w
Przykady metaprogramowania
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
// Ruby
class X
attr_reader :order
def +(y)
y + 2
end
def <=>(other)
self.order <=> other.order
end
end
instance = X.new
instance + 3 // => 5
// C++
struct X {
int operator+(int y) {
return y + 2;
}
};
int main () {
X instance;
std::cout << instance + 3; // => 5
return 0;
}
Destruktory
Przykady metaprogramowania
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
// Python
class X:
def __del__(self):
self.connection.close()
// PHP
class X
{
private function __destruct()
{
$this->connection->close();
}
}
Obsuga dynamicznych p坦l
Przykady metaprogramowania
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
// PHP
class X
{
public function __get($field)
{
return $field . " value";
}
}
// Ruby
class X
def method_missing(m, *args, &block)
"#{m} value"
end
end
Adnotacje i dekoratory
Przykady metaprogramowania
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
// Java
@Entity
public class X {
@Id @GeneratedValue
@Column(name = "id")
private int id;
public X() {}
}
// JavaScript
class X {
@emitOnEnd("someEvent")
doSomething () {
console.log("Something there")
}
}
Prywatne wartoci
Przykady metaprogramowania
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
// PHP
class X
{
private $name;
}
// C++
class X {
private:
string name;
}
Imitowanie tablicy
Przykady metaprogramowania
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
// PHP
class X implements ArrayAccess
{
public function offsetExists ($o) {}
public function offsetGet ($o) {}
public function offsetSet ($o, $v) {}
public function offsetUnset ($o) {}
}
$instance = new X();
$instance["key"];
$instance[0];
// JavaScript
// Array-like object
const a = {
0: 1,
1: 4943,
2: 2213,
length: 3
}
a[0];
Przeci甜anie metod/klas
Przykady metaprogramowania
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
// Ruby
class X
def something
'hello!'
end
end
class X
def somethingElse
'hello 2!'
end
end
instance = X.new
instance.print // => "hello!"
instance.printSomething // => "hello 2!"
// JavaScript
// Works pretty good!
function X () {}
X.prototype.something = function () {
return "hello!"
}
X.prototype.somethingElse = function () {
return "hello 2!"
}
instance = new X()
instance.print() // => "hello!"
instance.printSomething() // => "hello 2!
Metaprogramming API
Podstawowe mo甜liwoci w JavaScript
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
I've got a really good UDP joke to tell you,
but I don't know if you'll get it
Na co nam pozwala podstawowe API?
Metaprogramming API
 Analiza i mody鍖kacja struktury obiekt坦w
 Czytanie informacji o funkcjach
 Zarzdzanie acuchem prototyp坦w
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Analiza i mody鍖kacja obiekt坦w
Metaprogramming API
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
 Czytanie podstawowej struktury obiekt坦w
 Zarzdzanie staoci obiekt坦w (mutability)
 acuch prototyp坦w
Object.getPrototypeOf(obj)
Object.setPrototypeOf(obj, null)
Object.hasOwnProperty("key") // => true Object.getOwnPropertyNames(obj)
Object.keys(obj) // => [ "key" ]
Object.preventExtensions(obj) Object.isExtensible(obj) // => false
Object.seal(obj) Object.isSealed(obj) // => true
Object.freeze(obj) Object.isFrozen(obj) // => true
Funkcje
Metaprogramming API
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
 Wykonywanie funkcji
 Czytanie struktury funkcji
 Tworzenie funkcji
Math.max.call(Math, 10, 20) // => 20
Math.max.apply(Math, [ 10, 20 ]) // => 20
const func = Array.prototype.concat.bind([ 10, 30 ], 20)
func(40) // => [ 10, 30, 20, 40 ]
function test (a, b) {} test.length // => 2
test.toString() // => "function test (a, b) {}"
function test2 (a, ...args) {} test2.length // => 1
const sum = new Function("a", "b", "return a + b")
sum(10, 20) // => 30
Re鍖ect API
Metaprogramming API
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
// Function options wrappers
Reflect.apply(Math.max, null, [ 5, 15 ])
Reflect.construct(X, [ "John" ])
// Language wrappers
Reflect.has() // in operator
Reflect.deleteProperty() // delete
Reflect.get() // access property
Reflect.set() // set property value
// Object methods wrappers
Reflect.defineProperty()
Reflect.getOwnPropertyDescriptor()
Reflect.ownKeys()
Reflect.preventExtensions()
Reflect.isExtensible()
Reflect.getPrototypeOf()
Reflect.setPrototypeOf()
 Elastyczniejsze API do wielu metod:
 API funkcji
 Operacje jzyka
 Re鍖eksja obiekt坦w
Przykady u甜ycia
Metaprogramming API
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
 Dependency Injection (u甜yte podobnie w AngularJS)
function test ($m, $s) { const fnRegex = /function[s]+[^(]+(([^)]+))/
return $m.pow($s.points, 2) const args = test.toString().match(fnRegex)[1]
} args.split(/[s]*,[s]*/) // [ "$a", "$b" ]
const object = { "key": "value" } // Object.create(object)
function HiddenObject () { }
HiddenObject.prototype = object
const hiddenObject = new HiddenObject()
HiddenObject.prototype = null
hiddenObject // => { "prototype": null }
hiddenObject.key // => "value"
Object.getPrototypeOf(hiddenObject) // => { "key": "value" }
 Ukrywanie prototypu
Deskryptor pola - z czego si mo甜e skada?
Metaprogramming API
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
const object = {}
Object.defineProperty(object, "key", {
value: "Field Value",
// writable: false,
// get: () => "Field Value",
set: function (value) {
this.x = value + "abc"
},
configurable: true,
enumerable: false
}
Object.keys(object) // => []
object.key // => "Field value"
object.x // => undefined
object.key = "Def"
object.key // "Field value"
object.x // => "Defabc"
 Warto pola - value
 Getter / Setter - get/set
 Mo甜na przypisa warto? - writable
 De鍖nicja mo甜e si zmieni? - con鍖gurable
 Pole powinno by widoczne? - enumerable
 writable || set
 value || get
Dekoratory p坦l
Metaprogramming API
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
function readOnly (
target,
propertyName,
descriptor
) {
descriptor.writable = false
}
const object = {
@readOnly
field: "value"
}
object.field // => "value"
object.field = "something"
object.field // => "value"
 Dekoratory mog zmieni deskryptor pola:
 Mog nadpisa jego warto
 Zmieni gettery/settery
 Zapisa informacj jako efekt uboczny
Dekoratory klas
Metaprogramming API
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
function Serializable (Cls) {
Cls.prototype.toString = function () {
const str = JSON.stringify(this)
return Cls.name + ": " + str
}
}
@Serializable
class Point {
constructor (x, y) {
this.x = x
this.y = y
}
}
const point = new Point(1, 5)
console.log(point.toString())
// "Point: {"x":1,"y":5}"
 W klasie dekoratory mog nadpisa klas
lub edytowa jej prototyp w dowolny spos坦b
Dekoratory klas: przykad
Metaprogramming API
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
@Entity()
class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column()
age: number;
}
 ActiveRecord / ORM
 Przykad z TypeORM
https://github.com/typeorm/typeorm
Podstawowe symbole
Zmiana semantyki dziaania programu
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Why do programmers confuse
Halloween with Christmas?
Because OCT 31 = DEC 25.
Czym s symbole?
Podstawowe symbole
// Declare standard symbol
const internal = Symbol()
const symbol = Symbol()
symbol == internal // => false
 U甜ywane jako unikalna warto
 Nie koliduj z innymi typami
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Czym s symbole?
Podstawowe symbole
// Declare standard symbol
const internal = Symbol()
const symbol = Symbol()
symbol == internal // => false
// Prepare example object
const object = {}
// Set up some value in object
object[internal] = "value"
object[internal] + "s" // => "values"
Object.keys(object) // => []
 U甜ywane jako unikalna warto
 Nie koliduj z innymi typami
 Mog by u甜ywane jako klucz obiektu
 Ukryte w obiekcie
poza getOwnPropertySymbols i Re鍖ect.ownKeys
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Czym s symbole?
Podstawowe symbole
// Declare standard symbol
const internal = Symbol.for("debug")
const symbol = Symbol.for("debug")

internal == symbol // => true
Symbol.keyFor(internal) // => debug"
 Mog mie sw坦j identy鍖kator
 Do pobrania przez Symbol.keyFor
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Well-known symbols
Podstawowe symbole
class Something {
// getter in constructor
static get [Symbol.isMagical] () {
return true
}
// getter for instance
get [Symbol.isMagicDone] () {
return "Magic has been done"
}
// method for instance
[Symbol.makeMagic] () {
// Poof!
}
}
 Dostpne w przestrzeni Symbol
 Przykady Symbol.iterator, Symbol.species
 Przypisane do prototypu lub bezporednio
do konstruktora
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Symbol.iterator
Podstawowe symbole
class Range {
constructor (from, to) {
this.from = from
this.to = to
}
*[Symbol.iterator] () {
let i = this.from
while (i <= this.to) {
yield i
i++
}
}
}
const range = [ ...new Range(1, 5) ]
console.log(range) // [ 1, 2, 3, 4, 5 ]
 Pozwala na implementacj iteratora
 forof loop
 spread operator - [ arr ]
 Array.from
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Symbol.toPrimitive
Podstawowe symbole
const person = {
name: "John Doe",
[Symbol.toPrimitive] (hint) {
if (hint === "string") {
return this.name
} else if (hint === "number") {
return this.name.length
}
// "default"
return "Hi, I am " + this.name
}
}
`${person}` // => "John Doe"
+person // => 8
person + "" // => "Hi, I am John Doe"
person + 3 // => "Hi, I am John Doe3"
 Zmiana zachowania przy zrzucaniu do typu
 Rozr坦甜nia prymitywne typy
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Symbol.hasInstance
Podstawowe symbole
const notNode = x => !(x instanceof Node)
class Node {}
class NodeList extends Array {
static get [Symbol.hasInstance] (o) {
const proto = Object.getPrototypeOf(o)
const c = proto.constructor
if (c === NodeList) { return true }
if (!Array.isArray(o)) { return false }
return o.findIndex(notNode) === -1
}
}
const node = new Node()
[ 1 ] instanceof NodeList // => false
[ node ] instanceof NodeList // => true
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
 De鍖niuje dziaanie instanceof
 Sprawdza czy obiekt jest instancj klasy
 Sugar syntax:
obj instanceof Iterable油wyglda油lepiej ni甜:
isIterable(obj) czy Symbol.iterator in obj
Symbol.species
Podstawowe symbole
// Standard behavior
class TimeoutPromise extends Promise {}
const self = x => x
const promise = new TimeoutPromise(self)
promise.then(x => x) // => TimeoutPromise
// Modified behavior
class TimeoutPromise extends Promise {
static get [Symbol.species] () {
return Promise
}
}
const self = x => x
const promise = new TimeoutPromise(self)
promise.then(x => x) // => Promise
 Zmienia zwracany typ z podstawowych metod
 Przydatny jeli chcemy przej do standardu
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Symbol.isConcatSpreadable
Podstawowe symbole
// Standard behavior
const o = {
0: "a",
1: "b",
length: 2
}
[ 1 ].concat(o) // => [ 1,{0:"a",1:"b"} ]
// Modified behavior
const o = {
0: "a",
1: "b",
length: 2,
[Symbol.isConcatSpreadable]: true
}
[ 1 ].concat(o) // => [ 1, "a", "b" ]
 De鍖niuje zachowanie funkcji concat
 Decyduje czy obiekt ma by spaszczony
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Symbol.match, replace, split i search
Podstawowe symbole
const str = "<strong>Success</strong>"
class Tag {
constructor (name) {
this.name = name
}
[Symbol.search] (str) {
return str.indexOf(
"<" + this.name + ">"
)
}
}
str.search(new Tag("strong")) // => 0
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
 De鍖niuj dziaanie obiektu w kilku metodach
 string.split(object)
 string.search(object)
 string.replace(object, replacement)
 string.match(object)
Symbol.toStringTag
Podstawowe symbole
// Standard behavior
const object = {}
"" + object // => "[object Object]"
// Modified behavior
const object = {
[Symbol.toStringTag]: "X"
}
"" + object // => "[object X]"
 De鍖niuje podstawowy tag nazwy obiektu
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Symbol.unscopables
Podstawowe symbole
// Declare object
const object = {
txt1: "value",
txt2: "value2",
[Symbol.unscopables]: { "txt2": true }
}
with (object) {
console.log(txt1) // => "value"
console.log(txt2) // ReferenceError
}
 Blokuje pola dla konstrukcji with {}
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Proxy
Podsuchujemy i przejmujemy aplikacj!
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
- Knock knock.
- Race condition.
- Whos there?
Jak dziaa proxy?
Proxy
function SomeObject () {
this.pre = "Something "
}
const object = new SomeObject()
const proxy = new Proxy(object, {
get (target, property) {
return target.pre + property
}
})
proxy.special // "Something special"
proxy.funny // "Something funny"
Object.getPrototypeOf(proxy).constructor
// SomeObject
 Ustawia puapki (traps) na akcje
 Pozwala dynamicznie na zmiany zachowania
 Ma dostp do prototypu i konstruktora
 Ma dostp do p坦l
 Niezmienione akcje zachowuj si tak samo
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
Gdzie mo甜emy postawi puapki?
Proxy
 Zmiana i pobranie parametru
 Konstrukcja obiektu, wykonanie funkcji
 Zmiana i pobranie prototypu
 Operatory in, delete
 Pobranie kluczy obiektu
 Wicej: http://bit.ly/mdnproxy
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
function Something () {
this.pre = "Something "
}
const object = new X()
const proxy = new Proxy(object, {
get (target, property) {
return target.pre + property
},
set (target, property, value) {
throw new Error("You can't change!")
}
})
Object.getPrototypeOf(proxy) // Something
proxy.special // "Something special"
proxy.special = "xyz" // Error
Przykad: Dependency Injection
Proxy
 Po prawej szkic DI
 brak obsugi bd坦w
 brak poprawnego cache
 niezoptymalizowane
 nie dziaa poprawnie in czy getKeys
 Dynamiczne przypisanie danych
 Mo甜liwo "lazy loadingu"
 Przykad: github.com/rangoo94/easen-di
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
function Di (dependencies = {}) {
const cache = {}
this.proxy = new Proxy(dependencies, {
set (deps, prop, value) {
if (typeof value !== "function") {
throw new TypeError()
}
deps[prop] = value
},
get (deps, prop) {
if (!deps[prop]) {
throw new ReferenceError()
}
if (!cache[prop]) {
cache[prop] = deps[prop]()
}
return cache[prop]
}
})
}
const di = new Di({ x: () => "Hello" })
di.proxy.x // "Hello"
Przykad: Automatyczna walidacja na osobnej warstwie
Proxy
 Walidacja niezale甜na od obiektu kocowego
 Mo甜emy mie jeden obiekt, ale N walidacji
 Walidacja zale甜na od miejsca zmiany
 Przykad - jeden model User zamiast:
 CreatedUser
 PostUser
 AdminUser
 RegularUser
 StaffUser
 SomeWeirdUser
 
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
function Point (x, y) {
this.x = x
this.y = y
}
function assertNumber (x) {
if (typeof x !== "number") {
throw new Error("Incorrect number")
}
}
const checks = {
x: assertNumber,
y: assertNumber
}
function createPoint (...args) {
return new Proxy(new Point(...args), {
set (target, key, value) {
const v = checks[key] || (x => x)
v(value, target)
target[key] = value
}
})
}
Przykad: Prywatne wartoci
Proxy
 Brak dostpu do wartoci
 Bez u甜ycia domkni
 http://bit.ly/privatejs
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
function User (name, password) {
this.name = name
this.password = password
}
User.prototype.login = function () {
console.log(this.name, this.password)
}
function createUser (...args) {
const priv = [ "password" ]
return new Proxy(new User(...args), {
get (target, key) {
return priv.includes(key) ?
undefined : target[key]
},
ownKeys (target) {
return Reflect.ownKeys(target)
.filter(key => !priv.includes(key))
}
})
}
const user = createUser("name", "pass")
Object.keys(user) // [ "name" ]
user.login() // "name" undefined
Przykad: Prywatne wartoci
Proxy
 Brak dostpu do wartoci
 Bez u甜ycia domkni
 this kieruje na proxy, jako metoda proxy
 http://bit.ly/privatejs
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
User.prototype.login = function () {
console.log(this.name, this.password)
}
get (target, key) {
return priv.includes(key) ?
undefined : target[key]
}
function User (name, password) {
this.name = name
this.password = password
}
User.prototype.login = function () {
console.log(this.name, this.password)
}
function createUser (...args) {
const priv = [ "password" ]
return new Proxy(new User(...args), {
get (target, key) {
return priv.includes(key) ?
undefined : target[key]
},
ownKeys (target) {
return Reflect.ownKeys(target)
.filter(key => !priv.includes(key))
}
})
}
const user = createUser("name", "pass")
Object.keys(user) // [ "name" ]
user.login() // "name" undefined
Przykad: Prywatne wartoci
Proxy
 Brak dostpu do wartoci
 Bez u甜ycia domkni
 this kieruje na proxy, jako metoda proxy
 http://bit.ly/privatejs
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
function User (name, password) {
this.name = name
this.password = password
}
/* User.prototype.login as before */
function createUser (...args) {
const priv = [ "password" ]
return new Proxy(new User(...args), {
get (t, key) {
if (typeof t[key] === "function") {
return (...args) => {
return t[key](...args)
}
}
return priv.includes(key) ?
undefined : t[key]
},
ownKeys (target) {
return Reflect.ownKeys(target)
.filter(key => !priv.includes(key))
}
})
}
Przykad: QueryBuilder/DSL
Proxy
 Dynamiczne acuchy funkcjonalnoci
Dawid Rusnak
www.drcode.pl / GitHub: @rangoo94
function QueryBuilder () {
return new Proxy([], {
get (parts, prop, proxy) {
if (prop === "value") {
return parts.join(" ")
}
prop = prop.toUpperCase()
return arg => {
parts.push(`${prop} ${arg}`)
return proxy
}
}
})
}
new QueryBuilder()
.select("*")
.from("articles")
.where("user_id = 10")
.and("visible = true")
.value
// "SELECT * FROM articles
WHERE user_id = 10 AND visible = true"
Dzikuj za uwag!
dawid@drcode.pl
www.drcode.pl
github.com/rangoo94
linkedin.com/in/dawidrusnak
http://bit.ly/metaprogramowaniejs

More Related Content

What's hot (20)

Infrastructure As Code
Infrastructure As CodeInfrastructure As Code
Infrastructure As Code
Kamil Grabowski
Rundeck & Ansible
Rundeck & AnsibleRundeck & Ansible
Rundeck & Ansible
Maciej Lasyk
Uruchomienie i praca z laravel w wirtualnym kontenerze docker'a
Uruchomienie i praca z laravel w wirtualnym kontenerze docker'aUruchomienie i praca z laravel w wirtualnym kontenerze docker'a
Uruchomienie i praca z laravel w wirtualnym kontenerze docker'a
Laravel Poland MeetUp
Laravel Pozna Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...
Laravel Pozna Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...Laravel Pozna Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...
Laravel Pozna Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...
HighSolutions Sp. z o.o.
Webpack - Czym jest webpack i dlaczego chcesz go u甜ywa? - wersja kr坦tka
Webpack - Czym jest webpack i dlaczego chcesz go u甜ywa? - wersja kr坦tkaWebpack - Czym jest webpack i dlaczego chcesz go u甜ywa? - wersja kr坦tka
Webpack - Czym jest webpack i dlaczego chcesz go u甜ywa? - wersja kr坦tka
Marcin Gajda
Kubernetes (Canary) Deployments
Kubernetes (Canary) DeploymentsKubernetes (Canary) Deployments
Kubernetes (Canary) Deployments
The Software House
Monitoring sieci
Monitoring sieciMonitoring sieci
Monitoring sieci
Kamil Grabowski
Ansible - Automatyzacja zada IT
Ansible - Automatyzacja zada ITAnsible - Automatyzacja zada IT
Ansible - Automatyzacja zada IT
Kamil Grabowski
[BDD] Introduction to Behat (PL)
[BDD] Introduction to Behat (PL)[BDD] Introduction to Behat (PL)
[BDD] Introduction to Behat (PL)
Piotr Pelczar
Ansible w praktyce
Ansible w praktyceAnsible w praktyce
Ansible w praktyce
Kamil Grabowski
Sekrety magicznego ogrodu Docker
Sekrety magicznego ogrodu DockerSekrety magicznego ogrodu Docker
Sekrety magicznego ogrodu Docker
Kamil Grabowski
Wprowadzenie do test坦w wydajnociowych w k6
Wprowadzenie do test坦w wydajnociowych w k6Wprowadzenie do test坦w wydajnociowych w k6
Wprowadzenie do test坦w wydajnociowych w k6
The Software House
PHP@Docker - w produkcji
PHP@Docker - w produkcjiPHP@Docker - w produkcji
PHP@Docker - w produkcji
Marcin Kurzyna
Szybkie stawianie aplikacji z Elastic Beanstalk
Szybkie stawianie aplikacji z Elastic BeanstalkSzybkie stawianie aplikacji z Elastic Beanstalk
Szybkie stawianie aplikacji z Elastic Beanstalk
The Software House
Ruby, Ruby on Rails 2010
Ruby, Ruby on Rails 2010Ruby, Ruby on Rails 2010
Ruby, Ruby on Rails 2010
Natalia Stanko
Jak poprawi Core Web Vitals w aplikacji Next.js
Jak poprawi Core Web Vitals w aplikacji Next.jsJak poprawi Core Web Vitals w aplikacji Next.js
Jak poprawi Core Web Vitals w aplikacji Next.js
The Software House
Deployment kodu z Capistrano
Deployment kodu z CapistranoDeployment kodu z Capistrano
Deployment kodu z Capistrano
Micha Szajbe
Automatyzacja utrzymania jakoci w rodowisku PHP
Automatyzacja utrzymania jakoci w rodowisku PHPAutomatyzacja utrzymania jakoci w rodowisku PHP
Automatyzacja utrzymania jakoci w rodowisku PHP
Laravel Poland MeetUp
Shall we play a game? PL version
Shall we play a game? PL versionShall we play a game? PL version
Shall we play a game? PL version
Maciej Lasyk
DynamoDB podstawy modelowania danych dla opornych
DynamoDB  podstawy modelowania danych dla opornychDynamoDB  podstawy modelowania danych dla opornych
DynamoDB podstawy modelowania danych dla opornych
The Software House
Infrastructure As Code
Infrastructure As CodeInfrastructure As Code
Infrastructure As Code
Kamil Grabowski
Rundeck & Ansible
Rundeck & AnsibleRundeck & Ansible
Rundeck & Ansible
Maciej Lasyk
Uruchomienie i praca z laravel w wirtualnym kontenerze docker'a
Uruchomienie i praca z laravel w wirtualnym kontenerze docker'aUruchomienie i praca z laravel w wirtualnym kontenerze docker'a
Uruchomienie i praca z laravel w wirtualnym kontenerze docker'a
Laravel Poland MeetUp
Laravel Pozna Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...
Laravel Pozna Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...Laravel Pozna Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...
Laravel Pozna Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...
HighSolutions Sp. z o.o.
Webpack - Czym jest webpack i dlaczego chcesz go u甜ywa? - wersja kr坦tka
Webpack - Czym jest webpack i dlaczego chcesz go u甜ywa? - wersja kr坦tkaWebpack - Czym jest webpack i dlaczego chcesz go u甜ywa? - wersja kr坦tka
Webpack - Czym jest webpack i dlaczego chcesz go u甜ywa? - wersja kr坦tka
Marcin Gajda
Kubernetes (Canary) Deployments
Kubernetes (Canary) DeploymentsKubernetes (Canary) Deployments
Kubernetes (Canary) Deployments
The Software House
Ansible - Automatyzacja zada IT
Ansible - Automatyzacja zada ITAnsible - Automatyzacja zada IT
Ansible - Automatyzacja zada IT
Kamil Grabowski
[BDD] Introduction to Behat (PL)
[BDD] Introduction to Behat (PL)[BDD] Introduction to Behat (PL)
[BDD] Introduction to Behat (PL)
Piotr Pelczar
Sekrety magicznego ogrodu Docker
Sekrety magicznego ogrodu DockerSekrety magicznego ogrodu Docker
Sekrety magicznego ogrodu Docker
Kamil Grabowski
Wprowadzenie do test坦w wydajnociowych w k6
Wprowadzenie do test坦w wydajnociowych w k6Wprowadzenie do test坦w wydajnociowych w k6
Wprowadzenie do test坦w wydajnociowych w k6
The Software House
PHP@Docker - w produkcji
PHP@Docker - w produkcjiPHP@Docker - w produkcji
PHP@Docker - w produkcji
Marcin Kurzyna
Szybkie stawianie aplikacji z Elastic Beanstalk
Szybkie stawianie aplikacji z Elastic BeanstalkSzybkie stawianie aplikacji z Elastic Beanstalk
Szybkie stawianie aplikacji z Elastic Beanstalk
The Software House
Ruby, Ruby on Rails 2010
Ruby, Ruby on Rails 2010Ruby, Ruby on Rails 2010
Ruby, Ruby on Rails 2010
Natalia Stanko
Jak poprawi Core Web Vitals w aplikacji Next.js
Jak poprawi Core Web Vitals w aplikacji Next.jsJak poprawi Core Web Vitals w aplikacji Next.js
Jak poprawi Core Web Vitals w aplikacji Next.js
The Software House
Deployment kodu z Capistrano
Deployment kodu z CapistranoDeployment kodu z Capistrano
Deployment kodu z Capistrano
Micha Szajbe
Automatyzacja utrzymania jakoci w rodowisku PHP
Automatyzacja utrzymania jakoci w rodowisku PHPAutomatyzacja utrzymania jakoci w rodowisku PHP
Automatyzacja utrzymania jakoci w rodowisku PHP
Laravel Poland MeetUp
Shall we play a game? PL version
Shall we play a game? PL versionShall we play a game? PL version
Shall we play a game? PL version
Maciej Lasyk
DynamoDB podstawy modelowania danych dla opornych
DynamoDB  podstawy modelowania danych dla opornychDynamoDB  podstawy modelowania danych dla opornych
DynamoDB podstawy modelowania danych dla opornych
The Software House

Similar to Metaprogramowanie w JS (20)

Mongodb with Rails
Mongodb with RailsMongodb with Rails
Mongodb with Rails
Sebastian Nowak
Refaktoryzacja
RefaktoryzacjaRefaktoryzacja
Refaktoryzacja
PHPstokPHPstok
Modularny JavaScript - meet.js
Modularny JavaScript - meet.jsModularny JavaScript - meet.js
Modularny JavaScript - meet.js
Patryk Jar
Mvc frontend-trug-02-2011
Mvc frontend-trug-02-2011Mvc frontend-trug-02-2011
Mvc frontend-trug-02-2011
Rafal Piekarski
JavaScript, Moduy
JavaScript, ModuyJavaScript, Moduy
JavaScript, Moduy
Mariusz Nowak
[PL] Jak programowa aby nie zwariowa
[PL] Jak programowa aby nie zwariowa[PL] Jak programowa aby nie zwariowa
[PL] Jak programowa aby nie zwariowa
Jakub Marchwicki
Nowosci w Javie 8 okiem programisty鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深
Nowosci w Javie 8 okiem programisty鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深Nowosci w Javie 8 okiem programisty鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深
Nowosci w Javie 8 okiem programisty鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深
MarcinStachniuk
WordUp Tr坦jmiasto - Sage 9 w praktyce
WordUp Tr坦jmiasto - Sage 9 w praktyceWordUp Tr坦jmiasto - Sage 9 w praktyce
WordUp Tr坦jmiasto - Sage 9 w praktyce
Dawid Urbaski
Testowanie bezpieczestwa aplikacji dedykowanych na platform Android
Testowanie bezpieczestwa aplikacji dedykowanych na platform AndroidTestowanie bezpieczestwa aplikacji dedykowanych na platform Android
Testowanie bezpieczestwa aplikacji dedykowanych na platform Android
SecuRing
AADays 2015 - Jak to zrobic w JavaScript
AADays 2015 - Jak to zrobic w JavaScriptAADays 2015 - Jak to zrobic w JavaScript
AADays 2015 - Jak to zrobic w JavaScript
Jacek Okrojek
Micha Dec - Quality in Clouds
Micha Dec - Quality in CloudsMicha Dec - Quality in Clouds
Micha Dec - Quality in Clouds
kraqa
Using Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentationUsing Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentation
Mariusz Koprowski
RxJS okiem dowiadczonego in甜yniera - Angular Warsaw #13
RxJS okiem dowiadczonego in甜yniera - Angular Warsaw #13RxJS okiem dowiadczonego in甜yniera - Angular Warsaw #13
RxJS okiem dowiadczonego in甜yniera - Angular Warsaw #13
Piotr Kowalski
4Developers 2015: Property-based testing w jzyku Scala - Pawe Grajewski
4Developers 2015: Property-based testing w jzyku Scala - Pawe Grajewski4Developers 2015: Property-based testing w jzyku Scala - Pawe Grajewski
4Developers 2015: Property-based testing w jzyku Scala - Pawe Grajewski
PROIDEA
[Quality Meetup #9] TestOps, QAOps - czy kto taki istnieje? - Aleksandra Kor...
[Quality Meetup #9] TestOps, QAOps - czy kto taki istnieje? - Aleksandra Kor...[Quality Meetup #9] TestOps, QAOps - czy kto taki istnieje? - Aleksandra Kor...
[Quality Meetup #9] TestOps, QAOps - czy kto taki istnieje? - Aleksandra Kor...
Future Processing
Confitura 2018 - Sekretne 甜ycie job坦w Sparkowych
Confitura 2018 - Sekretne 甜ycie job坦w SparkowychConfitura 2018 - Sekretne 甜ycie job坦w Sparkowych
Confitura 2018 - Sekretne 甜ycie job坦w Sparkowych
Marcin Jasiski
Jak nad甜y za wiatem front-endu - WordPress Training Day
Jak nad甜y za wiatem front-endu - WordPress Training DayJak nad甜y za wiatem front-endu - WordPress Training Day
Jak nad甜y za wiatem front-endu - WordPress Training Day
Tomasz Dziuda
Czym jest zozonosc ?
Czym jest zozonosc ?Czym jest zozonosc ?
Czym jest zozonosc ?
GOG.com dev team
Jarorcon Sp
Jarorcon SpJarorcon Sp
Jarorcon Sp
jarorcon
Modularny JavaScript - meet.js
Modularny JavaScript - meet.jsModularny JavaScript - meet.js
Modularny JavaScript - meet.js
Patryk Jar
Mvc frontend-trug-02-2011
Mvc frontend-trug-02-2011Mvc frontend-trug-02-2011
Mvc frontend-trug-02-2011
Rafal Piekarski
JavaScript, Moduy
JavaScript, ModuyJavaScript, Moduy
JavaScript, Moduy
Mariusz Nowak
[PL] Jak programowa aby nie zwariowa
[PL] Jak programowa aby nie zwariowa[PL] Jak programowa aby nie zwariowa
[PL] Jak programowa aby nie zwariowa
Jakub Marchwicki
Nowosci w Javie 8 okiem programisty鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深
Nowosci w Javie 8 okiem programisty鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深Nowosci w Javie 8 okiem programisty鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深
Nowosci w Javie 8 okiem programisty鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深鐃種深
MarcinStachniuk
WordUp Tr坦jmiasto - Sage 9 w praktyce
WordUp Tr坦jmiasto - Sage 9 w praktyceWordUp Tr坦jmiasto - Sage 9 w praktyce
WordUp Tr坦jmiasto - Sage 9 w praktyce
Dawid Urbaski
Testowanie bezpieczestwa aplikacji dedykowanych na platform Android
Testowanie bezpieczestwa aplikacji dedykowanych na platform AndroidTestowanie bezpieczestwa aplikacji dedykowanych na platform Android
Testowanie bezpieczestwa aplikacji dedykowanych na platform Android
SecuRing
AADays 2015 - Jak to zrobic w JavaScript
AADays 2015 - Jak to zrobic w JavaScriptAADays 2015 - Jak to zrobic w JavaScript
AADays 2015 - Jak to zrobic w JavaScript
Jacek Okrojek
Micha Dec - Quality in Clouds
Micha Dec - Quality in CloudsMicha Dec - Quality in Clouds
Micha Dec - Quality in Clouds
kraqa
Using Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentationUsing Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentation
Mariusz Koprowski
RxJS okiem dowiadczonego in甜yniera - Angular Warsaw #13
RxJS okiem dowiadczonego in甜yniera - Angular Warsaw #13RxJS okiem dowiadczonego in甜yniera - Angular Warsaw #13
RxJS okiem dowiadczonego in甜yniera - Angular Warsaw #13
Piotr Kowalski
4Developers 2015: Property-based testing w jzyku Scala - Pawe Grajewski
4Developers 2015: Property-based testing w jzyku Scala - Pawe Grajewski4Developers 2015: Property-based testing w jzyku Scala - Pawe Grajewski
4Developers 2015: Property-based testing w jzyku Scala - Pawe Grajewski
PROIDEA
[Quality Meetup #9] TestOps, QAOps - czy kto taki istnieje? - Aleksandra Kor...
[Quality Meetup #9] TestOps, QAOps - czy kto taki istnieje? - Aleksandra Kor...[Quality Meetup #9] TestOps, QAOps - czy kto taki istnieje? - Aleksandra Kor...
[Quality Meetup #9] TestOps, QAOps - czy kto taki istnieje? - Aleksandra Kor...
Future Processing
Confitura 2018 - Sekretne 甜ycie job坦w Sparkowych
Confitura 2018 - Sekretne 甜ycie job坦w SparkowychConfitura 2018 - Sekretne 甜ycie job坦w Sparkowych
Confitura 2018 - Sekretne 甜ycie job坦w Sparkowych
Marcin Jasiski
Jak nad甜y za wiatem front-endu - WordPress Training Day
Jak nad甜y za wiatem front-endu - WordPress Training DayJak nad甜y za wiatem front-endu - WordPress Training Day
Jak nad甜y za wiatem front-endu - WordPress Training Day
Tomasz Dziuda
Jarorcon Sp
Jarorcon SpJarorcon Sp
Jarorcon Sp
jarorcon

Metaprogramowanie w JS

  • 1. Metaprogramowanie w JS Spojrzenie na interesujce wewntrzne mechanizmy Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 2. Achtung! Danger! Uwaga! Metaprogramowanie w JS Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 3. Zajawka Metaprogramowanie w JS Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 4. Zajawka Metaprogramowanie w JS Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 5. Zajawka Metaprogramowanie w JS Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 6. Zajawka Metaprogramowanie w JS Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 7. Zajawka Metaprogramowanie w JS What the Hack? Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 What the Hack? What the Hack? What the Hack?
  • 8. Agenda Metaprogramowanie w JS Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 Czym jest metaprogramowanie? Metaprogramming API Podstawowe symbole Proxy
  • 9. Czym jest metaprogramowanie? Czyli kilka s坦w teorii Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 Why do JS developers wear glasses? Because they dont C#
  • 10. De鍖nicja Czym jest metaprogramowanie? Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 Program, kt坦ry tworzy lub mody鍖kuje inny program - metaprogram Program, kt坦ry mody鍖kuje samego siebie
  • 11. De鍖nicja Czym jest metaprogramowanie? Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 Program, kt坦ry tworzy lub mody鍖kuje inny program - metaprogram Kompilatory - np. parsowanie i optymalizacja kodu Transpilery - np. mody鍖kacja kodu 甜eby by zgodny z urzdzeniem IDE - np. analiza JSDoc Program, kt坦ry mody鍖kuje samego siebie Mechanizmy re鍖eksji
  • 12. De鍖nicja Czym jest metaprogramowanie? Program, kt坦ry tworzy lub mody鍖kuje inny program - metaprogram Kompilatory - np. parsowanie i optymalizacja kodu Transpilery - np. mody鍖kacja kodu 甜eby by zgodny z urzdzeniem IDE - np. analiza JSDoc Program, kt坦ry mody鍖kuje samego siebie Mechanizmy re鍖eksji Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 13. Mody鍖kacja programu innym programem Czym jest metaprogramowanie? Program, kt坦ry tworzy lub mody鍖kuje inny program - metaprogram Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 #define true false #define private public Robienie zamieszania w C dziki makrom / Zy kod nie zale甜y od jzyka
  • 14. Programowanie re鍖eksyjne Czym jest metaprogramowanie? Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 Introspekcja - czytanie struktury programu Mody鍖kacja - zmiana struktury programu Intercesja - wchodzenie pomidzy - zmiana semantyki jzyka/programu
  • 15. Przykady metaprogramowania Co mo甜emy dziki temu osign? Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 SQL query goes into a bar, walks up to two tables and asks "Can I join you?"
  • 16. Przeci甜anie operator坦w Przykady metaprogramowania Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 // Ruby class X attr_reader :order def +(y) y + 2 end def <=>(other) self.order <=> other.order end end instance = X.new instance + 3 // => 5 // C++ struct X { int operator+(int y) { return y + 2; } }; int main () { X instance; std::cout << instance + 3; // => 5 return 0; }
  • 17. Destruktory Przykady metaprogramowania Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 // Python class X: def __del__(self): self.connection.close() // PHP class X { private function __destruct() { $this->connection->close(); } }
  • 18. Obsuga dynamicznych p坦l Przykady metaprogramowania Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 // PHP class X { public function __get($field) { return $field . " value"; } } // Ruby class X def method_missing(m, *args, &block) "#{m} value" end end
  • 19. Adnotacje i dekoratory Przykady metaprogramowania Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 // Java @Entity public class X { @Id @GeneratedValue @Column(name = "id") private int id; public X() {} } // JavaScript class X { @emitOnEnd("someEvent") doSomething () { console.log("Something there") } }
  • 20. Prywatne wartoci Przykady metaprogramowania Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 // PHP class X { private $name; } // C++ class X { private: string name; }
  • 21. Imitowanie tablicy Przykady metaprogramowania Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 // PHP class X implements ArrayAccess { public function offsetExists ($o) {} public function offsetGet ($o) {} public function offsetSet ($o, $v) {} public function offsetUnset ($o) {} } $instance = new X(); $instance["key"]; $instance[0]; // JavaScript // Array-like object const a = { 0: 1, 1: 4943, 2: 2213, length: 3 } a[0];
  • 22. Przeci甜anie metod/klas Przykady metaprogramowania Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 // Ruby class X def something 'hello!' end end class X def somethingElse 'hello 2!' end end instance = X.new instance.print // => "hello!" instance.printSomething // => "hello 2!" // JavaScript // Works pretty good! function X () {} X.prototype.something = function () { return "hello!" } X.prototype.somethingElse = function () { return "hello 2!" } instance = new X() instance.print() // => "hello!" instance.printSomething() // => "hello 2!
  • 23. Metaprogramming API Podstawowe mo甜liwoci w JavaScript Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 I've got a really good UDP joke to tell you, but I don't know if you'll get it
  • 24. Na co nam pozwala podstawowe API? Metaprogramming API Analiza i mody鍖kacja struktury obiekt坦w Czytanie informacji o funkcjach Zarzdzanie acuchem prototyp坦w Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 25. Analiza i mody鍖kacja obiekt坦w Metaprogramming API Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 Czytanie podstawowej struktury obiekt坦w Zarzdzanie staoci obiekt坦w (mutability) acuch prototyp坦w Object.getPrototypeOf(obj) Object.setPrototypeOf(obj, null) Object.hasOwnProperty("key") // => true Object.getOwnPropertyNames(obj) Object.keys(obj) // => [ "key" ] Object.preventExtensions(obj) Object.isExtensible(obj) // => false Object.seal(obj) Object.isSealed(obj) // => true Object.freeze(obj) Object.isFrozen(obj) // => true
  • 26. Funkcje Metaprogramming API Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 Wykonywanie funkcji Czytanie struktury funkcji Tworzenie funkcji Math.max.call(Math, 10, 20) // => 20 Math.max.apply(Math, [ 10, 20 ]) // => 20 const func = Array.prototype.concat.bind([ 10, 30 ], 20) func(40) // => [ 10, 30, 20, 40 ] function test (a, b) {} test.length // => 2 test.toString() // => "function test (a, b) {}" function test2 (a, ...args) {} test2.length // => 1 const sum = new Function("a", "b", "return a + b") sum(10, 20) // => 30
  • 27. Re鍖ect API Metaprogramming API Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 // Function options wrappers Reflect.apply(Math.max, null, [ 5, 15 ]) Reflect.construct(X, [ "John" ]) // Language wrappers Reflect.has() // in operator Reflect.deleteProperty() // delete Reflect.get() // access property Reflect.set() // set property value // Object methods wrappers Reflect.defineProperty() Reflect.getOwnPropertyDescriptor() Reflect.ownKeys() Reflect.preventExtensions() Reflect.isExtensible() Reflect.getPrototypeOf() Reflect.setPrototypeOf() Elastyczniejsze API do wielu metod: API funkcji Operacje jzyka Re鍖eksja obiekt坦w
  • 28. Przykady u甜ycia Metaprogramming API Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 Dependency Injection (u甜yte podobnie w AngularJS) function test ($m, $s) { const fnRegex = /function[s]+[^(]+(([^)]+))/ return $m.pow($s.points, 2) const args = test.toString().match(fnRegex)[1] } args.split(/[s]*,[s]*/) // [ "$a", "$b" ] const object = { "key": "value" } // Object.create(object) function HiddenObject () { } HiddenObject.prototype = object const hiddenObject = new HiddenObject() HiddenObject.prototype = null hiddenObject // => { "prototype": null } hiddenObject.key // => "value" Object.getPrototypeOf(hiddenObject) // => { "key": "value" } Ukrywanie prototypu
  • 29. Deskryptor pola - z czego si mo甜e skada? Metaprogramming API Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 const object = {} Object.defineProperty(object, "key", { value: "Field Value", // writable: false, // get: () => "Field Value", set: function (value) { this.x = value + "abc" }, configurable: true, enumerable: false } Object.keys(object) // => [] object.key // => "Field value" object.x // => undefined object.key = "Def" object.key // "Field value" object.x // => "Defabc" Warto pola - value Getter / Setter - get/set Mo甜na przypisa warto? - writable De鍖nicja mo甜e si zmieni? - con鍖gurable Pole powinno by widoczne? - enumerable writable || set value || get
  • 30. Dekoratory p坦l Metaprogramming API Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 function readOnly ( target, propertyName, descriptor ) { descriptor.writable = false } const object = { @readOnly field: "value" } object.field // => "value" object.field = "something" object.field // => "value" Dekoratory mog zmieni deskryptor pola: Mog nadpisa jego warto Zmieni gettery/settery Zapisa informacj jako efekt uboczny
  • 31. Dekoratory klas Metaprogramming API Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 function Serializable (Cls) { Cls.prototype.toString = function () { const str = JSON.stringify(this) return Cls.name + ": " + str } } @Serializable class Point { constructor (x, y) { this.x = x this.y = y } } const point = new Point(1, 5) console.log(point.toString()) // "Point: {"x":1,"y":5}" W klasie dekoratory mog nadpisa klas lub edytowa jej prototyp w dowolny spos坦b
  • 32. Dekoratory klas: przykad Metaprogramming API Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 @Entity() class User extends BaseEntity { @PrimaryGeneratedColumn() id: number; @Column() firstName: string; @Column() lastName: string; @Column() age: number; } ActiveRecord / ORM Przykad z TypeORM https://github.com/typeorm/typeorm
  • 33. Podstawowe symbole Zmiana semantyki dziaania programu Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 Why do programmers confuse Halloween with Christmas? Because OCT 31 = DEC 25.
  • 34. Czym s symbole? Podstawowe symbole // Declare standard symbol const internal = Symbol() const symbol = Symbol() symbol == internal // => false U甜ywane jako unikalna warto Nie koliduj z innymi typami Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 35. Czym s symbole? Podstawowe symbole // Declare standard symbol const internal = Symbol() const symbol = Symbol() symbol == internal // => false // Prepare example object const object = {} // Set up some value in object object[internal] = "value" object[internal] + "s" // => "values" Object.keys(object) // => [] U甜ywane jako unikalna warto Nie koliduj z innymi typami Mog by u甜ywane jako klucz obiektu Ukryte w obiekcie poza getOwnPropertySymbols i Re鍖ect.ownKeys Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 36. Czym s symbole? Podstawowe symbole // Declare standard symbol const internal = Symbol.for("debug") const symbol = Symbol.for("debug") internal == symbol // => true Symbol.keyFor(internal) // => debug" Mog mie sw坦j identy鍖kator Do pobrania przez Symbol.keyFor Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 37. Well-known symbols Podstawowe symbole class Something { // getter in constructor static get [Symbol.isMagical] () { return true } // getter for instance get [Symbol.isMagicDone] () { return "Magic has been done" } // method for instance [Symbol.makeMagic] () { // Poof! } } Dostpne w przestrzeni Symbol Przykady Symbol.iterator, Symbol.species Przypisane do prototypu lub bezporednio do konstruktora Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 38. Symbol.iterator Podstawowe symbole class Range { constructor (from, to) { this.from = from this.to = to } *[Symbol.iterator] () { let i = this.from while (i <= this.to) { yield i i++ } } } const range = [ ...new Range(1, 5) ] console.log(range) // [ 1, 2, 3, 4, 5 ] Pozwala na implementacj iteratora forof loop spread operator - [ arr ] Array.from Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 39. Symbol.toPrimitive Podstawowe symbole const person = { name: "John Doe", [Symbol.toPrimitive] (hint) { if (hint === "string") { return this.name } else if (hint === "number") { return this.name.length } // "default" return "Hi, I am " + this.name } } `${person}` // => "John Doe" +person // => 8 person + "" // => "Hi, I am John Doe" person + 3 // => "Hi, I am John Doe3" Zmiana zachowania przy zrzucaniu do typu Rozr坦甜nia prymitywne typy Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 40. Symbol.hasInstance Podstawowe symbole const notNode = x => !(x instanceof Node) class Node {} class NodeList extends Array { static get [Symbol.hasInstance] (o) { const proto = Object.getPrototypeOf(o) const c = proto.constructor if (c === NodeList) { return true } if (!Array.isArray(o)) { return false } return o.findIndex(notNode) === -1 } } const node = new Node() [ 1 ] instanceof NodeList // => false [ node ] instanceof NodeList // => true Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 De鍖niuje dziaanie instanceof Sprawdza czy obiekt jest instancj klasy Sugar syntax: obj instanceof Iterable油wyglda油lepiej ni甜: isIterable(obj) czy Symbol.iterator in obj
  • 41. Symbol.species Podstawowe symbole // Standard behavior class TimeoutPromise extends Promise {} const self = x => x const promise = new TimeoutPromise(self) promise.then(x => x) // => TimeoutPromise // Modified behavior class TimeoutPromise extends Promise { static get [Symbol.species] () { return Promise } } const self = x => x const promise = new TimeoutPromise(self) promise.then(x => x) // => Promise Zmienia zwracany typ z podstawowych metod Przydatny jeli chcemy przej do standardu Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 42. Symbol.isConcatSpreadable Podstawowe symbole // Standard behavior const o = { 0: "a", 1: "b", length: 2 } [ 1 ].concat(o) // => [ 1,{0:"a",1:"b"} ] // Modified behavior const o = { 0: "a", 1: "b", length: 2, [Symbol.isConcatSpreadable]: true } [ 1 ].concat(o) // => [ 1, "a", "b" ] De鍖niuje zachowanie funkcji concat Decyduje czy obiekt ma by spaszczony Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 43. Symbol.match, replace, split i search Podstawowe symbole const str = "<strong>Success</strong>" class Tag { constructor (name) { this.name = name } [Symbol.search] (str) { return str.indexOf( "<" + this.name + ">" ) } } str.search(new Tag("strong")) // => 0 Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 De鍖niuj dziaanie obiektu w kilku metodach string.split(object) string.search(object) string.replace(object, replacement) string.match(object)
  • 44. Symbol.toStringTag Podstawowe symbole // Standard behavior const object = {} "" + object // => "[object Object]" // Modified behavior const object = { [Symbol.toStringTag]: "X" } "" + object // => "[object X]" De鍖niuje podstawowy tag nazwy obiektu Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 45. Symbol.unscopables Podstawowe symbole // Declare object const object = { txt1: "value", txt2: "value2", [Symbol.unscopables]: { "txt2": true } } with (object) { console.log(txt1) // => "value" console.log(txt2) // ReferenceError } Blokuje pola dla konstrukcji with {} Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 46. Proxy Podsuchujemy i przejmujemy aplikacj! Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 - Knock knock. - Race condition. - Whos there?
  • 47. Jak dziaa proxy? Proxy function SomeObject () { this.pre = "Something " } const object = new SomeObject() const proxy = new Proxy(object, { get (target, property) { return target.pre + property } }) proxy.special // "Something special" proxy.funny // "Something funny" Object.getPrototypeOf(proxy).constructor // SomeObject Ustawia puapki (traps) na akcje Pozwala dynamicznie na zmiany zachowania Ma dostp do prototypu i konstruktora Ma dostp do p坦l Niezmienione akcje zachowuj si tak samo Dawid Rusnak www.drcode.pl / GitHub: @rangoo94
  • 48. Gdzie mo甜emy postawi puapki? Proxy Zmiana i pobranie parametru Konstrukcja obiektu, wykonanie funkcji Zmiana i pobranie prototypu Operatory in, delete Pobranie kluczy obiektu Wicej: http://bit.ly/mdnproxy Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 function Something () { this.pre = "Something " } const object = new X() const proxy = new Proxy(object, { get (target, property) { return target.pre + property }, set (target, property, value) { throw new Error("You can't change!") } }) Object.getPrototypeOf(proxy) // Something proxy.special // "Something special" proxy.special = "xyz" // Error
  • 49. Przykad: Dependency Injection Proxy Po prawej szkic DI brak obsugi bd坦w brak poprawnego cache niezoptymalizowane nie dziaa poprawnie in czy getKeys Dynamiczne przypisanie danych Mo甜liwo "lazy loadingu" Przykad: github.com/rangoo94/easen-di Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 function Di (dependencies = {}) { const cache = {} this.proxy = new Proxy(dependencies, { set (deps, prop, value) { if (typeof value !== "function") { throw new TypeError() } deps[prop] = value }, get (deps, prop) { if (!deps[prop]) { throw new ReferenceError() } if (!cache[prop]) { cache[prop] = deps[prop]() } return cache[prop] } }) } const di = new Di({ x: () => "Hello" }) di.proxy.x // "Hello"
  • 50. Przykad: Automatyczna walidacja na osobnej warstwie Proxy Walidacja niezale甜na od obiektu kocowego Mo甜emy mie jeden obiekt, ale N walidacji Walidacja zale甜na od miejsca zmiany Przykad - jeden model User zamiast: CreatedUser PostUser AdminUser RegularUser StaffUser SomeWeirdUser Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 function Point (x, y) { this.x = x this.y = y } function assertNumber (x) { if (typeof x !== "number") { throw new Error("Incorrect number") } } const checks = { x: assertNumber, y: assertNumber } function createPoint (...args) { return new Proxy(new Point(...args), { set (target, key, value) { const v = checks[key] || (x => x) v(value, target) target[key] = value } }) }
  • 51. Przykad: Prywatne wartoci Proxy Brak dostpu do wartoci Bez u甜ycia domkni http://bit.ly/privatejs Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 function User (name, password) { this.name = name this.password = password } User.prototype.login = function () { console.log(this.name, this.password) } function createUser (...args) { const priv = [ "password" ] return new Proxy(new User(...args), { get (target, key) { return priv.includes(key) ? undefined : target[key] }, ownKeys (target) { return Reflect.ownKeys(target) .filter(key => !priv.includes(key)) } }) } const user = createUser("name", "pass") Object.keys(user) // [ "name" ] user.login() // "name" undefined
  • 52. Przykad: Prywatne wartoci Proxy Brak dostpu do wartoci Bez u甜ycia domkni this kieruje na proxy, jako metoda proxy http://bit.ly/privatejs Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 User.prototype.login = function () { console.log(this.name, this.password) } get (target, key) { return priv.includes(key) ? undefined : target[key] } function User (name, password) { this.name = name this.password = password } User.prototype.login = function () { console.log(this.name, this.password) } function createUser (...args) { const priv = [ "password" ] return new Proxy(new User(...args), { get (target, key) { return priv.includes(key) ? undefined : target[key] }, ownKeys (target) { return Reflect.ownKeys(target) .filter(key => !priv.includes(key)) } }) } const user = createUser("name", "pass") Object.keys(user) // [ "name" ] user.login() // "name" undefined
  • 53. Przykad: Prywatne wartoci Proxy Brak dostpu do wartoci Bez u甜ycia domkni this kieruje na proxy, jako metoda proxy http://bit.ly/privatejs Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 function User (name, password) { this.name = name this.password = password } /* User.prototype.login as before */ function createUser (...args) { const priv = [ "password" ] return new Proxy(new User(...args), { get (t, key) { if (typeof t[key] === "function") { return (...args) => { return t[key](...args) } } return priv.includes(key) ? undefined : t[key] }, ownKeys (target) { return Reflect.ownKeys(target) .filter(key => !priv.includes(key)) } }) }
  • 54. Przykad: QueryBuilder/DSL Proxy Dynamiczne acuchy funkcjonalnoci Dawid Rusnak www.drcode.pl / GitHub: @rangoo94 function QueryBuilder () { return new Proxy([], { get (parts, prop, proxy) { if (prop === "value") { return parts.join(" ") } prop = prop.toUpperCase() return arg => { parts.push(`${prop} ${arg}`) return proxy } } }) } new QueryBuilder() .select("*") .from("articles") .where("user_id = 10") .and("visible = true") .value // "SELECT * FROM articles WHERE user_id = 10 AND visible = true"