Skip to content

Instantly share code, notes, and snippets.

@royaltm
Created August 23, 2013 16:54
Show Gist options
  • Save royaltm/6321532 to your computer and use it in GitHub Desktop.
Save royaltm/6321532 to your computer and use it in GitHub Desktop.
var assert = require('assert');
function timer(fun) {
var start = Date.now();
try {
fun()
} catch(e) {
console.error(e);
}
console.log((Date.now() - start) / 1000 + 's');
}
Function.prototype.clone0 = function() {
var newfun;
eval('newfun=' + this.toString());
for (var key in this)
newfun[key] = this[key];
return newfun;
};
Function.prototype.clone1 = function() {
var that = this;
var temp = function temporary() { return that.apply(this, arguments); };
for(var key in this ) {
temp[key] = this[key];
}
return temp;
};
Function.prototype.clone2 = function() {
return this.bind({});
};
Function.prototype.clone3 = 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;
};
Function.prototype.clone4 = function() {
var newfun = new Function('return ' + this.toString())();
for (var key in this)
newfun[key] = this[key];
return newfun;
};
function Alpha(a,b,c) {
return a+b+c;
}
Alpha.x = {bar:1};
Alpha.prototype.x = {foo:1};
Function.prototype.clone = Function.prototype[process.argv[2]];
var test = Alpha.clone();
timer(function() {for(var i=0;i<100000;i++) test = test.clone()});
timer(function() {for(var i=0;i<10000000;i++) test(1,2,3)});
// not the same object
assert.notStrictEqual(test, Alpha);
assert.notEqual(test, Alpha);
// works the same way
assert.equal(test(1,2,3), 6);
assert.equal(Alpha(1,2,3), 6);
// same basic properties
assert.equal(Alpha.length, 3);
assert.equal(test.length, 3);
assert.equal(Alpha.name, 'Alpha');
assert.equal(test.name, Alpha.name);
// same source
assert.equal(test.toString(), Alpha.toString());
assert.deepEqual(test.toString(), Alpha.toString());
// same extended properties
assert.deepEqual(Alpha.x, {bar:1});
assert.strictEqual(test.x, Alpha.x);
// not shared state (the strict equality test is enough, but seeing is believing)
test.x = 2;
assert.notStrictEqual(test.x, Alpha.x);
assert.deepEqual(Alpha.x, {bar:1});
// not shared prototype (we have cloned the <<function>> not the object factory)
assert.deepEqual(new Alpha().x, {foo:1});
assert.strictEqual(new test().x, void(0));
assert.strictEqual(new Alpha().constructor, Alpha);
assert.notEqual(new Alpha().constructor, new test().constructor);
assert.strictEqual(new test().constructor, test);
console.log('all good!');
@royaltm
Copy link
Author

royaltm commented Aug 23, 2013

$node clonetest.js clone0
0.481s
0.061s
all good!

$ node clonetest.js clone1
0.403s
[RangeError: Maximum call stack size exceeded]

$ node clonetest.js clone2
0.659s
2.532s

assert.js:92
throw new assert.AssertionError({
^
AssertionError: "" == "Alpha"

$ node clonetest.js clone3
0.53s
0.227s

assert.js:92
throw new assert.AssertionError({
^
AssertionError: 0 == 3

$ node clonetest.js clone4
0.578s
0.061s
all good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment