Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 952083
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T23:50:08+00:00 2026-05-15T23:50:08+00:00

Background I’ve been using the C preprocessor to manage and compile semi-large javascript projects

  • 0

Background

I’ve been using the C preprocessor to manage and “compile” semi-large javascript projects with multiple files and build targets. This gives full access to C preprocessor directives like #include, #define, #ifdef, etc. from within javascript. Here’s a sample build script so you can test the example code:

#!/bin/bash
export OPTS="-DDEBUG_MODE=1 -Isrc"
for FILE in `find src/ | egrep '\.js?$'`
do
  echo "Processing $FILE"
  cat $FILE  \
  | sed 's/^\s*\/\/#/#/'  \
  | cpp $OPTS  \
  | sed 's/^[#:<].*// ; /^$/d'  \
  > build/`basename $FILE`;
done

Make a src and a build directory, and put the .js files in src.


Convenience Macros

Originally, I just wanted the preprocessor stuff for #include and maybe a few #ifdefs, but I got to thinking, wouldn’t it be nice to have some convenience macros too? Experimentation ensued.

#define EACH(o,k)     for (var k in o) if (o.hasOwnProperty(k))

Cool, so now I can write something like this:

EACH (location, prop) {
  console.log(prop + " : " location[prop]);
}

And it will expand to:

for (var prop in location) if (location.hasOwnProperty(prop)) {
  console.log(prop + " : " location[prop]);
}

How about foreach?

#define FOREACH(o,k,v)   var k,v; for(k in o) if (v=o[k], o.hasOwnProperty(k))
// ...
FOREACH (location, prop, val) { console.log(prop + " : " + val) }

Notice how we sneak v=o[k] inside the if condition so it doesn’t disturb the curly braces that should follow the invocation of this macro.


Class-like OOP

Let’s start with a NAMESPACE macro and an obscure but useful js pattern…

#define NAMESPACE(ns)    var ns = this.ns = new function()

new function(){ ... } does some neat stuff. It calls an anonymous function as a constructor, so it doesn’t need an extra () at the end to call it, and within it this refers to the object being created by the constructor, in other words, the namespace itself. This also allows us to nest namespaces within namespaces.

Here is my full set of class-like OOP macros:

#define NAMESPACE(ns) var ns=this.ns=new function()

#define CLASS(c)      var c=this;new function()

#define CTOR(c)       (c=c.c=this.constructor=$$ctor).prototype=this;\
                      function $$ctor

#define PUBLIC(fn)    this.fn=fn;function fn
#define PRIVATE(fn)   function fn
#define STATIC(fn)    $$ctor.fn=fn;function fn

As you can see, these macros define many things both in the Variable Object (for convenience) and in this (from necessity). Here’s some example code:

NAMESPACE (Store) {

  CLASS (Cashier) {

    var nextId = 1000;

    this.fullName = "floater";

    CTOR (Cashier) (fullName) {
      if (fullName) this.fullName = fullName;
      this.id = ++nextId;
      this.transactions = 0;
    }

    PUBLIC (sell) (item, customer) {
      this.transactions += 1;
      customer.inventory.push(item);
    }

    STATIC (hire) (count) {
      var newCashiers = [];
      for (var i=count; i--;) {
        newCashiers.push(new Cashier());
      }
      return newCashiers;
    }
  }

  CLASS (Customer) {

    CTOR (Customer) (name) {
      this.name = name;
      this.inventory = [];
      this.transactions = 0;
    }

    PUBLIC (buy) (item, cashier) {
      cashier.sell(this, item);
    }
  }
}

What about EXTENDS?

So this brings me to the question… how can we implement EXTENDS as a macro to wrap the usual “clone the prototype, copy constructor properties” js prototype inheritance? I haven’t found a way to do it outside of requiring the EXTENDS to appear after the class definition, which is silly. This experiment needs EXTENDS or it’s useless. Feel free to change the other macros as long as they give the same results.

Edit – These might come in handy for EXTENDS; listing them here for completeness.

#define EACH(o,k)   for(var k in o)if(o.hasOwnProperty(k))
#define MERGE(d,s)  EACH(s,$$i)d[$$i]=s[$$i]
#define CLONE(o)    (function(){$$C.prototype=o;return new $$C;function $$C(){}}())

