Coder Social home page Coder Social logo

tnhu / jsface Goto Github PK

View Code? Open in Web Editor NEW
301.0 301.0 46.0 268 KB

Small, fast, elegant, powerful, and cross platform JavaScript OOP library. Support main(), singleton, super call, private, mixins, plugins, AOP and more.

License: MIT License

JavaScript 95.58% HTML 0.53% CSS 3.89%

jsface's People

Contributors

dannyfritz avatar fbudassi avatar peterdavehello avatar tnhu avatar zikicm avatar

Stargazers

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

Watchers

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

jsface's Issues

$statics do not work

$statics do not work in 2.4.0 and 2.4.1 on Google Chrome 42.0.2311.135.

All static methods and properties are undefined on derived objects

Code:

"use strict"; // Activates ECMA JavaScript 5 strict mode

    var Person = Class({
          $statics: {
            MIN_AGE:   1,
            MAX_AGE: 150,

            isValidAge: function(age) {
              return age >= this.MIN_AGE && age <= this.MAX_AGE;
            }
          },

          constructor: function(name, age) {
            this.name = name;
            this.age  = age;
          }
        });

        var person = new Person("Rika", 20);

        Person.MIN_AGE === person.MIN_AGE;               // person.MIN_AGE == undefined
        Person.MAX_AGE === person.MAX_AGE;               // person.MAX_AGE== undefined
        Person.isValidAge(0);                            // false 
        person.isValidAge(person.age);                   // person.isValidAge== undefined.

Error using EventEmitter api

I am learning jsface, and have written a test class to debug the structure of how I want to write my classes before I code them full blown. Everything works great, unless I try to add EventEmitters to the object. I get the following error

f.updateConfig("new config");
^
TypeError: Object [object Object] has no method 'updateConfig'

By event code is as follows:

var jsface = require("jsface"),
    Class = jsface.Class,
    extend = jsface.extend,
    b = require("bonescript"),
    util = require("util"),
    EventEmitter = require("events").EventEmitter;


var face = Class({

    constructor: function(opts, callback) {

      console.log("object created - " + opts);

      this.name = opts;

      //callback(null);

    },

    updateConfig: function(opts, callback) {

      console.log("config updated - " + opts);

      //callback(null);

    },

    setPower: function(power, callback) {

      console.log("set power - " + power);

      //callback(null);

    },

    setState: function(state, callback) {

      console.log("state set - " + state);

      //callback(null);
    },

    getData: function(callback) {

      console.log("data requested");

      callback(null, "data object");

    },

    getConfig: function(callback) {

      console.log("config requested");

      callback(null, "config object");

    },


    $statics: {

        actions: {

            subscribe: function() {

                console.log("subscribe called");

            },

            setState: function() {

                console.log("setState action called");

            },

            setPower: function() {

                console.log("setPower action called");

            },

            updateConfig: function() {

                console.log("updateConfig action called");

            },

            getConfig: function() {

                console.log("getConfig action called");

            }

        }

    }

});

module.exports = face;

//util.inherits(face, EventEmitter);

If I comment out the util.inherits line (as shown), I can access all of the class methods and everything works as expected (just no eventemitters). I have used this eventemitter api on non jsFace objects and it works well. Any ideas? Any alternatives to the EventEmitter?

Thanks.

Should be able to call singleton parent function

It should allow the parent functions to be called. It's useful when creating static helpers, are a just a bunch of utility functions, that you may alter, and still reuse the code from the parent singleton.

Introduce $class

Please, introduce $class field in each instance created. Using it the example provided:

var Student = Class(Person, {
constructor: function(id, name, age) {
this.id = id;
Student.$super.call(this, name, age); // Invoke parent's constructor
}
})

may be written as:

var api = {
constructor: function(id, name, age) {
this.id = id;
this.$class.$super.call(this, name, age); // Invoke parent's constructor
}
}

var Student = Class(Person, api)

This allows to use API mixins when the real class name is not known.

issue Mixin with instance and Mixin with native classes

hello Tannhu

i have tested the new files from git, and regarding the issue of ie7 and ie8 the page of unit tests displays no errors. my congrats.

thank for your work fixing the issue. once again my congrats for such a helpful library.

i have a file with your implementations of the api, the examples from the github and i have 2 issues

in all browsers

Mixin with instance:

var person = new Person("Rika", 20);

extend(person, Options);

