v1.2.3
js.componentWelcome to js.component!
js.component is a 4D component comprising 40+ classes with 450+ functions that:
- Brings several of the most popular and powerful JavaScript packages to 4D
- Fills many holes in the 4D language
- Dramatically improves the developer experience
- Reduces method count, lines of code, and coding time
- Provides multiple new ways to debug your code
- Implements key object-oriented techniques that are not widely known in the 4D world
js.component is 100% pure 4D code, 100% preemptive-safe, and 100% guaranteed to make you a more effective, more productive and more happy programmer!
Why js.component?
js.component is not just a loose collection of unrelated utilities; it is an integrated framework that provides you with an entire programming system, from foundational low level utilities borrowed from other languages to world class modules ported from the JavaScript world.
js.component is both broad in scope and deep in functionality. Yet it has minimal impact on your existing projects — there are only ten methods that live in the global namespace! Every function has been carefully designed to provide maximum utility, flexibility, and ease of use.
Installation
NOTE
js.component requires 4D v19 R5 or later.
To install js.component, place it (or an alias/symlink to it) in the Components
folder of your database, as you would any other 4D component.
js.component is not compiled so that you can see (and hopefully learn from!) the source code. If your host application is distributed in compiled form, you can open js.component as a project and compile it according to your preferred settings.
Initialization
It is recommended that you add the following lines early in the On Startup
and On Server Startup
methods (or to methods that are called by them):
// You should call this in the main application process before any other
// processes are started that might use DateTime.
DateTime()
// If you want to use js.component error handling, you MUST do this
// to synchronize error handlers with the host db.
_.setHostOnErrCall(Formula(ON ERR CALL($1)))
// If you don't want to see a debug alert when an uncaught error occurs
// (e.g. when you are running on Server), you should create your own
// uncaught error handler and set it here.
If (Application type=4D Server)
_.setUncaughtErrorHandler(Formula(uncaughtErrorHandler($1)))
End if
Release notes
For a complete list of what has changed in each release, see the release notes.
Documentation conventions
This documentation follows the format and conventions of the new 4D documentation at developer.4d.com, so it should seem familiar. Extensive links have been provided to make navigation easy.
The headers of the documentation (which includes function names) are searchable via the search box in the upper right of the page. On the desktop, pressing /
or s
focuses the search box.
Callables
Throughout this documentation you will see parameters with the type Callable
. A Callable
is any object that has both .call()
and .apply()
properties which are formulas. This is done primarily to allow you to use formulas interchangeably with functors when using js.component. Why use a Functor
instead of a formula?
Functors are objects that can have properties. Thus they can maintain state and determine what
This
refers to when called.The implementation of functors can be arbitrarily complex, whereas formulas are limited to a single line of code.
Interfaces
Some of the classes documented here are interfaces, which represent the shape of classes you will define to provide custom functionality. For example, the MochaReporterDelegate
interface is not actually a class, but rather a description of the functions that a class must implement in order to be used as a delegate for the MochaReporter
class.
Accessing js.component classes
Almost all of js.component’s functionality is provided by classes, along with a very small set of global methods. The publicly accessible classes are available via the .js
namespace. For example, to instantiate an instance of the Error
class, you would use:
$error:=cs.js.Error.new("Something went wrong")
Using js.component
js.component can broadly be split into several categories of functionality.
TIP
The Lodash
class itself contains over 100 functions 🚀 covering a broad range of functionality. It is perhaps the best place to start exploring js.component.
DateTime
DateTime()
DateTime
DateTimeStatic
Errors
DBError
Error
RangeError
ReferenceError
SystemError
SyntaxError
TypeError
i18n
Language
Lodash
Logging
console()
ConsoleTransport
LogFormats
Logger()
Logger
LoggerStatic
Transport
TransportDelegate
Mocha unit testing framework
ChaiBdd
ChaiAssertionError
MochaHtmlReporter
MochaMultiReporter
MochaReporter
MochaReporterDelegate
MochaRunner
MochaSuite
MochaTest
Singletons
instance()
registerSingleton()
unregisterSingleton()
Timing
Utility
js_openMethod()
macro_commentBlock()
Regex
Class structure
The classes in this component use a few key object-oriented design patterns:
- Singleton
- Facade
- Handle/implementation
- Delegate
- Class statics
Singleton
A singleton class is a class that is designed to be global, and thus have one and only one instance. The following classes in js.component are (or are designed to be) singletons:
ErrorHandler
Lodash and its private friend classes
LogFormats
Logger
LoggerStatic
You manage singletons with the methods in the Singletons category.
Facade
A facade class provides a single API to instances of other classes which provide the facade’s functionality. This allows the functionality to be split up into multiple classes, which can be tested and maintained independently, while still providing a single API to the user.
The Lodash
class, for example, is a facade to multiple private classes.
Handle/implementation
A handle/implementation is similar to a facade in that the handle class provides a public API to an instance of the implementation class. Unlike a facade, however, the implementation class is provided by the user. Unlike a delegate, the implementation class provides the functionality of the handle class, rather than just providing a way to customize the behavior of the handle class.
The Functor
class and its corresponding implementation class are an example of handle/implementation.
Delegate
A delegate class is provided by the user and serves to customize or augment a subset of the functionality of the parent class. Delegate classes in this documentation are always interfaces and the class name ends with "Delegate".
MochaReporter
is an example of a class that uses MochaReporterDelegate
as its delegate.
Class statics
In most object oriented languages, there are two types of class methods and properties: instance and static.
TIP
As in many other areas of the language, 4D’s terminology is, shall we say, “unique”: what it calls “methods”, almost every other language calls “functions”, and vice versa.
Instance methods and properties are accessed through individual instances of a class. Static methods and properties are accessed through the class object itself, which makes them global in nature.
4D unfortunately does not natively support static methods or properties. js.component works around this through the following convention:
For any given class
Foo
, a parallel class calledFooStatic
is created which contains “static” functions and properties.A global method (what 4D calls a “method”)
Foo
is created which uses theinstance()
method to return a singleton instance of theFooStatic
class.
To access the (pretend) static functions and properties on the Foo
class, you would use this:
Foo.bar()
$baz:=Foo.baz
I call them “pretend” statics because if 4D supported native class statics, the code would most likely be like this:
cs.Foo.bar()
$baz:=cs.Foo.baz
js.component uses this trick for DateTime
and Logger
.
NOTE
You can add properties and functions to a class object in 4D, but they are ephemeral — they will be lost when any classes’ source is modified and 4D internally rebuilds the cs
class store. This is why js.component uses a parallel “static” class to hold static properties and functions.