How to safely define a custom property on prototype in Javascript
Hello world citizens,
I want to share some code snippets about defining properties in Javascript. But first thing first WHY? Why I want to do such a thing? Here comes your answer my friend :)
- We may need a property to return our
array's last element
. Because we don't want to typearray[array.length - 1 ]
every time. We just want to get last element asarray.last
- We may need an
orderBy
ororderByDesc
function that will get a function as parameter , sort according to this function and then return brand new array without changing my original array(Remember Javascript originalsort
method mutates the source array, we do not want this behavior.)
... and so on.
Sounds good right? Just like Ruby language
. Let's see the code.
- I want to a property called
last
to get my last element in a array
if(!Array.prototype.last){
Object.defineProperty(Array.prototype,"last",{
get(){
return this.length > 0 ? this[this.length - 1] : undefined
}
})
}
var numbers = [1,2,3,4,5,6,7,8,9,10];
console.log(numbers.last); // 10
Take a look to if check. It is known as Guard clause
. Crucial to add, because we do not want to pollute global namespace if there is already defined a property called last(Maybe defined in a third party library, or a new shinny feature that will come with ES2099 :) )
- Or we want a
reject
function which rejects elements that satisfies a given criteria (I am sureRubyists
will understand much better :)
if(!Array.prototype.reject){
//With object define property writable,configurable,enumerable
// props are set false by default
Object.defineProperty(Array.prototype,"reject",{
value(predicate){
return this.filter(el => !predicate(el))
}
})
}
const users = [
{
"id": 1,
"username": "cambot",
"favorite_color": "red"
},
{
"id": 2,
"username": "gypsy",
"favorite_color": "purple"
},
{
"id": 3,
"username": "tom",
"favorite_color": "red"
},
{
"id": 4,
"username": "crow",
"favorite_color": "gold"
},
{
"id": 5,
"username": "joel",
"favorite_color": "red"
},
{
"id": 6,
"username": "mike",
"favorite_color": "blue"
},
{
"id": 6,
"username": "jonah",
"favorite_color": "yellow"
}
]
users.reject(u => u.favorite_color === "red");
/*-> [
{
"id": 2,
"username": "gypsy",
"favorite_color": "purple"
},
{
"id": 4,
"username": "crow",
"favorite_color": "gold"
},
{
"id": 6,
"username": "mike",
"favorite_color": "blue"
},
{
"id": 6,
"username": "jonah",
"favorite_color": "yellow"
}
]
*/
- Or we want to add a
where
method which will do same job with filter. For some people(Hi there C#,LINQ)where
method is much more convenient so lets add it to the array.
if(!Array.prototype.where){
Object.defineProperty(Array.prototype,"where", {
//default to false. If false you can not change or
//delete this property from our prototype
configurable: false,
//default to false. If false you can not assign our
//property to a new value
writable: false,
//default to false. If false you will not see this prop in
//enumeration process(for, for in, for of ...)
enumerable: false,
value(predicate){
return this.filter(predicate)
}
})
}
const numbers = [1,2,3,4,5,6,7,8,9,10]
console.log(numbers.where(num => num > 4)); // [5,6,7,8,9,10]
const isEven = n => n % 2 === 0 ;
console.log(numbers.where(isEven)); // [2,4,6,8,10]
- Or we want to an
orderBy
function to order array according to the provided functionwithout mutating original array
if(!Array.prototype.orderBy){
Object.defineProperty(Array.prototype,"orderBy", {
// we can assign our orderBy property to another
// function later on if we want
writable: true,
value(predicate){
//get copy array to prevent original array modification !!!
const copyArray = this.slice();
return copyArray.sort((val1,val2) => {
const firstValue = predicate(val1);
const secondValue = predicate(val2);
if(firstValue == null || secondValue == null){
return 0;
}
if(firstValue === secondValue){
return 0;
}
return firstValue > secondValue ? 1 : -1;
})
}
})
}
- Or
orderByDesc
function which does the above job but in reverse order
if(!Array.prototype.orderByDesc){
Object.defineProperty(Array.prototype,"orderByDesc", {
writable: true,
value(predicate){
//get copy array to prevent original array modification.
const copyArray = this.slice();
return copyArray.orderBy(predicate).reverse()
}
})
}
var people = [
{name:"chety", salary: 20_000},
{name:"rodik", salary: 5_000_000},
{name:"mirko", salary: 500_000},
]
//sort people by their name ascending(From A to Z)
//console.log(people.orderBy(p => p.name))
//sort people by their salary ascending(From Smaller to Bigger)
//console.log(people.orderBy(p => p.salary))
//sort people by their salary descending
console.log(people.orderByDesc(p => p.salary))
console.log(people) ;
That is it for today everyone. Please do not hesitate comment, share ... Have a nice day with JS.