console.log(person);

/* - inspecting in console
age 20
name "Rika"
$super function()
toString function()
*/

person.setOptions({ foo: true });

gives this error:

person.setOptions is not a function
person.setOptions({ foo: true });

it appears that extends is not working, since it has no prop from the options class

another issue but only in ie7, ie8, works in ie9, ff, chrome, safari

regarding

Mixin with native classes:

extend(Array.prototype, {
trim: function() {
return this.replace(/^\s+|\s+$/g, "");
}
});

" Hello World ".trim(); // "Hello World"

in ie7 and ie8

SCRIPT438: Object doesn't support property or method 'trim'

thank you very much

$ready works incorrectly

var App = Class({
    $ready: function(clazz, api, parent) {
      var fromSubClass = (this !== clazz);

      console.log(this !== clazz);

      if (fromSubClass) {
        api.main.call(clazz);
      }
    }
  });

var Foo = Class(App, {
   constructor: function(foo) { this.foo = foo; },
   main: function() {
      console.log(new Foo("heloo").foo);
   }
});

main is not executed in App's context.

issue unit tests and mixin native classes

hello tahhnhu

first of all my congrats for such a helper in creating something like jsface, a very lightweight oop library,i have already played with your library creating classes, subclasses, extending and augmenting, and using the super call.

will use definitely your library organizing both my client side scripts as well node scripts. so far only played in the client side with your library, cant wait to do the same in node. a oop library to work in both client side and in node, that is great.

when digging more in the examples of the api, i came across this example

extend(Array.prototype, {
trim: function() {
return this.replace(/^\s+|\s+$/g, "");
}
});

" Hello World ".trim(); // "Hello World"

works in ff, chrome, safari, ie9, but does not work in ie8, ie7 and probably ie6 as well

also when debugging, tested the units test page, the page does not display correctly in ie8 and ie7,
in the file /test/tests/core.js

there are some extra commas in the end of the object declaration

line 632 and line 598, extra commas

after fixing this , the page of unit tests display correctly, but reports errors in some unit tests in ie7 and ie8

issues:

unit test 5 - each returned value over a string (1, 0, 1) - invalid each returned value over a string -

unit test 11 - Check type with jsface.isMap on iframe (1, 0, 1) - 1 - Died on test #1: Object doesn't support this action - { "message": "Object doesn't support this action", "description": "Object doesn't support this action", "number": -2146827843, "name": "TypeError" }

unit test 13 - Check type with jsface.isArray on iframe (1, 0, 1) - 1 - Died on test #1: Object doesn't support this action - { "message": "Object doesn't support this action", "description": "Object doesn't support this action", "number": -2146827843, "name": "TypeError" }

unit test 15 - Check type with jsface.isFunction on iframe (1, 0, 1) - 1 - Died on test #1: Object doesn't support this action - { "message": "Object doesn't support this action", "description": "Object doesn't support this action", "number": -2146827843, "name": "TypeError" }

once again congrats for your work developing this library, it looks very promissing.

cheers

Undefined is not an object | Exporting a Node.js Module

I have a node module (Output.js) that I wrote with jsface as follows:

module.exports = Output;

var Output = Class({

code, etc...

})

In the app.js I use is as follows:

var Output = require("./Output");

var output = new Output(config);

When I run app.js I get the following error:

/var/lib/brewbone/bb_hwc/test_output.js:23
var output = new Output(config);
^
TypeError: undefined is not a function
at Object. (/var/lib/brewbone/bb_hwc/test_output.js:23:14)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:902:3

As I am a noob, I assume I have done something stupid, but for the life of me I cannot pinpoint it. Any suggestions?

Introduce Class.create() function

Well known, that new operator doesn't allow you to invoke it as Function.apply(this, arguments). To create instances in places where the actual number of arguments is not known, please, introduce Class.create() function. It may be used like this:

var Person = Class(Human, { ... })

function() { //<-- factory method
return Person.create.apply(Person, arguments)
}

or simply like this:

function() {
return Person.create(arguments)
}

or directly instead of new operator (as a 'statis' constructor):

var p = Person.create(id, name, ...)

Uncaught ReferenceError: extend is not defined

I get this error when I try this example:

