Javascript is a very nice language (at least for someone π) but it's still missing some core functionalities...
are you wondering which functionality are missing in the language? well, to remove an element from an array like now looks like this:
someArray.splice(someArray.indexOf(elementYouWantToRemove), 1)
and if you have to remove each occurrence of that element can be even worse:
for (let i = 0; i < someArray.length; i++) {
if (elementYouWantToRemove === someArray[i]) {
someArray.splice(i, 1)
i--
}
}
not sure why javascript doesn't have such a basic functionality, something like this will be great:
someArray.remove(someElement)
well, i have a great news for you! π₯
this and many many other functionalities are available directly into the language throught polyfull
all you need to do to unlock that functionalities is to import it in the index of your project:
import 'polyfull'
β οΈ THIS IS INTENDED TO USE ONLY IN FINAL APPLICATIONS.
if you use this in library, any other applications that use your library will have
polyfull
injected as well.
please DO NOT use this if you are building a library, use this only where you have control of your node interpreter.
also, if you are using some other polyfiller, be sure that there is no overlaps, or something will broke. Thanks!
and you can use a lot of functionalities, here is an example:
import 'polyfull'
// ArrayConstructor
Array.zip([1, 2, 3], ['a', 'b', 'c']) // => [[1, 'a'], [2, 'b'], [3, 'c']]
Array.collapse([1], [2, 3], [4, 5, 6]) // => [1, 2, 3, 4, 5, 6]
Array.intersect([1, 2, 3], [2, 3, 4]) // => [2, 3]
Array.unique([1, 2], [2, 3], [3, 4]) // [1, 2, 3, 4]
// Array
[1, 2, 3].remove(2) // => [1, 3]
[1, 2, 3].removeIndex(2) // => [1, 2]
[1, 2, 3].first() // => 1
[1, 2, 3].last() // => 3
// DateConstructor
Date.current() // => new Date(Date.now())
// Date
new Date(0).addHours(1) // => 1970-01-01T01:00:00.000Z
new Date(0).isBefore(new Date(Date.now())) // => true
new Date(0).isAfter(new Date(Date.now())) // => false
new Date(0).diff(new Date()) // => how many ms passed from 1970? :D
// NumberConstructor
Number.random() // => -789.0123
Number.random(0) // => 789.0123
Number.random(0, 100) // => 89.0123
Number.randomInt(0) // => 42
// Number
7.0.isPrime() // => true
3.0.pow(2) // => 6
40.0.goldenRation() // => [24.72~, 15.28~]
50.0.percentage(20) // => 10
// Promise
await Promise.allProperties({
a: Promise.resolve(1),
b: Promise.resolve(2),
}) // => { a: 1, b: 2 }
await Promise.allPropertiesSettled({
a: Promise.resolve(1),
b: Promise.reject(2)
}) // => {
// a: { status: 'fulfilled', value: 1 },
// b: { status: 'rejected', reason: 2 }
// }
// String
'hello'.reverse() // => "olleh"
'racecar'.isPalindrome() // => true
'0x01'.isNumeric() // => true
'polyfull'.equalsIgnoreCase('POLYFULL') // => true
// And Many Many Others!!
Remember to leave a β if you like it!
Top comments (15)
This isn't polyfilling, it's monkey patching. Polyfills are to add support for features that are in the spec but not yet supported by all environments. Polyfills are considered safe, because all they're doing is improving consistency between the different environments.
Monkey patching, however, is stuff that will almost certainly never be in the spec, but might clash with other things added to the spec later on, or with other rogue libraries that decide to monkey patch stuff, because it's all global.
There is one way and only one way to monkey patch safely: by using unique symbols:
That works fine and won't pollute any global namespaces, because the symbol used to access the new method is only accessible by importing it directly from the library (or by doing something convoluted like
Object.getOwnPropertySymbols(Array.prototype).find(({ description }) => description === 'remove')
, which a consumer of your library wouldn't plausibly do by mistake).As shiny and cool as symbols are, however, in my opinion it's better not to monkey patch at all, and instead to just use plain old functions that take the target array as a parameter. If you want to keep the nice left-to-right syntax you get from method chaining, you can implement the API with higher-order functions and use a pipe function to compose them:
This version also has the added advantage of not mutating the original array.
at this point is bit annoying, but let's give a fair reply:
Polyfilling native object is a common pratice (i don't think i have explain to you, you seems smart enought, but i will do for everyone else reading this post), due to lack of functionality missing in previous version of javascript, an example can be
core-js
.The aim of core-js is to provide compatibility function where are missing.
the aim of
polyfull
is a bit different, and should be handled carefully.first of all, none of ECMAScript specification should be replaced. (and i am doing this at current version ES2021)
second, i have to provide a way to make some version of polyfull incompatible if a new release of EcmaScript have name collision with polyfull. (and this can be done with flags in package.json)
of course you are creating a bit of incompatibility if you are using previous version of polyfull with new version of ecmascript if an incompatibility occurs, or if you have to make porting from an older version to a new one (i am perfectly aware of this).
but i think you can agree with me that some stuff is missing in nodejs, and it's fucking annoying.
If you need functionality to manipulate array and this stuff you can simply install lodash. but my library isn't targeting this advantages.
programmer are lazy, and i am bored of searching over and over to remove an element from array or generate a random number.
This library is just a shortaround to have some basic functionality that aren't builded in js language in two decades.
Also jsDoc annotations like
@deprecated
can be useful to spot where naming collisions occurs.You are free to not use this library, the name and the warning are pretty much representing what this library do and where it can be used. And where should NOT be used.
i gonna use it in some project where i am just to lazy to do something like this:
instead of
furthermore, thanks for any tips and advice! And thanks for the time you spent here :D
I'd just point out that Sugar has been doing this kind of thing for a long while. They've now made the extension functions "opt-in" so it can be used in a library or in a final application. In final applications I have used it in both ways.
Modifying the prototypes of objects is a contentious subject, I have a huge amount of respect for the stuff @lukeshiru writes and creates, but probably in this case fall more on the side of "it's fine if you aren't building a library". The Sugar comments on modes and other content on the site will express the opinions here far better than I can though :)
I see LUKESHIRU got a bit dogmatic here. But someone had to be 1st π Anyway, I don't want to get involved into that discussion. I believe everyone can decide. But I remember SugarJS has nice long article about the risks, how to deal with them and alternatives to choose in their own library. Nice reading everyone :) sugarjs.com/extending/
Great care should be taken when extending the built in types. The potential to break stuff is very high
I know, that's why i have 100% code coverage
Having 100% code coverage has nothing to do with the potential to break things. Even if your code is perfect, you can still break things by monkey patching.
at the first line of README you can find this:
if you use it in final application (whatever it is) you should be fine.
if you use with another library that change native object, some trouble can occurs if there is name collisions.
This is intended to use "alone" or at least with another that have no overlaps.
Most of this stuff is available in lodash without the pitfalls of having so many global functions. This is really bad practice, nobody should use this.
Also nobody else mentioned, besides all the other problems, you can't tree-shake away any of the methods you aren't using.
if you are building a cli, a microservice, something else where you control your node interpreter, this tool can make your life a bit easier.
If you are building a library, do not use this. Is literally in the first line
(i also make it a bit clear why in the readme after your reply).
I know this is wrong...
polyfull is not overriding language standard methods, so should be now way of broke another library, the only way this can happen is if is polyfilling the same signature with some other method.
Elsewhere i see no way you can broke it.
yes, and that is why versions exists