How can I write a closure function in getter in ES6 ? - ecmascript-6

In ES5, I can write it like this:
MyClass.prototype.value = (function() {
var privateVariable = 0;
return function() {
return ++privateVariable;
};
})();
But in ES6, how can I do it ?
class MyClass {
get value() {
// return ??
}
}

A direct counterpart, which is not idiomatic to ES6 classes:
class MyClass {}
MyClass.prototype.value = (() => {
let privateVariable = 0;
return function() {
return ++privateVariable;
};
})();
There are no practical reasons to make privateVariable completely unavailable from the outer scope, especially since it doesn't play well with ES6 classes. This cannot be considered a proper encapsulation because privateVariable isn't available for reflection; it cannot act as protected member as well.
There can be private member that stores a value:
class MyClass {
constructor() {
this._value = 0;
}
value() {
return ++this._value;
}
}
It could be a symbol but this doesn't make class design more secure, just introduces additional complications when a class is inherited in another module:
// should be carried around everywhere to make the class extendable
export const VALUE = Symbol('value');
class MyClass {
constructor() {
this[VALUE] = 0;
}
value() {
return ++this[VALUE];
}
}
Note that get value() {} is not same thing as value() {}.
One of TypeScript (which is a superset of ECMAScript) benefits is the encapsulation that is enforced at compilation time.

The equivalent to the ES5
function MyClass() {}
var privateVariable = 0;
MyClass.prototype = {
get value() {
return ++privateVariable;
}
};
in ES6 class syntax would be
let privateVariable = 0;
class MyClass {
get value() {
return ++privateVariable;
}
}
Whether you put all that in an IEFE or module or whatnot for local scope doesn't matter, it's the same.

Related

How do I access a method that's in another method that's in a class in ECMA6Script?

How do I declare the method getYellowCycle() so that the variable game can access it? getYellowCycle is a method that's in another method called newGame(), that's in a class called model.game.
Here is where the method should be called.
let game = model.Game.newGame();
expect(game.getYellowCycle().getX()).to.equal(50);
Here is the class model.game
model.Game = class {
newGame() {
}
};
getYellowCycle() should go in newGame()
Something like this:
const model = {};
model.Game = class {
newGame() {
return {
getYellowCycle() {
return {
getX() {
console.log("In getX");
return 50;
}
};
}
};
}
};
const game = (new model.Game()).newGame();
console.log(game.getYellowCycle().getX());

How can I get a list of all properties in a mixin in Polmyer 2.x?

I have a mixin and a class that uses it, but within the mixin (or the class itself), I can't seem to get a list of all properties. this.config is undefined, and this.constructor.config only gives me the list of properties in the current class (not those in the mixin itself).
See below for a more detailed example.
const myMixin = subclass => class extends subclass {
static get config() {
return {
properties: {
mixInVariable: {
type: String,
}
}
}
}
constructor() {
super();
console.log(this.constructor.config.properties);
}
}
class ContainerGrid extends myMixin(Polymer.Element) {
static get is() { return 'container-grid' }
static get config() {
// properties, observers meta data
return {
properties: {
something: {
type: String
}
}
};
}
}
customElements.define(ContainerGrid.is, ContainerGrid);
In the console, I only see the variable something. How can I get a list of all properties (e.g. mixInVariable and something)?
From the constructor, use super.constructor.config.properties to access the inherited properties.
class XFoo extends MyMixin(Polymer.Element) {
...
constructor() {
super();
console.log('constructor(): ', super.constructor.config.properties);
}
}
From get properties(), use super.config.properties.
class XFoo extends MyMixin(Polymer.Element) {
...
static get properties() {
console.log('get properties(): ', super.config.properties);
}
}
codepen

How to use this before super?

I know that this is not allowed before super but I need to do it. I was wondering if there was a legal way to do this in es6?
My code:
class DOMElement {
constructor(aNodeName) {
this.name = aNodeName;
this.create();
}
create() {
let domref = document.createElement(this.name);
document.body.appendChild(domref);
return domref;
}
}
class Button extends DOMElement {
constructor(aLabel) {
this.label = aLabel;
super('button');
}
create() {
let domref = super.create();
domref.textContent = this.label;
}
}
If I don't set this.label before calling super('button') in Button.prototype.create then domref.textContent is set to undefined.
There's no 'legal' way.
It can be be a getter in cases where static property value is supposed to be used by parent class on construction:
get label() {
return 'label';
}
In this case this means that class design is just wrong. There's nothing in parent class that would impose such restriction. Actually, label is only used by child class. It should be:
constructor(aLabel) {
super('button');
this._domref.textContent = alabel;
}
create() {
// if parent class is user-defined, it should be done there
// instead of returning a value, because it doesn't make sense
// to leave an important part of the object without a reference
this._domref = super.create();
}

Attempted to assign to readonly property ECMAScript React Native