var Student = Class(Person, {
constructor: function(id, name, age) {
});

extend(Student, [ Options, Events ]);

I've tried both referencing jsface and include it in the script

instanceof does not work for jsface

Hi, jsface is very nice given its speed and simplicity. I only found one issue that instanceof is broken for classes created by jsface. Besides of fixing instanceof, I have one wish to have instanceof also works for mixins, which acts as interfaces. Thanks.

requirejs + jsface problem

Hi, I'm trying to combine requirejs with jsface and i have a strange behavior.
Consider this simple project example layout:
+app/
+core/
Person.js
Student.js

I have created two classes declared in two seperate modules defined with requirejs:
Person.js:

  define(["jsface"], function() {
    Class = jsface.Class, extend = jsface.extend;

    var Person = Class(
             {constructor : function(name, age) {
            this.name = name;
            this.age = age;
        },
});return Person;};

Studen.js:

  define(["jsface","Person"], function(Person) {
    Class = jsface.Class, extend = jsface.extend;

    var Student= Class([Person],
             {constructor : function(id,name, age) {
            this.id=id;
                        Student.$super.call(this,name,age);
        },
});return Student;};

when i use Student class constructor it fails on: Student.$super.call(this,name,age); the error thrown is "$super" is not a function.
It works well if i move the Person class declaration in the same requirejs module (inside the define function of Student.js...).
It would be nice to know if this is a normal behavior or there is a jsface problem such as requirejs incompatibility.

Thanks in advance.

Luigi

benchmarks not run!

Testing in Chrome 26.0.1410.64 on Windows Server 2008 R2 / 7

ERROR
ReferenceError: jsface is not defined.

ReferenceError: my is not defined.

ReferenceError: JRClass is not defined.

ReferenceError: klass is not defined.

ReferenceError: Classy is not defined.

ReferenceError: PTClass is not defined.

Documentation of $superp

What is $superp? What does it do? Unfortunately I am not able to find any documentation about $superp.

Super's constructor not getting called if sub class not defining constructor

When no constructor defined, an empty function is created instead, which however does not call super constructor. Expected behavior is if sub class has no constructor it automatically calls super class one.

Suggested fix:

// construct constructor
clazz  = singleton ? {} : (constructor ? (overload ? overload("constructor", constructor) : constructor) : 
  (isClass(parent) ? function(){ parent.apply(this, arguments); } : function(){}));

A better way may be using the p found in later code, which require rearrange the code a little bit

Inherit from javascript function

Hi! I'm using jsface for the new objects of my project, but I have a lot of "legacy objects", like:

var Robot = function() {

    this.getRotation = function() { return 0; }

};

I'm trying to create a child of Robot using jsface, like:

var RobotChild = Class(Robot, function() {
    return {
    };
});

But, when I do:

var robot = new RobotChild();

I get an empty instance.

Regards

Parent class constructor evaluated when defining child class

Hello,

Thank you for writing jsface, I think it is a powerful OOP library for JS.

I came across the following issue that occurs in 2.3. but not in 2.2.

In the following simplified code a child class C is defined based on a parent class P.
Defining C results in the constructor of P to be called, see the 'No Name!!' output.

Calling the constructor of parent P when defining child class C is unwanted behaviour in my opinion.
A fix would be awesome!

var Class = require('jsface').Class
var P = Class({
    constructor : function(name) {
        if (!name) {
            console.error('No Name!!');
        } else {
            console.info('OK');
        }
    }
});

//We define child class C here based on parent class P, which results in 
// the constructor of P to be called
var C = Class(P, {
    constructor : function() {
        C.$super.call(this, "TEST");
    }
});

//CONSOLE OUTPUT:
No Name!!

var c = new C()

//CONSOLE OUTPUT:
OK

Cannot call a class as a function

When i try to extend ES6 class (transpiled to ES5 with babel) as a parent class and I call MyJSFaceCLass.$super.call(this);

I get an error with pointing line to $super.call as mentioned above

Cannot call a class as a function

Was anyone able to migrate from jsface to ES6 successfully? As far as I can tell, I'll need to fork jsface to use new to construct parent object and then extend it, or find a non-standard babel transpiler for transforming classes into pure functions without checking new keyword generated object instance.

Btw. Is this project dead?

how to call $superp without a variable assigned?

suppose I have two classes (in different files, in Node):

factory('Core', {
  /* my stuff */
  mystuff: function(){
    /*do*/
  }
});

now in a second file I do:

factory('MyClass', 'Core', {
  newstuff: function(){
    this.$superp.mystuff(); // this is {} and has no $superp
  }
});

I want the user to drop the need to use variables, and define a class without having to assign it, because I'm using a repository pattern, when factory is called, a new class is instantiated inside a private repository object automatically. factory is merely a wrapper:

global.factory = (function(){
   var repository = {};
   return function(name, obj, opt){
     if (_.isString(obj) && obj in repository) {
       return repository[name] = jsface.Class(repository[obj], opt || {});
     } else if (_.isUndefined(opt)) {
       return repository[name] = jsface.Class(obj);
     } else {
       return repository[name] = jsface.Class(obj, opt);
     }
   }
})();

How can I go around this? How can I make it so the "this" points to the current class?

Super's constructor not getting called if sub class not defining constructor (yes, again).

Just reopening this issue: #13

Actually it's a first OOP model I ever seen, which behaves this way. In most cases you expect parent's constructor to be called. If you don't need parent's class constructor to be called from child class, you could define constructor in child class without a $super call, right?

Nope. Not in this library. You have to create an empty constructors, containing only super's call here.

noConflict does not solve all conflicts

Hi buddy,
this is not enough:

    oldClass          = context.Class;                                         // save current Class namespace
    context.Class     = Class;                                                 // bind Class and jsface to global scope
    context.jsface    = jsface;
    jsface.noConflict = function() { context.Class = oldClass; };              // no conflict

noConflict "pattern" should allow to preserve global context from pollution completely, you'll need to backup and return jsface too:

    oldClass          = context.Class;                                       // save current Class namespace
    context.Class     = Class;                                                 // bind Class and jsface to global scope
    var oldJsface     = context.jsface;
    context.jsface    = jsface;
    jsface.noConflict = function() { 
       context.Class = oldClass;
       context.jsface = oldJsface;  
       return jsface; 
    };              // no conflict

Now people can use noConflict like this:

var Class = jsface.noConflict().Class;

If you review this comment I can make a PR for you.

Nested objects extending

in jsface.extend-method nested objects instead of extending just replace each other.
Example

var Man = Class({
    config: {
        prefix: 'Mr',
        name: '',
        eyes: 'green',
        hair: 'blonde',
        rightHanded: true
    },
    constructor: function (name) {
        this.config.name = name;
    },

    echo: function () {
        console.log(JSON.stringify(this.config));
    }
});

var Woman = Class(Man, {
    config: {
        prefix: 'Ms',
        eyes: 'blue'
    }
});
var jack = new Man("Jack");
jack.echo();
var rika = new Woman("Rika");
rika.echo();

and as a result we've got
{"prefix":"Mr","name":"Jack","eyes":"green","hair":"blonde","rightHanded":true}
{"prefix":"Ms","eyes":"blue","name":"Rika"}
(name presents because of contructor)

In my opinion its incorrect behavior, all properties must inherit instead of whole object replacing, but only in case of simple objects (not for classes).

typo in line 60 $superb?

On line 60 of jsface.js, the ignored key $superb is correct? isn't it supposed to be $superp?

Maximum call stack size exceeded when C extends B and B extends A

var Class = require('jsface').Class;

var A = Class(function() {
    return {
        constructor: function() {
            console.log('A');
        }
    };
});

var B = Class(A, function() {
    return {
        constructor: function() {
            this.$class.$super.call(this);

            console.log('B');
        }
    };
});

var C = Class(B, function() {
    return {
        constructor: function() {
            this.$class.$super.call(this);

            console.log('C');
        }
    };
});

new A; // OK
console.log();
new B; // OK
console.log();
new C; // throws RangeError: Maximum call stack size exceeded

getters & inheritance don't work (gets evaluated while inheriting)

Consider the following code:


// define a class with a getter
var test1 = Class({

    constructor: function(socket)
    {
        this._should_exist = {yep: true};
    },

    // this getter will mess things up...
    should_exist: {
        get: function() {
            return this._should_exist.yep;
        }
    },
});

// then inherit from it.
// this part will evaluate the 'should_exist' getter and will cause exception, since _should_exist is not yet defined.
var test2 = Class(test1, {

});

The code above will invoke exception: TypeError: Cannot read property 'yep' of undefined. The reason for that, I assume, is because probably somewhere inside jsface tries to copy the prototype attribute should_exist, but instead of copying the definition it tries to evaluate it to return the value.

I didn't look too deep into it though.

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.