Skip to content

Instantly share code, notes, and snippets.

@doasync
Created September 22, 2017 12:01
Show Gist options
  • Select an option

  • Save doasync/74560203b927fc58159a3aba14e0c977 to your computer and use it in GitHub Desktop.

Select an option

Save doasync/74560203b927fc58159a3aba14e0c977 to your computer and use it in GitHub Desktop.
ES6 classes without a class keyword but with class variable

noclass

Here is an example of ES6 classes without a class keyword but with class variables. Looks the same as classes and has the same structure internally.

Example

// class
var Foo = {
  classVariable: true,

  // constructor
  [$constructor](who){
    this.me = who;
    this.species = 'fufel';
  },

  // methods
  identify(){
    return 'I am ' + this.me;
  }
}

// class extends Foo
var Bar = $extends(Foo, {

  // constructor
  [$constructor](who){
    $super(Foo, this, who);
    this.subtype = 'barashek';
  },

  // methods
  speak(){
    console.log('Hello, ' + this.identify());
  },
  bark(num){
    console.log('Woof');
  }
});

Multiple "inheritance"

// class
var Foo = {
  classVariable: true,

  // constructor
  [$constructor](who){
    this.me = who;
    this.species = 'fufel';
  },

  // methods
  identify(){
    return 'I am ' + this.me;
  }
}

var Logger = {
  logEnabled: true,
  log(){
    if(logEnabled){
      console.log('Log saved.');
    } else {
      throw Error('Log disabled');
    }
  },
  startLogging(num){
    this.logEnabled = true;
  },
  stopLogging(num){
    this.logEnabled = false;
  },
}

var Tester = {
  test(){
    if(this.speak){
      console.log('Can speak.');
    }
  }
}

// class extends Foo
var Bar = $extends([Foo, Tester, Logger], {

  // constructor
  [$constructor](who){
    $super(this, who);
    this.subtype = 'barashek';
  },

  // methods
  speak(){
    console.log('Hello, ' + this.identify());
  },
  bark(num){
    console.log('Woof');
  }
});
// Helper
const $constructor = Symbol();
const $extends = (parents, child) => {
if(Array.isArray(parents) && parents.length){
parents.reduce((proto, parent) => {
Object.setPrototypeOf(proto, parent);
return parent;
});
parents = parents[0];
}
return Object.assign(Object.create(parents), child);
}
const $new = (object, ...args) => {
let instance = Object.create(object);
instance[$constructor].call(instance, ...args);
return instance;
}
const $super = (context, ...args) => {
Object.getPrototypeOf(
Object.getPrototypeOf(context)
)[$constructor].call(context, ...args);
}
// class
var Foo = {
classVariable: true,
// constructor
[$constructor](who){
this.me = who;
this.species = 'fufel';
},
// methods
identify(){
return 'I am ' + this.me;
}
}
var Logger = {
logEnabled: true,
log(){
if(logEnabled){
console.log('Log saved.');
} else {
throw Error('Log disabled');
}
},
startLogging(num){
this.logEnabled = true;
},
stopLogging(num){
this.logEnabled = false;
},
}
var Tester = {
test(){
if(this.speak){
console.log('Can speak.');
}
}
}
// class extends Foo
var Bar = $extends([Foo, Tester, Logger], {
// constructor
[$constructor](who){
$super(this, who);
this.subtype = 'barashek';
},
// methods
speak(){
console.log('Hello, ' + this.identify());
},
bark(num){
console.log('Woof');
}
});
var a1 = $new(Foo, 'a1');
var b1 = $new(Bar, 'b1');
console.log(a1, b1);
console.log('b1.classVariable', b1.classVariable);
const $constructor = Symbol();
function $extends(parents, child){
if(Array.isArray(parents) && parents.length){
parents.reduce((proto, parent) => {
Object.setPrototypeOf(proto, parent);
return parent;
});
parents = parents[0];
}
return Object.assign(Object.create(parents), child);
}
function $new(object, ...args){
let instance = Object.create(object);
instance[$constructor].call(instance, ...args);
return instance;
}
function $super(context, ...args){
Object.getPrototypeOf(
Object.getPrototypeOf(context))
[$constructor].call(context, ...args);
}
export {$new, $extends, $constructor, $super};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment