Code Monkey home page Code Monkey logo

jclass's Introduction

jclass

jclass

jclass started as a port of John Resig's lightweight OO inheritance model. However, this implementation is faster as it avoids threefold method wrapping (see this link). In addition, it provides class members, property descriptors, conversion of prototype-based classes and various conveniences.

jclass has no dependencies and works in most import environments: RequireJS (AMD), CommonJS, NodeJs and web browsers.

Note: The current version (1.X.X) is a merge of the node-oo project and the previous version of jclass (0.2.X). For legacy code, see the v0.2.X branch.

Installation

jclass is hosted at npmjs. Install it via:

npm install jclass

Examples

All examples below use NodeJs but the jclass related code would also work in other environments.

Simple Inheritance

var JClass = require("jclass");

var Cat = JClass._extend({

  // constructor
  init: function(color) {
    this.color = color;
  },

  // instance method
  meow: function() {
    console.log("An abstract cat cannot meow!");
  },
  
  // instance method
  getColor: function() {
    return this.color;
  }

});


var GrumpyCat = Cat._extend({

  // constructor
  init: function init() {
    init._super.call(this, "greyish");
  },

  // instance method
  meow: function() {
    console.log("Nah, not in the mood.");
  }

});

var cat = new Cat("black");
cat.meow(); // "An abstract cat cannot meow!"

var grumpy = new GrumpyCat();
grumpy.meow(); // "Nah, not in the mood."
grumpy.getColor(); // "greyish", same as grumpy.color

// instanceof works as expected
console.log(grumpy instanceof GrumpyCat); // true
console.log(grumpy instanceof Cat); // true
console.log(GrumpyCat._extends(Cat)); // true, same as GrumpyCat._superClass == Cat
console.log(GrumpyCat._extends(JClass)); // true
Note

In the GrumpyCat.init constructor method, the super class' constructor is invoked as well via init._super.call. init is the method itself, _super references the super class's method. This is achieved using function declaration. For more info, see this link.

Class members

Class members are accessible via the _members property which is itself a jclass instance. To add class members, add a second paramter to _extend.

var JClass = require("jclass");

var Cat = JClass._extend({
  // instance members

  // constructor
  init: function(color) {
    this.color = color;
  },

  // instance method
  meow: function() {
    console.log("An abstract cat cannot meow!");
  }

}, {
  // class members

  family: "Felidae",

  getFamily: function() {
    return this.family;
  },
  
  reproduce: function(color) {
    // create a new cat ;)
    return new this._class._instanceClass(color);
  }

});

Cat._members.getFamily()); // "Felidae", same as Cat._members.family

Please note that this within class methods references the _members instance itself.

Property Descriptors

All instance and class members given to _extend can also be applied as property descriptors that are passed to Object.defineProperty. There are two approaches.

Descriptors

Define members as objects and add a property descriptor: true. Both, accessor-type and data-type descriptors are supported.

var JClass = require("jclass");

var MyClass = JClass._extend({

  someKey: {
    descriptor: true,
    get: function() {
      return "some value";
    }
  }

});

var myInstance = new MyClass();
console.log(myInstance.someKey); // "some value"
Getter/Setter Syntax

Use getter/setter syntax. This is equivalent to the accessor-type descriptor definition.

var JClass = require("jclass");

var MyClass = JClass._extend({

  set someKey(value) {
    // do sth with "value", e.g.
    this._someKey = value;
  },
  
  get someKey() {
    // do sth to return a value, e.g.
    return this._someKey * 2;
  }

});

var myInstance = new MyClass();
myInstance.someKey = 123;
console.log(myInstance.someKey); // 246
Accessing Super Property Descriptors

When extending a class that implements property descriptors, you cannot access its super definitions the normal way, i.e. via the _super attribute. Instead, you have to do a little trick (based on MyClass above):

var JClass = require("jclass");

var MyClass = ...

var MySubClass = MyClass._extend({
    
    get someKey() {
        var _super = JClass._superDescriptor(this, "someKey");
        // same as
        // var _super = JClass._superDescriptor(this._class, "someKey");
        // same as
        // var _super = JClass._superDescriptor(MySubClass, "someKey");
        // alias for
        // var _super = Object.getOwnPropertyDescriptor(MyClass.prototype, "someKey");
        return _super.get.call(this) * 3;
    }

});


var mySubInstance = new MySubClass();

mySubInstance.someKey = 1;
console.log(mySubInstance.someKey); // 6

Converting Prototyped Classes

You can convert prototype-base classes into jclasses. This approach supports constructor arguments.

// example using nodejs

var JClass       = require("jclass");
var EventEmitter = require("events").EventEmitter;

var Emitter = JClass._convert(EventEmitter);

var emitter = new Emitter();
emitter.on("topic", function() { ... });
emitter.emit("topic", ...);
});

The instance of the (original) prototyped class is stored as _origin in each jclass instance.

API

Classes

Classes have the following attributes:

  • _extend(instanceMembers, classMembers): Derives a new class with instanceMembers and classMembers (example).
  • _extends(JClass): Returns true (false) if JClass is (is not) a super class.
  • _superClass: The super class (not available for the base JClass).
  • _subClasses: An array containing all (directly inheriting) sub classes.
  • _members: A jclass instance holding the class members (example).

Only for the class that holds class members:

  • _instanceClass: The original class holding instance members.

The base JClass has additional attributes that are not propagated to derived classes:

  • _convert(cls, options): Converts a prototype based class cls into a jclass (example).
  • _construct(cls, args): Returns an instance of cls, instantiated with args. This is an apply-like usage for the new operator.
  • _superDescriptor(JClass|instance, prop): Returns the property descriptor prop of the super class. The first argument can be either a jclass or an instance of a jclass.

Instances

All instances have the following attributes:

  • _class: The class of this instance.

Within instance methods, the super method is always referenced as _super. You can access them by making your instance method a named function (example).

Development

Authors

Marcel R. (riga)

jclass's People

Contributors

riga avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

jclass's Issues

Can this be used in Angular?

Hi,
I started off using Resigs version in an angular app which worked/s great.
I then tried bringing in jclass but get lots of errors, with angulars._extend method.
I'm wondering if jclass is overriding angulars own _exclude ?
/Stephen.

private properties cannot be modified within the class

I'm hitting an odd problem where private variables cannot be modified within methods of the class. is it possible I am doing something wrong?

var theClass = jClass.extend({
   init: function() {
      this.__privateProperty = 0;
   },
   increase: function() {
      this.__privateProperty++;
   },
   show: function() {
      return this.__privateProperty;
   }
});

var foo = new theClass();
foo.increase();
foo.show(); //returns 0 instead of 1

I have no idea if I am doing something wrong or not, but if I'm not, then this here bug is a problem.

Collision of private members between multiple instances

See #1 (comment)

var MyClass = jClass.extend({
    init: function() {
        this.__privateProperty = 0;
    },

    increase: function() {
        this.__privateProperty++;
    },

    show: function() {
        return this.__privateProperty;
    }
});

var instA = new MyClass();
var instB = new MyClass();

instA.increase();
instB.show(); //expect 0, returns 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.