Никита Дубко, iTechArt Group
Никита Дубко, iTechArt Group
Императивный подход | Декларативный подход |
---|---|
|
Адрес: город Минск, проспект Независимости 116 |
var fibonacci = _.memoize(function(n) {
return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
});
var throttled = _.throttle(updatePosition, 100);
window.addEventListener('scroll', throttled);
var abc = function(a, b, c) {
return [a, b, c];
};
var curried = _.curry(abc);
curried(1)(2)(3); // => [1, 2, 3]
_.delay(function(text) {
console.log(text);
}, 1000, 'later');
var handler = {
get: function(target, name) {
return (name in target) ? target[name] : 42;
}
};
var p = new Proxy({}, handler);
p.a = 1;
console.log(p.a, p.b); // 1, 42
Декоратор (англ. Decorator) — структурный шаблон проектирования, предназначенный для динамического подключения дополнительного поведения к объекту. Шаблон Декоратор предоставляет гибкую альтернативу практике создания подклассов с целью расширения функциональности.
public class Person
{
[Display(Name = "Имя")]
[Required()]
public string FirstName { get; set; }
[Display(Name = "Отчество")]
public string Patronym { get; set; }
}
@Service("testBean")
@Scope("singleton")
public class TestBean {
private String data = "I am a singleton!!";
public String getData() {
return data;
}
}
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
@makebold
def hello():
return "hello world"
class TonyStark {
constructor() {
this.isBillionaire = true;
this.isPlayboy = true;
this.isPhilanthropist = true;
}
}
@Avenger
@Armor('Mark III')
@Assistant('J.A.R.V.I.S')
class TonyStark {
constructor() {
this.isBillionaire = true;
this.isPlayboy = true;
this.isPhilanthropist = true;
}
}
@Avenger
@Armor('Iron Captain')
class StevenRogers {
constructor() {
this.isLeader = true;
this.equipment = [
new VibraniumShield(),
new VibraniumHelmet()
];
}
}
@Avenger
@Armor('Iron Hulk')
class BruceBanner {
constructor() {
this.isAngry = false;
}
toggle() {
this.isAngry = !this.isAngry;
}
get isSmart() {
return !this.isAngry;
}
}
wycats / javascript-decorators
function decorator(...args) {
return function(target, name, descriptor) {
// do something
return descriptor;
}
}
Object.defineProperty(target, name, {
enumerable: true,
configurable: true,
writable: true,
value: 42,
// get: function() {},
// set: function(value) {}
});
const meetup = {
name: 'MinskJS',
number: 3
};
const meetup = Object.defineProperties({}, {
name: {
value: 'MinskJS',
writable: true,
enumerable: true,
configurable: true
},
number: {
value: 3,
writable: true,
enumerable: true,
configurable: true
}
});
const obj = {
get getter() { return 42; },
property: true,
method: function() {
return "I am the method";
}
};
['getter', 'property', 'method'].forEach(p => {
console.log(
Object.getOwnPropertyDescriptor(obj, p)
);
});
@classDecorator
class MyClass {
@propertyDecorator
property = 42
@methodDecorator
someMethod() {}
}
/* https://jsfiddle.net/dark_mefody/gL1j34sw/9/ */
function decorator(id) {
console.log(id + ' declaration');
return function(target, name, descriptor) {
console.log(id + ' calling');
};
}
@decorator('1st')
@decorator('2nd')
class MyClass {
constructor() {
console.log('new object created');
}
}
const c = new MyClass();
{
kind: "method" or "field",
key: String, Symbol or Private Name,
placement: "static", "prototype" or "own",
descriptor: Property Descriptor
}
class MyClass {
@First("test")
@Second
method() { }
}
var MyClass = (function () {
function MyClass() {}
MyClass.prototype.method = function () { }
var _temp;
_temp = First("test")(MyClass.prototype, "method",
_temp = Second(MyClass.prototype, "method",
_temp = Object.getOwnPropertyDescriptor(
MyClass.prototype,
"method"
)) || _temp)
|| _temp;
if (_temp) Object.defineProperty(MyClass.prototype, "method", _temp);
return Foo;
})();
<form className='new-item' onSubmit={this.addItem.bind(this)}>
class AddNewItemComponent extends React.Component {
@autobind
addItem(event) { ... }
render() {
return ( ...
<form className='new-item' onSubmit={this.addItem}>
... );
}
}
function checkPermission(target, name, descriptor) {
const oldValue = descriptor.value;
const newDescriptor = {
enumerable: false,
configurable: false,
get: function() {
return isAdmin() ? oldValue : (() => {});
},
set: function() {}
};
return newDescriptor;
}
function fluent(target, name, descriptor) {
const fn = descriptor.value;
descriptor.value = function(...args) {
fn.apply(target, args);
return target;
}
}
class Person {
@fluent
setName(name) { this.name = name; }
sayName() { console.log(this.name); }
}
const p = new Person();
p.setName('Bruce').sayName();
@Component({
selector: 'minsk-js',
template: `Hello, MinskJS #<%= number %>!
`
})
class MinskJsComponent {
number = 3
}
bootstrap();
import _ from 'lodash';
const COMPONENTS = [];
function Component(config) {
config.template = _.template(config.template);
return function(target) {
config.class = target;
COMPONENTS.push(config);
}
}
const bootstrap = function() {
COMPONENTS.forEach(component => {
document
.querySelectorAll(component.selector)
.forEach(node => {
const instance = new component.class();
node.innerHTML = component.template(instance);
});
});
};
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
npm install --save-dev babel-plugin-transform-decorators-legacy
{
"presets": ["env"],
"plugins": ["transform-decorators-legacy"]
}
import { autobind } from 'core-decorators';
class Person {
@autobind
getPerson() {
return this;
}
}
const person = new Person();
const { getPerson } = person;
getPerson() === person; // true
import { Debounce, Memoize } from 'lodash-decorators';
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Debounce(100)
save(date) {
return this.httpService.post(data);
}
@Memoize(item => item.id)
doSomeHeavyProcessing(arg1, arg2) {}
}
import { Mixin } from 'lodash-decorators';
const MyOtherApi = {
method() {
// Do something cool
}
};
@Mixin(MyOtherApi)
class Person {}
Person.prototype.method === MyOtherApi.method; // => true
mefody.github.io/talks/js-decorators/
@dark_mefody
n.a.dubko@gmail.com