Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript: clone a function

People also ask

How do you clone a function in JavaScript?

Function. prototype. clone = function() { var newfun; eval('newfun=' + this. toString()); for (var key in this) newfun[key] = this[key]; return newfun; };

How do you clone a variable in JavaScript?

var clone = Object. assign({}, obj); The Object. assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

What is cloning object in JavaScript?

"Cloning" an object in JavaScript means creating a new object with the same properties as the original object. Objects in JavaScript are stored by reference, which means that two variables can point to the same object in memory. Modifying one object variable can impact other variables.

What is deep clone in JavaScript?

A deep copy is a copy of all elements of the original object. Changes made to the original object will not be reflected in the copy. In this article, you will create deep copies of objects using the Lodash library.


Here is an updated answer

var newFunc = oldFunc.bind({}); //clones the function with '{}' acting as its new 'this' parameter

However .bind is a modern ( >=iE9 ) feature of JavaScript (with a compatibility workaround from MDN)

Notes

  1. It does not clone the function object additional attached properties, including the prototype property. Credit to @jchook

  2. The new function this variable is stuck with the argument given on bind(), even on new function apply() calls. Credit to @Kevin

function oldFunc() {
  console.log(this.msg);
}
var newFunc = oldFunc.bind({ msg: "You shall not pass!" }); // this object is binded
newFunc.apply({ msg: "hello world" }); //logs "You shall not pass!" instead
  1. Bound function object, instanceof treats newFunc/oldFunc as the same. Credit to @Christopher
(new newFunc()) instanceof oldFunc; //gives true
(new oldFunc()) instanceof newFunc; //gives true as well
newFunc == oldFunc; //gives false however

try this:

var x = function() {
    return 1;
};

var t = function(a,b,c) {
    return a+b+c;
};


Function.prototype.clone = function() {
    var that = this;
    var temp = function temporary() { return that.apply(this, arguments); };
    for(var key in this) {
        if (this.hasOwnProperty(key)) {
            temp[key] = this[key];
        }
    }
    return temp;
};

alert(x === x.clone());
alert(x() === x.clone()());

alert(t === t.clone());
alert(t(1,1,1) === t.clone()(1,1,1));
alert(t.clone()(1,1,1));

Here's a slightly better version of Jared's answer. This one won't end up with deeply nested functions the more you clone. It always calls the original.

Function.prototype.clone = function() {
    var cloneObj = this;
    if(this.__isClone) {
      cloneObj = this.__clonedFrom;
    }

    var temp = function() { return cloneObj.apply(this, arguments); };
    for(var key in this) {
        temp[key] = this[key];
    }

    temp.__isClone = true;
    temp.__clonedFrom = cloneObj;

    return temp;
};

Also, in response to the updated answer given by pico.creator, it is worth noting that the bind() function added in Javascript 1.8.5 has the same problem as Jared's answer - it will keep nesting causing slower and slower functions each time it is used.


Being curious but still unable to find the answer to the performance topic of the question above, I wrote this gist for nodejs to test both the performance and reliability of all presented (and scored) solutions.

I've compared the wall times of a clone function creation and the execution of a clone. The results together with assertion errors are included in the gist's comment.

Plus my two cents (based on the author's suggestion):

clone0 cent (faster but uglier):

Function.prototype.clone = function() {
  var newfun;
  eval('newfun=' + this.toString());
  for (var key in this)
    newfun[key] = this[key];
  return newfun;
};

clone4 cent (slower but for those who dislike eval() for purposes known only to them and their ancestors):

Function.prototype.clone = function() {
  var newfun = new Function('return ' + this.toString())();
  for (var key in this)
    newfun[key] = this[key];
  return newfun;
};

As for the performance, if eval/new Function is slower than wrapper solution (and it really depends on the function body size), it gives you bare function clone (and I mean the true shallow clone with properties but unshared state) without unnecessary fuzz with hidden properties, wrapper functions and problems with stack.

Plus there is always one important factor you need to take into consideration: the less code, the less places for mistakes.

The downside of using the eval/new Function is that the clone and the original function will operate in different scopes. It won't work well with functions that are using scoped variables. The solutions using bind-like wrapping are scope independent.


It was pretty exciting to make this method work, so it makes a clone of a function using Function call.

Some limitations about closures described at MDN Function Reference

function cloneFunc( func ) {
  var reFn = /^function\s*([^\s(]*)\s*\(([^)]*)\)[^{]*\{([^]*)\}$/gi
    , s = func.toString().replace(/^\s|\s$/g, '')
    , m = reFn.exec(s);
  if (!m || !m.length) return; 
  var conf = {
      name : m[1] || '',
      args : m[2].replace(/\s+/g,'').split(','),
      body : m[3] || ''
  }
  var clone = Function.prototype.constructor.apply(this, [].concat(conf.args, conf.body));
  return clone;
}

Enjoy.


Short and simple:

Function.prototype.clone = function() {
  return new Function('return ' + this.toString())();
};

const oldFunction = params => {
  // do something
};

const clonedFunction = (...args) => oldFunction(...args);