Thanks in advance for any help, advice, or lively discussion. 🙂

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T23:50:09+00:00Added an answer on May 15, 2026 at 11:50 pm

    I think I just completed my own challenge. I’ve added a second (optional) argument to the CLASS declaration macro for the superclass of the class being declared.

    My original implementation created a lot of inline junk around the constructor, so I decided to wrap some convenience functions up in a macro helper object to avoid redundancy.

    Here are the current incarnations of my class-like OOP macros:

    // class-like oo
    
    #ifndef BASE
      #define BASE  $$_
    #endif
    
    #define COLLAPSE(code)      code
    
    #define NAMESPACE(ns)       var ns=BASE._ns(this).ns=new function()
    
    #define CLASS(c,__ARGS...)  var c=[BASE._class(this),[__ARGS][0]]; \
                                new function()
    
    #define CTOR(c)             BASE._extend($$_##c,c[1],this); \
                                c=c[0].c=$$_##c; function $$_##c
    
    #define PUBLIC(fn)          BASE._public(this).fn=fn;function fn
    
    #define PRIVATE(fn)         function fn
    
    #define STATIC(fn)          BASE._static(this).fn=fn;function fn
    
    // macro helper object
    
    COLLAPSE(var BASE=new function(){
    
      function Clone(){};
    
      function clone (obj) {
        Clone.prototype=obj; return new Clone;
      };
    
      function merge (sub, sup) { 
        for (var p in sup) if (sup.hasOwnProperty(p)) sub[p]=sup[p]; 
      };
    
      this._extend = function (sub, sup, decl) {
        if (sup) {
          merge(sub, sup);
          sub.prototype=clone(sup.prototype);
          sub.prototype.constructor=sub;
        };
        if (decl) {
          merge(sub.prototype, decl);
          decl._static=sub;
          decl._public=sub.prototype;
        };
      };
    
      this._static=this._ns=this._class=function (obj) {
        return (obj._static || obj); 
      };
    
      this._public=function (obj) {
        return (obj._public || obj); 
      };
    
    })
    

    … here’s a test namespace …

    //#include "macros.js"
    
    NAMESPACE (Store) {
    
      CLASS (Cashier) {
    
        var nextId = 1000;
    
        this.fullName = "floater";
    
        CTOR (Cashier) (fullName) {
          if (fullName) this.fullName = fullName;
          this.id = ++nextId;
          this.transactions = 0;
        }
    
        PUBLIC (sell) (item, customer) {
          this.transactions += 1;
          customer.inventory.push(item);
        }
    
        STATIC (hire) (count) {
          var newCashiers = [];
          for (var i=count; i--;) {
            newCashiers.push(new Cashier());
          }
          return newCashiers;
        }
      }
    
      // Customer extends Cashier, just so we can test inheritance
    
      CLASS (Customer, Cashier) {
    
        CTOR (Customer) (name) {
          this.name = name;
          this.inventory = [];
          this.transactions = 0;
        }
    
        PUBLIC (buy) (item, cashier) {
          cashier.sell(this, item);
        }
    
        CLASS (Cart) {
    
          CTOR (Cart) (customer) {
            this.customer = customer;
            this.items = [];
          }
        }
    
      }
    }
    

    … and here’s the output …

    var $$_=new function(){ function Clone(){}; function clone (obj) { Clone.prototype=obj; return new Clone; }; function merge (sub, sup) { for (var p in sup) if (sup.hasOwnProperty(p)) sub[p]=sup[p]; }; this._extend = function (sub, sup, decl) { if (sup) { merge(sub, sup); sub.prototype=clone(sup.prototype); sub.prototype.constructor=sub; }; if (decl) { merge(sub.prototype, decl); decl._static=sub; decl._public=sub.prototype; }; }; this._static=this._ns=this._class=function (obj) { return (obj._static || obj); }; this._public=function (obj) { return (obj._public || obj); }; }
    var Store=$$_._ns(this).Store=new function() {
      var Cashier=[$$_._class(this),[][0]]; new function() {
        var nextId = 1000;
        this.fullName = "floater";
        $$_._extend($$_Cashier,Cashier[1],this); Cashier=Cashier[0].Cashier=$$_Cashier; function $$_Cashier (fullName) {
          if (fullName) this.fullName = fullName;
          this.id = ++nextId;
          this.transactions = 0;
        }
        $$_._public(this).sell=sell;function sell (item, customer) {
          this.transactions += 1;
          customer.inventory.push(item);
        }
        $$_._static(this).hire=hire;function hire (count) {
          var newCashiers = [];
          for (var i=count; i--;) {
            newCashiers.push(new Cashier());
          }
          return newCashiers;
        }
      }
      var Customer=[$$_._class(this),[Cashier][0]]; new function() {
        $$_._extend($$_Customer,Customer[1],this); Customer=Customer[0].Customer=$$_Customer; function $$_Customer (name) {
          this.name = name;
          this.inventory = [];
          this.transactions = 0;
        }
        $$_._public(this).buy=buy;function buy (item, cashier) {
          cashier.sell(this, item);
        }
        var Cart=[$$_._class(this),[][0]]; new function() {
          $$_._extend($$_Cart,Cart[1],this); Cart=Cart[0].Cart=$$_Cart; function $$_Cart (customer) {
            this.customer = customer;
            this.items = [];
          }
        }
      }
    }
    

    Inheritance, internal classes, and nested namespaces seem to work fine. What do you think, is this a useful approach to class-like OOP and code reuse in js? Let me know if I’ve missed anything.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 499k
  • Answers 500k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer This is not pretty but it works: rm -R $(ls… May 16, 2026 at 12:45 pm
  • Editorial Team
    Editorial Team added an answer Yes. Override the base1 and base2 methods in Derived to… May 16, 2026 at 12:45 pm
  • Editorial Team
    Editorial Team added an answer No, you can't. Unfortunately, UIEvent doesn't expose any public way… May 16, 2026 at 12:45 pm

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Related Questions

Background: At my company we are developing a bunch applications that are using the
Background I am writing and using a very simple CGI-based (Perl) content management tool
Background I work for a large organization which has thousands of MS Access applications
Background: I have a little video playing app with a UI inspired by the
Background: Some time ago, I built a system for recording and categorizing application crashes
Background: I need to reserve an amount of memory below 0xA0000 prior to my
Background I have a massive db for a SharePoint site collection. It is 130GB
Background I am trying to create a copy of a business object I have
Background: Over the next month, I'll be giving three talks about or at least
In order to apply a triggered animation to all ToolTip s in my app,

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.