Ondřej Žára, @0ndras
this
let fun = function() { alert(this); }
fun(); /* ? */
let obj1 = { fun:fun };
let obj2 = { fun:fun };
obj1.fun(); /* this == obj1 */
obj2.fun(); /* this == obj2 */
fun == obj1.fun == obj2.fun
this
this
je objekt vlevothis
globální jmenný prostorthis
lze explicitně určitlet fun = function() { alert(this); }
let obj1 = {};
let obj2 = {};
fun.call(obj1, arg1, ...); /* this == obj1 */
fun.apply(obj2, [arg1, ...]); /* this == obj2 */
this
– bindlet f1 = function() { alert(this.name); }
let foo = { name:"foo" }
let bar = { name:"bar" }
f1.call(foo); /* "foo" */
let f2 = f1.bind(bar);
f2() /* "bar" */
this
– bindthis
let plus = (a, b) => a+b;
this
v těle arrow function je vždy shodná s hodnotou this
v obalující funkcicall
/apply
: hodnota prvního parametruundefined
let obj1 = { klic:"hodnota" };
let obj2 = Object.create(obj1);
alert(obj2.klic); /* "hodnota" */
Object.getPrototypeOf(obj2) == obj1;
// obj2.__proto__ == obj1;
let obj1 = { klic:"hodnota" };
let obj2 = Object.create(obj1);
let obj3 = Object.create(obj2);
obj3.klic = "jina hodnota";
obj1.jinyKlic = "jeste jina hodnota";
alert(obj2.klic); /* "hodnota" */
alert(obj3.klic); /* "jina hodnota" */
alert(obj3.jinyKlic); /* "jeste jina hodnota" */
V JS jsou tři způsoby tvorby objektů
let x = {p: 3.14}
let x = Object.create(y)
new
new
.prototype
new f
vytvoří nový objekt, nastaví mu prototypovou vazbu na f.prototype
a vykoná nad ním f()
prototype
vs. __proto__
vs. [[Prototype]]
new
let F = function() {
this.a = 1;
}
F.prototype.b = 2;
let f = new F();
f.c = 3;
new
vlastnoručněfunction myNew(ctor, ...args) {
let inst = Object.create(ctor.prototype);
let result = ctor.apply(inst, args);
return (typeof(result) == "object" ? result : inst);
}
let Parent = function() {}
Parent.prototype.hi = function() { return "hello"; }
let Child = function() {}
Child.prototype = Object.create(Parent.prototype);
/* alternativně: Child.prototype = new Parent(); */
let ch = new Child();
ch.hi(); /* "hello" */
String.prototype.lpad = function(what, length) {
let count = length - this.length;
let padding = "";
for (let i=0; i<count; i++) { padding += what; }
return padding + this;
}
Function.prototype.bind = function(thisObj, ...args1) {
let fn = this;
return function(...args2) {
return fn.apply(thisObj, args1.concat(args2));
}
}
class
class Child extends Parent {
doStuff() {
super.doStuff();
}
}
/* ↑↓ */
function Child() {}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.doStuff = function() {
return Parent.prototype.doStuff();
}
Nepodporujeme atribut prototype, který je u všech objektů. Tento atribut je normou povolen a přidává do objektu nové metody a atributy (případně s danou hodnotou). Tento atribut jsme neimplementovali, protože by byl problém ho implementovat a jsme toho názoru, že je k ničemu.
— prohlížeč Links, projektová dokumentace
select
/epoll
let scheduledJS = "";
let listeners = [];
while (1) {
eval(scheduledJS); /* TADY se vykoná JS */
if (!listeners.length) break;
/* počkat, než bude čas na nejbližší posluchač */
let currentListener = waitFor(listeners);
/* naplánovat jej */
scheduledJS = listeners[currentListener];
delete listeners[currentListener];
}
Jak naplánovat další vykonávání JS?
addEventListener
setTimeout
/setInterval
requestAnimationFrame
Víte, co a proč udělá tato funkce?
function s(a) {
while (a.length) {
let v = a.shift();
setTimeout(a.push.bind(a, v), v);
}
}
Nevýhody callbacků
Promise
je standardizován až v ES6let promise = doAsyncStuff();
promise.then(okCallback, errorCallback);
promise.then(anotherCallback); // téměř se nepoužívá
promise.then(x).then(y);
Metoda then()
vrací novou Promise, závislou na návratové hodnotě callbacku
let promise = doAsyncStuff1();
promise.then(doAsyncStuff2).then(console.log);
doAsyncStuff().then(null, onError)
doAsyncStuff().catch(onError)
// finalize v obou případech, tj. chyba se nepropaguje
doAsyncStuff().then(ok, err).then(finalize);
// implicitní try-catch kolem vykonání cb
doAsyncStuff().then(cb).catch(err);
let pSetTimeout = function(delay) {
let executor = function(resolve, reject) {
setTimeout(resolve, delay);
}
return new Promise(executor);
}
pSetTimeout(3000).then(...);
Promise.resolve(value)
, Promise.reject(error)
Promise.all(arrayOfPromises)
Promise.race(arrayOfPromises)
Důvod: stejné chování synchronních i asynchronních funkcí!
// stejné jako setTimeout(() => console.log(42), 0)
Promise.resolve(42).then(console.log);
console.log("lolwut");