JS is a pretty good language, but it can be better.
This library does not export anything, but modifies build-in APIs.
As a build-in APIs modifier, this module should be imported at the first. To be used with other build-in APIs modifiers is not recommanded.
To use full BetterJS, just import the index.js:
import 'https://better-js.fenz.land/index.js';
const anchor= '<a href="https://better-js.fenz.land/"></a>';
const href= anchor.matchGroup( /href="([^"]*)"/, 1, );
Or you can only use specific feature like below.
import 'https://better-js.fenz.land/src/promisive.js';
await timeout( 250, );
There are some breaking changes that may trouble you, you can use the breaking-free version.
import 'https://better-js.fenz.land/breaking-free.js';
const caches= new Map();
const data= caches.getOrSet( 'key', ()=> fetch( 'key', ), );
Some parts of BetterJS may depend on others. So when you import one feature, another feature may available too. But a breaking-free feature will never depend on a breaking feature.
- SyncPromise
- throws and tries
- global then, promisive timeout, nextFrame and window onload
- lists extend array (breaking)
- accessible AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, Generator and AsyncGenerator
- fix Generator and AsyncGenerator
- better types
- better instanceof (breaking)
- Object.isObject
- Object.isPrimitive
- Object.isPureObject
- Object.equal
- Object.areSame
- Object.deeplyGet and Object.deeplySet
- Object.deeplyAssign
- Object.haveOwnProperty, Object.bePrototypeOf, Object.propertyBeEnumerable
- Object.map
- Object.get and Object.set
- better frozen (breaking)
-
better forEach (breaking)
-
better reduce (breaking)
-
better entries, keys and values (breaking)
- convert between maps and objects
- better modifications (breaking)
- better entries, keys and values (breaking)
- getOrSet
- put
- pop
- map
- flatMap
- reduce
- sequentially async iterators
- mapAndFilter
- better addEventListener and removeEventListener (breaking)
- removeEventListenersByType and removeAllEventListeners
- pipeline operator hack
- bind syntax hack
- Function.pipe and Function.compose
- curry and yrruc
- detach methods from prototypes
- toMethod
- prepare and postpare
- through and awaitThrough
- Function.prototype.await
- Function.prototype.valve
- Function.prototype.debounce
- Function.prototype.throttle
- noop
- run
- if
There are three paradigms in the JavaScript world, when a function has a main parameter and some of other parameters or options.
The traditional JavaScript paradigm (OOP) put the main parameter as the this
context;
another widely used paradigm is put the main parameter at the first;
the last paradigm that from other FP languages is put the main parameter at the last of parameter list.
We provide various way to make them work together.
Expect curry
, we also support yrruc
for the first parameter paradigm;
A group methods of detach
to help you convert a method with this
into a functio;
And toMethod
let you convert functions into methods.
There are dozens of Functional Programming (FP) libraries. They often leave standard methods away, and make functions themselves. However, BetterJS only do the basic work and fully reuse then standard methods on the prototypes to make it minimal.
Here is the code with a typical FP library. Obviously, they implement map
, join
, slice
repeatedly.
import { pipe, map, join, slice, } from 'https://some-url.js';
pipe(
map( x=> String (x*2), ),
join( '~', ),
slice( 1, ),
)( [ 0, 1, 2, ], );
Here is the code with BetterJS:
import 'https://better-js.fenz.land/fp.js';
const map= Array.prototype.map.detachCurry();
const join= String.prototype.join.detachCurry();
const slice= String.prototype.slice.detachCurry();
// before pipe operator coming
[ 0, 1, 2, ]['|>'](
map( x=> String (x*2), ),
join( '~', ),
slice( 1, ),
);
// tomorrow
[ 0, 1, 2, ]
|> map( x=> String (x*2), )
|> join( '~', )
|> slice( 1, )
;
As we see, functions map
, join
, slice
are detached from standard prototypes. It makes the library minimal.
Benefit from taking the way of build-in APIs modifying, we can provide a '|>' method on all basic prototypes,
so need not to wait for the pipe operator coming. And it's easy to switch to |> syntax tomorrow.
The regular way to make JavaScript better is to make proposals to the TC39. But it's slow and conservative. There is another way, which is token by Prototype.js and JQuery, to build a better environment with a library, to make examples for the wold. Maybe the standard will absorb your ideas (and often make it better), like querySelector from JQuery and a lot of prototype methods form Prototype.js.
You may think that BetterJS is just another Prototype.js. That's true, we take similar way and do similar things. But BetterJS is the more modern one, and only add feature in standard compatible way. When standard update in tomorrow, we can follow up. We also make breaking changes, but in a sustainable way too. The main version will keep these changes tomorrow.
We are not always follow the standard, but make changes in main version.
Because even standard makes bad designs or mistakes, and they often unable to fix them, like typeof null === 'object'
.
If we can make it better beyond the standard can do, why not?
Historical burdens will not exist in every project. We have main version for brand new modern projects, and breaking-free version for historical projects. What's more, you can pick out features you like, and make a DIY version. Even if you just read the code and get some ideas, our works are worthful.
Let's make JavaScript better, let's make the world better.