Jonah Jonah - 1 month ago 5
Javascript Question

Implementing Ruby Refinements in Javascript

Ruby's refinements allow you to temporarily "upgrade" an object within a lexical scope. I'm trying to implement a similar idea in javascript. Here's some working code that does almost what I want:

function dateExtension() {
return {
day: function() { return this.getDate() }

function refine(ctor, mixin) {
return function() {
var ret = new (Function.prototype.bind.apply(ctor, arguments));
return Object.assign(ret, mixin);

function test() {
// Cant overwrite native Date function,
// so have to rename it.
var XDate = refine(Date, dateExtension());
var d = new XDate();
console.log(; // prints the day of the month to console



What I really want to do is this:

function test() {
var Date = refine(Date, dateExtension());
var d = new Date();
console.log(; // Uncaught TypeError: Bind must be called on a function

The idea would be to make the local
var Date
overide the built in
, within the body of
only. So that, within
, it would acquire the new method
, but outside of
would be unaffected. This apparently is not allowed.

Is there some workaround to make this idea work?


I made a tiny library called chill-patch to do exactly that. It enables you to use functions as methods, and to safely patch prototypes.

Here's an example of how to use it:

const chillPatch = require('chill-patch')
const lastFunc = arr => arr[arr.length - 1]
const array = [1, 2, 3]

// safely add a method to `Array` 
const last = chillPatch(Array, lastFunc, 'last')

// call the new method! 
array[last]() //=> 3 

If you want to roll your own, the entire source code is as follows:

'use strict'

const chillPatch = (klass, func, optionalDescription) => {
  const symbol = Symbol(optionalDescription)
  klass.prototype[symbol] = function(){
    const args =
    return func.apply(null, args)
  return symbol

module.exports = chillPatch

I see you said in a comment that you do not want to modify prototypes, but your reason is probably that modifying prototypes is dangerous. However, the method above patches using Symbol, which is completely safe. The change will be invisible to other parts of the codebase unless someone is doing reflection with Object.getOwnPropertySymbols()