Станислав Говоров, Яндекс
Станислав Говоров,
Системный инженер
{
key1 : value,
key2 : value2,
}
//...and a bit magic
//create empty object
let obj1 = {}; // not really empty
let obj2 = Object.create(Object.prototype);
let obj3 = Object.create(null);
Symbol
Symbol('val') === Symbol('val') //false !!!let obj = {};
obj['123'] = {a:'b'};
obj[123] === obj['123']; //true
//obj.123 - ERROR - not valid identificator
let obj1 = { name : 'Doge' };
obj.wow = 'much prop';
obj['wow'] = 'such value';
//Calculated property names:
let calculated = 'doge';
let obj2 = {[calculated] : 'WOW'};
//ES5:
var calculated = 'doge';
var obj2 = {};
obj2[calculated] = 'WOW';
//Shorthand property names
let name = 'Ilya';
let obj3 = {name};
//ES5:
var obj3 = { name: name };
Object.defineProperty(obj1,'anotherProp',{
value : 'another value',
writeable : true,
configurable : true,
enumerable : true,
});
//!! not obj.defineProperty !!!
//same as
obj1.anotherProp = 'another value';
Object.defineProperty(obj, prop, descriptor)
Descriptor:
{
//descriptors and default values
configurable : false,
enumerable : false,
value : undefined,
writeable : false,
get : undefined,
set : undefined,
}
for .. in and Object.keyslet obj = {};
Object.defineProperty(obj,'magicProp',{
get: function(){
console.log('getter invoked');
return 42;
},
set: function(){
console.log('setter invoked');
this.magicProp = '21';
},
});
Object.defineProperties(obj, descriptors)
Object.keys(obj),
Object.getOwnPropertyNames(obj)
Object.getOwnPropertyDescriptor(obj, prop)
Object.preventExtensions(obj)
Object.seal(obj)
Object.freeze(obj)
Object.isExtensible(obj)
Object.isSealed(obj)
Object.isFrozen(obj)
class ThisIsNotAClass {
static whoAmI(){
return typeof this;
}
}
ThisIsNotAClass.whoAmI()
"function"
WATJavaScript classes introduced in ECMAScript 6 are syntactical sugar over JavaScript’s existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance.
ES6 way:
class MyAwesomeClass {
constructor(){
this.importantProp = 'importantValue';
}
coolMethod(){
console.log('coolMethod invoked');
}
static andStaticOne(){
console.log('static method invoked');
}
}
let instance = new MyAwesomeClass();
Pre-ES6 way:
const MyAwesomeClass = function(){
this.importantProp = 'importantValue';
}
MyAwesomeClass.prototype = {
coolMethod: function(){
console.log('coolMethod invoked');
},
};
MyAwesomeClass.andStaticOne = function(){
console.log('static method invoked');
};
let instance = new MyAwesomeClass();
Ok. What about inheritance?
ES6 way:
class AwesomeChildClass extends MyAwesomeClass {
childMethod(){
console.log('child method invoked');
}
coolMethod(){
console.log('redeclared method');
}
}
Pre-ES6 way:
const AwesomeChildClass.prototype = Object.create(MyAwesomeClass);
AwesomeChildClass.prototype.childMethod = function(){
console.log('child method invoked');
}
AwesomeChildClass.prototype.coolMethod = function(){
console.log('redeclared method');
}
:) Mix ES6 and pre-ES6:
const MyAwesomeClass = function(){
this.importantProp = 'importantValue';
}
class ChildClass extends MyAwesomeClass();
let instance = new ChildClass();
undefinedclass Coffee {}
let latte = new Coffee();
let isCoffee = latte instanceof Coffee; // true
let arr = [];
arr instanceof Array; // true
arr instanceof Object; // true
obj instanceof Constructor
obj.__proto__ === Constructor.prototypeobj = obj.__proto__vs
??
hasOwnProperty!
Object.prototype.hasOwnProperty()
To check whether an object has a property defined on itself and not somewhere on its prototype chain, it is necessary to use the hasOwnProperty method which all objects inherit from Object.prototype.
hasOwnPropertyis the only thing in JavaScript which deals with properties and does not traverse the prototype chain.
Note: It is not enough to check whether a property is undefined. The property might very well exist, but its value just happens to be set to undefined.
Array.prototype.forEach = function(){
console.log('PWNED')
};
[1,2,3,4,5,6,7].forEach(function(element,index,arr){
console.log(element);
});
"PWNED"
very dynamic :)
class PepperoniPizza {
get type() {
return 'pepperoni';
};
}
class QuattroFormaggiPizza {
get type() {
return 'quattro formaggi';
}
}
class BigTastyPizza extends PepperoniPizza {
size() {
return '40cm';
}
}
console.log(Object.getPrototypeOf(BigTastyPizza) === PepperoniPizza);
true
let hotPizza = new BigTastyPizza();
console.log(hotPizza.size());
"40cm"
Object.setPrototypeOf(BigTastyPizza,QuattroFormaggiPizza);
console.log(Object.getPrototypeOf(BigTastyPizza) === PepperoniPizza);
false
console.log(
Object.getPrototypeOf(BigTastyPizza) === QuattroFormaggiPizza
);
true

Warning: Changing the
[[Prototype]]of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent inobj.__proto__ = ...statement, but may extend to any code that has access to any object whose[[Prototype]]has been altered. If you care about performance you should avoid setting the[[Prototype]]of an object. Instead, create a new object with the desired[[Prototype]]using Object.create().
new operator in a nutshelllet object = new Constructor(arguments);
//1
let obj = {};
//2
Object.setPrototypeOf(obj,Object.getPrototypeOf(Constructor));
//3
let constructorResult = Constructor.apply(obj,arguments);
//4
return constructorResult instanceof Object ? constructorResult : instance;