I am trying to assign a value to an array declared in my Component. Unfortunately, exception is thrown.
TypeError: Attempted to assign to readonly property
Even if I remove strict mode, still exception is being raised. Can please someone guide me how can I make a variable both readable and writable? Thanks..!
Code:
class RootView extends Component {
cachedData : []; //declared array here
//trying to assign dictionary in some function
someFunction(results) {
this.cachedData[this.state.searchString.length - 1] = results;
//exception raised here
}
}
Your syntax is incorrect. Add it to a constructor.
class RootView extends Component {
constructor() {
super();
this.cachedData = [];
}
someFunction(results) {
this.cachedData[this.state.searchString.length - 1] = results;
}
}
If your transpiler supports experimental code (stage 0), you can use the following:
class RootView extends Component {
cachedData = [];
someFunction(results) {
this.cachedData[this.state.searchString.length - 1] = results;
}
}

How to pass a reference to class into another class

The question is a bit silly. I am trying to implement a skill updating system. So to explain.
There is a class
class AppInfo
{
public static var power:int = 10;
public static var speed:int = 20;
}
and class SmartButton which should take a reference to one of the static variables e.g. power in a constructor and increment it on the given value.
e.g.
class SmartButton
{
public function onClick(skillReference:int = <AppInfo.power>, incrementVAlue:int = 10)
{
skillReference += incrementVAlue
}
}
I want this code to update the value of the power in AppInfo class. But this doesn't happen... I assume because the skill was passed as value not as reference...
Can you suggest a way of solving the task?
Thanks
Your assumption is correct, ints are passed by value rather than reference. One direct approach would be to encapsulate power into a reference type (a class) rather than a value type:
class Skill {
public var value:int;
public function Skill(val:int) {
this.value = val;
}
}
class AppInfo
{
public static var power:Skill = new Skill(10);
public static var speed:Skill = new Skill(20);
}
Then passing power should pass it as a reference to the instance. Though you would have to change your implemenation a bit to use skillReference.value instead.
Aside from that, I think there are a couple of ways to abstract what you want out. One way would be use an interface and leverage some dependency injection.
interface ISkills
{
function get power():int;
function set power(val:int):void;
}
class AppInfo implements ISkills
{
private static _power:int = 0;
public function get power():int { return _power; }
public function set power(val:int):void { _power = val; }
}
class SmartButton
{
public function onClick(skills:int = ISkills, skill:String = "power", incrementVAlue:int = 10)
{
skills[skill] += incrementVAlue
}
}
The idea here that you want to decouple your usage from your implementation. In this case SmartButton doesn't need to know how Skills work just how to operate on them. It loses its reference to the static class AppInfo in favor of an injectable instance. There are some advantages to this approach, it makes it easier to test and easier to swap implementations later if you decide that a static class isn't the best implementation idea without having to update a bunch of classes/code. Also, rather than injecting ISkills into the method, you could inject it into the constructor of SmartButton, and keep a private reference to the skill container.
Another approach would be to use a functional approach.
class SmartButton
{
public var defaultWorker:Function = function(val:int):void {
AppInfo.power += val;
}
public function onClick(worker:Function = undefined, incrementValue:int = 10):void
{
if(worker == undefined) worker = defaultWorker;
worker.call(this, incrementValue);
}
}
Again, in this case, rather than tightly coupling your implementation to use the AppInfo class directly, you inject a "worker" for it do the work for you (if the worker is undefined then use the default worker. You can then swap out which property gets changed by changing the closure that gets passed in. For instance if you wanted to change speed instead then you would call:
var smartButton:SmartButton;
smartButton.onClick(function(val:int):void { AppInfo.speed += val});
Not quite as succinct as it could be, but it gets the job done.
The obligatory "elegantly sophisticated" approach using the command pattern:
Interface Command {
function execute():void;
}
Class UpdatePower implements Command {
private var appInfo:AppInfo;
private var delta:int;
public function UpdatePower(appInfo:AppInfo, delta:int) {
this.appInfo = appInfo;
this.delta = delta;
}
public function execute():void {
appInfo.delta += delta;
}
}
Class SmartButton {
var command:Command;
public function SmartButton(command:Command) {
this.command = command;
}
public function onClick(event:Event):void {
command.execute();
}
}
I would probably implement this in a slightly different way.
Maybe something like;
class Properties {
private var _properties:Dictionary = new Dictionary();
public function setValue(key:String, value:int) {
_properties[key] = value;
}
public function getValue(key:String):int {
if( !_properties[key] ) return 0;
else return _properties[key];
}
public function modifyValue(key:String, value:int) {
setValue(key, getValue(key) + value);
}
}
class SmartButton
{
public function onClick(target:Properties, key:String, incrementValue:int = 10) {
target.modifyValue(key, incrementValue);
}
}
Or something along those lines.