In javascript, I want to make a (shallow) copy of a Function
, so that the properties of the new object will not be affected by the original object:
function func(...) { ... } // to say, function func(x, y) { return [x,y] }
func.a = 1
let func1 = func // without copy, func1 and func IS the same object
let func2 = copy(func) // need to be implemented
func.a = 2
func1.a // becomes 2
func2.a // shall still be 1
func2("abc") // shall return the same result as func("abc")
Is it possible?
The best way I've found at present is defining a wrapper function:
function f0(x, y) { return [x,y] }
f0.a = 1
function copy(fn){
function wrapper(){
return fn.apply(wrapper, arguments)
}
Object.assign(wrapper,fn)
return wrapper
}
let f2 = copy(f0)
f0.a = 2
f2.a // is still 1
f0.length // gives 2
f2.length // gives 0
However, there are some problems with this solution:
copy
will lead to multiple levels of wrapper. for example, copy(copy(copy(fn)))
will return a function with three wrappers.length
of the origin function is lost, wrapper.length
is alaways 0
.According to the OP's asking I'm providing my above comment as an answer ...
As for the OP's use case, the simplest, most straight forward way is as follows. Create another function via
bind
. And since all offunc
's properties are assigned directly, the best way of assigning an entirely decoupled set offunc
specific own properties tof2
is by utilizing bothObject.assign
andstructuredClone
... all-in-one solution ...const f2 = Object.assign(func.bind(), structuredClone(Object.assign({}, func)));
function blueprint(a, b) {
return [a, b].join(' ');
}
blueprint.foo = 'foo';
const bpReference = blueprint;
const boundBpCopy = Object
.assign(
blueprint.bind(),
structuredClone(
Object.assign({}, blueprint)
)
);
console.log({ 'bpReference.foo': bpReference.foo });
console.log({ 'boundBpCopy.foo': boundBpCopy.foo });
blueprint.foo = 'BAR';
console.log({ 'bpReference.foo': bpReference.foo });
console.log({ 'boundBpCopy.foo': boundBpCopy.foo });
console.log(boundBpCopy('hello', 'world'));
.as-console-wrapper { bottom: auto; right: auto; top: 0; min-height: 100%; }
The OP's simplified version of the above provided stack snippet ...
const f2 = Object.assign(func.bind(),func);
... will create just a shallow copy for each of func
's own properties where such a property is an object itself and not just a primitive value.