Created
September 29, 2015 12:45
-
-
Save SerafimArts/650b43d830d021ae7c2e to your computer and use it in GitHub Desktop.
ES Example (ES6 Symbol + ES7 Decorators + ES7 Object properties)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Observable from "Observable"; | |
class AuthController { | |
@Observable | |
user = null; | |
@Observable | |
isAuth = false; | |
constructor() { | |
// Update isAuth if user variable exists | |
this.user.after(value => this.isAuth = value instanceof User); | |
// Remove user if isAuth == false | |
this.isAuth.after(value => { | |
if (!value) { this.user = null; } | |
}); | |
} | |
loginAs(user) { | |
this.user = user; | |
} | |
logout() { | |
this.isAuth = false; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* ObservablePrimitive instance | |
*/ | |
class ObservablePrimitive { | |
/** | |
* @constructor | |
* @param value | |
*/ | |
constructor(value = null) { | |
this.events = { | |
before: [], | |
after: [], | |
all: [] | |
}; | |
Object.defineProperty(this, '$value', { | |
enumerable: false, | |
value: value | |
}); | |
} | |
/** | |
* @param value | |
* @return void | |
*/ | |
set value(value) { | |
var exists = typeof value !== "undefined" && value !== null; | |
var oldValue = this.$value; | |
if (exists) { | |
this.events.before.forEach((c) => c(oldValue)); | |
this.$value = value; | |
this.events.all.forEach((c) => c(oldValue, value)); | |
this.events.after.forEach((c) => c(value)); | |
} | |
} | |
/** | |
* Return value | |
* @return {*} | |
*/ | |
get value() { | |
return this.$value; | |
} | |
/** | |
* @param callback | |
* @returns {ObservablePrimitive} | |
*/ | |
after(callback) { | |
this.events.after.push(callback); | |
return this; | |
} | |
/** | |
* @param callback | |
* @returns {ObservablePrimitive} | |
*/ | |
before(callback) { | |
this.events.before.push(callback); | |
return this; | |
} | |
/** | |
* @param callback | |
* @returns {ObservablePrimitive} | |
*/ | |
subscribe(callback) { | |
this.events.all.push(callback); | |
return this; | |
} | |
/** | |
* @returns {*} | |
*/ | |
toString() { | |
return this.value; | |
} | |
/** | |
* @returns {*} | |
*/ | |
[Symbol.toPrimitive]() { | |
return this.value; | |
} | |
} | |
/** | |
* Observable decorator | |
* | |
* @param target | |
* @param key | |
* @param descriptor | |
* @returns {{enumerable, get, set}} | |
* @constructor | |
*/ | |
export default function Observable(target, key, descriptor) { | |
return (function (descriptor) { | |
var value = descriptor.initializer(); | |
var property = new ObservablePrimitive(value); | |
return { | |
enumerable: true, | |
get: () => property, | |
set: (value) => property.value = value | |
}; | |
})(descriptor); | |
} |
P.S. Не выкладывай ссылки на babel, они обрезаются, т.к. в get нельзя иметь строку такой длины, как размер кода у тебя.
Не знаю, у тебя не открывается?
А вот так красиво будет в будущем.
Смотреть в лисе, если что, в консоль.
Из плюшек -- возможность отменить присваивание (валидация), возможность сделать один универсальный обработчик хоть для всех инстансов (потому что обработчик получает всю инфу), минимальное потребление памяти.
В общем, прокси классная штука)
@trikadin, это конечно круто, но код по-моему нафига не читаем. Используй нормальное ооп, раз боженька (мозилла и ко) в ES6 его дал =)
А что не читаемо-то? О_о
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@trikadin я с офф сайта и собирал, а не отдельно.
Замыкание внутри декоратора нужно что бы ссылка на property всегда относилась к нужному декоратору. Если замыкание убрать, то геттер\сеттер будет обращаться к самой последней декларации обсервабла (я предполагаю, т.к. уже по привычке обрамляю такое в замыкания), а так я просто сохраняю эту ссылку внутри этого замыкания.
Я проверял, но общую работоспособность, а не конкретно этот пример с AuthController. Попробую запилить более приближённый к реальности и выложить куда-нибудь на jsbin.