15
\$\begingroup\$

I have been trying to wrap my head around all the new options in ECMAscript 6 and to do this I tried to develop a simple setup which would allow me to place absolutely positioned <div>s on the page.

main.js:

import {Screen} from './objects/screen';
import {Position} from './objects/position';

var welcomeScreen = new Screen("Hello World");
welcomeScreen.title = "Hello World2";
welcomeScreen.position = new Position(100,100);
//Make sure the following does work if you have any advices, because there is a simple mistake which breaks this:
console.log(welcomeScreen.position.x);

var secondScreen = new Screen("Second screen", new Position(200,200));

objects/baseobject.js:

export class BaseObject{
    on(eventname,func){
        if(typeof this.listeners == "undefined"){
            this.listeners = {};
        }
        if(typeof this.listeners[eventname] == "undefined"){
            this.listeners[eventname] = [];
        }
        this.listeners[eventname].push(func);
        return this;
    }
    trigger(eventname){
        if(this.listeners && this.listeners[eventname]){
            for(let func of this.listeners[eventname]){
                func.call(this);
            }
        }
    }
}

objects/screen.js:

import {BaseObject} from './baseobject';
// private properties:
var pp = {
    position: Symbol(),
    title: Symbol()
};
export class Screen extends BaseObject{
    constructor(title,position = new Position(0,0)){
        this.element = document.createElement("div");
        this.element.classList.add("screen");
        this.title = title;
        this.position = position;
        document.body.appendChild(this.element);
    }
    reposition(){
        this.element.style.left = this.position.x + "px";
        this.element.style.top = this.position.y + "px";
    }
    set position(position){
        var that = this;
        this[pp.position] = position;
        this[pp.position].on("positionchange",function(){
            that.reposition();
        }).trigger("positionchange");
    }
    get position(){
        return this[pp.position];
    }
    set title(value){
        this[pp.title] = value;
        this.element.textContent = value;
    }
    get title(){
        return this[pp.title];
    }
}

objects/position.js:

import {BaseObject} from './baseobject';
// private properties:
var pp = {
    x: Symbol(),
    y: Symbol()
};
export class Position extends BaseObject{
    constructor(x,y){
        this[pp.x]=x;
        this[pp.y]=y;
    }
    set x(value){
        this[pp.x]=x;
        super.trigger("positionchange");
    }
    get x(){
        return this[pp.x];
    }
    set y(value){
        this[pp.y]=y;
        super.trigger("positionchange");
    }
    get y(){
        return this[pp.y];
    }
}

You can transpile ES6 to ES3 (I think it is 3) using (Google) Traceur.

Points of interest:

  • Are there nice ES6 language features I am forgetting?
  • Is there a nicer way to handle the 'set triggers' (-> private property construction)?
  • Should I be using modules? Combine classes into the same files? etc.
\$\endgroup\$
11
  • \$\begingroup\$ Traceur does not support private in class bodies.. github.com/google/traceur-compiler/issues/57 That's a bit of a let down. \$\endgroup\$
    – konijn
    Commented Mar 5, 2014 at 16:26
  • \$\begingroup\$ Have been reading the spec now for the last half hour and for the life of me, I can't figure out how private properties are 'supposed' to work (regardless of Traceur). \$\endgroup\$ Commented Mar 5, 2014 at 18:38
  • \$\begingroup\$ I looked at wiki.ecmascript.org/doku.php?id=harmony:classes#class_body -> check out the constructor. \$\endgroup\$
    – konijn
    Commented Mar 5, 2014 at 18:55
  • \$\begingroup\$ That one is old and superseded by wiki.ecmascript.org/… \$\endgroup\$ Commented Mar 5, 2014 at 19:01
  • \$\begingroup\$ And yeah, I would have loved it if they could have agreed on that one. I thought you were talking about the new Name() stuff which I can't figure out. \$\endgroup\$ Commented Mar 5, 2014 at 19:02

2 Answers 2

13
\$\begingroup\$

Most interesting,

  • In BaseObject, you should really have a constructor that builds this.listeners, it would make your code much cleaner afterwards
  • I am not sure why your listeners are not private in BaseObject ?
  • I am not sure what is more important to you, learn EC6 or position divs efficiently, if the latter is more important, than this code is massive overkill ;)

If you want to avoid having a constructor for BaseObject, then I would re-write on like this:

on(eventname,func){
    this.listeners = this.listeners || [];
    this.listeners[eventname] = this.listeners[eventname] || [];
    this.listeners[eventname].push(func);
    return this;
}
\$\endgroup\$
2
  • \$\begingroup\$ To point 1 I did this because this way a user doesn't need to call the super constructor on each and every object he constructs. To point 2, you are absolutely right, I forgot entirely. And lastly to point 3: It is to learn EC6 whilst making a mobile app framework slowly (this was just me trying to figure out the setup). \$\endgroup\$ Commented Mar 5, 2014 at 18:29
  • \$\begingroup\$ Great suggestion btw@on :D \$\endgroup\$ Commented Mar 5, 2014 at 19:44
8
\$\begingroup\$

So, going to 'answer' my own question here with a nice thing I discovered since then. Might expand my answer if I discover more stuff.

In ECMAscript 6 rather than

var that = this;
something.on("positionchange",function(){
     that.reposition();
});

You can do

something.on("positionchange",() => {
     this.reposition();
});

As the this scope doesn't change.

\$\endgroup\$
1
  • \$\begingroup\$ It's exciting though? Already with the latest additions I have stopped using typical javascript libraries for most my projects and with ES6 I can get rid of a couple I occasionally use again :D \$\endgroup\$ Commented Mar 6, 2014 at 23:15

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.