One thread
(web workers API)
Event Loop
while(queue.waitForMessage()){
queue.processNextMessage();
}
Functions in Stack
Objects allocated in a Heap
Callback Queue
“Run-to-completion”
non-blocking
alert, confirm, promptdebuggerlet timerId = setTimeout(func,timeout);
console.log('3.. 2.. 1.. Go!');
setTimeout(function(){
console.log('horse finished');
}, 5);
let carTimer = setTimeout(function(){
console.log('racecar finished');
}, 20);
clearTimeout(carTimer);
var endDate = +new Date() + 100;
while (+new Date() < endDate){} //do nothing
console.log('turtle finished');
"turtle finished"
"horse finished"
for (var i=1; i <= 5; i++){
setTimeout(function(){
console.log(i);
},0);
}
6
6
6
6
6
for (let i=1; i <= 5; i++){
setTimeout(function(){
console.log(i);
},0);
}
1
2
3
4
5



//...
http.get(
'cat.gif',
onComplete(cat){
console.log(cat);
},
onError(e){
console.error('details');
}
);
//...
askServiceOne(
param,
onCompleteOne(),
onErrorOne(),
);
askServiceOne(
param,
function onCompleteOne(){
doSomething();
askServiceTwo();
},
function onErrorOne(){
//error handling one
},
);
askServiceOne(
param,
function onCompleteOne(){
doSomething();
askServiceTwo('param',
function onCompleteTwo(){
doSomethingTwo();
},
function onErrorTwo(){
//error handling two
},
});
}),
function onErrorOne(){
//error handling one
}),
);
askServiceOne(
param,
onCompleteOne(function(){
doSomething();
askServiceTwo('param',
function onCompleteTwo(){
doSomethingTwo();
askService100500({
'param100500',
function onComplete100500(){
console.log('OH GOD WHY??');
},
function onError100500(){
//error handling logic
},
});
}),
function onErrorTwo(){
//error handling two
}),
});
}),
onErrorOne(function(){
//error handling one
}),
);

},
},
},
},
},
},
},
},
},

askService('param');
listener.on('service:success', function(){
});
listener.on('service:pending', function(){
});
listener.on('service:fail', function(){
});
listener.on('service:done', function(){
});
listener.on('service:accessDenied', function(){
});
askServiceOne(
param,
onCompleteOne(function(){
doSomething();
askServiceTwo('param',
function onCompleteTwo(){
doSomethingTwo();
askService100500({
'param100500',
function onComplete100500(){
console.log('OH GOD WHY??');
},
function onError100500(){
//error handling logic
},
});
}),
function onErrorTwo(){
//error handling two
}),
});
}),
onErrorOne(function(){
//error handling one
}),
);
let flags = [];
askServiceOne(
param,
onCompleteOne(function(){
doSomething();
flags.push('one');
askServiceTwo('param',
function onCompleteTwo(){
doSomethingTwo();
flags.push('two');
askService100500({
'param100500',
function onComplete100500(){
flags.push('100500');
console.log('OH GOD WHY??');
},
function onError100500(){
//error handling logic
},
});
}),
function onErrorTwo(){
//error handling two
}),
});
}),
onErrorOne(function(){
//error handling one
}),
);

askService(param)
.then(callback1)
.catch(handler1)
.then(callback2)
.catch(handler2)
.then(callback3)
.catch(handler3)
.then(callback4)
.catch(handler4)
Chaining
Asynchronous catch

var promise = new Promise(function(resolve, reject) {
//business logic
//call resolve(result) or reject(error) when you need it
});
promise.then(onResolve,onReject);
pendingfulfilled (resolved)rejectedresolve/rejectthenablelet monkey = new Promise(function(resolve,reject){
let r = Math.round(Math.random());
if (r === 0){
resolve('OK');
}
else {
reject('o0');
}
});
//async one
let asyncMonkey = new Promise(function(resolve,reject){
let res = Math.round(r);
let r = Math.random();
setTimeout(function(){
if (res === 0){
resolve('OK');
}
else {
reject('o0');
}
},r*10000);
});
asyncMonkey.then(
function(result){
console.log(result); //OK
},
function(error){
console.error(error); //o0
}
);
asyncMonkey.then(
//logic
);
asyncMonkey.then(
//logic
);
asyncMonkey.then(
//logic
);
{
PromiseState : "pending", //rejected/resolved
PromiseResult : undefined,
PromiseFulFillReactions : [],
PromiseRejectReactions : [],
}
then - the magic
allrace


It’s like an asynchronous immutable array
underscore for events
/* Get stock data somehow */
const source = getAsyncStockData();
const subscription = source
.filter(quote => quote.price > 30)
.map(quote => quote.price)
.subscribe(
price => console.log(`Prices higher than $30: ${price}`),
err => console.log(`Something went wrong: ${err.message}`)
);
/* When we're done */
subscription.dispose();
let previousValue;
let currentRequest;
const callback = _.debounce(function(e){
let value = $input.val();
if (previousValue !== value) {
//fetch autocomplete results
if (currentRequest){
currentResuest.cancel();
}
currentRequest = http.get('/url')
.then(function(){
//callback
});
//...
previousValue = value;
}
});
$input.on('input',callback);
//assume we have rxjs-based http service
//this.requestSubscription;
this.inputField.onValueChange()
.debounce(400)
.distinctUntilChanged()
.subscribe((value)=>{
requestSubscription = this.http.get('/url')
.subscribe((data)=>{
//callback
});
});
this.requestSubscription.unsubscribe(); //will cancel automatically!

google.com :)