¿Cuál es la forma más rápida de clonar una función en JavaScript (con o sin sus propiedades)?
Dos opciones que me vienen a la mente son eval(func.toString())
y function() { return func.apply(..) }
. Pero me preocupa que el rendimiento de eval y la envoltura empeore la pila y probablemente degradará el rendimiento si se aplica mucho o se aplica a la ya envuelta.
new Function(args, body)
se ve bien, pero ¿cómo exactamente puedo dividir de manera confiable la función existente en args y body sin un analizador JS en JS?
Gracias por adelantado.
Actualización: lo que quiero decir es poder hacer
var funcB = funcA.clone(); // where clone() is my extension
funcB.newField = {...}; // without affecting funcA
javascript
function
Andrey Shchekin
fuente
fuente
Respuestas:
prueba esto:
fuente
Aquí hay una respuesta actualizada
Sin embargo,
.bind
es una característica moderna (> = iE9) de JavaScript (con una solución alternativa de compatibilidad de MDN )Notas
No clona las propiedades adjuntas adicionales del objeto de función , incluida la propiedad del prototipo . Crédito a @jchook
La nueva función esta variable está atascada con el argumento dado en bind (), incluso en las nuevas llamadas de función apply (). Crédito a @Kevin
fuente
newFunc
NO tendrá su propio prototipo paranew newFunc
instancias, mientras queoldFunc
sí.var f = function() { console.log('hello ' + this.name) }
cuando se enlaza a{name: 'Bob'}
imprime 'hola Bob'.f.apply({name: 'Sam'})
también imprimirá 'hola Bob', ignorando el objeto 'esto'.function () { [native code] }
lugar del contenido completo de la función.Aquí hay una versión ligeramente mejor de la respuesta de Jared. Este no terminará con funciones profundamente anidadas cuanto más clone. Siempre llama al original.
Además, en respuesta a la respuesta actualizada dada por pico.creator, vale la pena señalar que la
bind()
función agregada en Javascript 1.8.5 tiene el mismo problema que la respuesta de Jared: seguirá anidando y causando funciones cada vez más lentas cada vez que se usa.fuente
Siendo curioso pero aún incapaz de encontrar la respuesta al tema de rendimiento de la pregunta anterior, escribí esta esencia para nodejs para probar tanto el rendimiento como la confiabilidad de todas las soluciones presentadas (y calificadas).
He comparado los tiempos de muro de la creación de una función de clonación y la ejecución de un clon. Los resultados junto con los errores de afirmación se incluyen en el comentario de la esencia.
Más mis dos centavos (según la sugerencia del autor):
clone0 cent (más rápido pero más feo):
clone4 cent (más lento pero para aquellos a quienes no les gusta eval () para propósitos que solo ellos y sus ancestros conocen):
En cuanto al rendimiento, si eval / new Function es más lento que la solución de envoltura (y realmente depende del tamaño del cuerpo de la función), le brinda un clon de función desnudo (y me refiero al clon superficial real con propiedades pero estado no compartido) sin problemas innecesarios con propiedades ocultas, funciones de envoltura y problemas con la pila.
Además, siempre hay un factor importante que debe tener en cuenta: cuanto menos código, menos lugares para errores.
La desventaja de usar la función eval / new es que el clon y la función original operarán en diferentes ámbitos. No funcionará bien con funciones que utilizan variables de ámbito. Las soluciones que utilizan envoltura similar a un enlace son independientes del alcance.
fuente
Object.assign(newfun.prototype, this.prototype);
antes de la declaración de devolución (versión limpia), su método es la mejor respuesta.Fue muy emocionante hacer que este método funcione, por lo que hace un clon de una función usando la llamada de función.
Algunas limitaciones sobre los cierres descritos en Referencia de funciones de MDN
Disfrutar.
fuente
Breve y simple:
fuente
fuente
fuente
originalFunction
, pero en realidad no las ejecutará cuando ejecuteclonedFunction
, lo cual es inesperado.Esta respuesta es para las personas que ven la clonación de una función como la respuesta a su uso deseado, pero que en realidad no necesitan clonar una función, porque lo que realmente quieren es simplemente poder adjuntar diferentes propiedades a la misma función, pero solo declare esa función una vez.
Haga esto creando una función de creación de funciones:
Esto no es exactamente lo mismo que ha descrito, sin embargo, depende de cómo desee utilizar la función que desea clonar. Esto también usa más memoria porque en realidad crea múltiples copias de la función, una vez por invocación. Sin embargo, esta técnica puede resolver el caso de uso de algunas personas sin la necesidad de una
clone
función complicada .fuente
Me pregunto: ¿por qué querría clonar una función cuando tiene prototipos Y puede establecer el alcance de una llamada de función a lo que desee?
fuente
Si desea crear un clon usando el constructor de funciones, algo como esto debería funcionar:
Una simple prueba:
Sin embargo, estos clones perderán sus nombres y el alcance de cualquier variable cerrada.
fuente
He mejorado la respuesta de Jared a mi manera:
1) ahora admite la clonación de constructores (se puede llamar con new); en ese caso, solo toma 10 argumentos (puede variarlo), debido a la imposibilidad de pasar todos los argumentos en el constructor original
2) todo está en cierres correctos
fuente
arguments[0], arguments[1] /*[...]*/
por qué no usas simplemente...arguments
? 1) No hay dependencia con respecto a la cantidad de argumentos (aquí limitado a 10) 2) más cortoSi bien nunca recomendaría usar esto, pensé que sería un pequeño desafío interesante crear un clon más preciso tomando algunas de las prácticas que parecían ser las mejores y arreglándolas un poco. Aquí está el resultado de los registros:
fuente
Esta función de clonación:
Tenga en cuenta que esta versión solo realiza una copia superficial. Si su función tiene objetos como propiedades, la referencia al objeto original se conserva (el mismo comportamiento que Object spread o Object.assign). Esto significa que cambiar las propiedades profundas en la función clonada afectará al objeto al que se hace referencia en la función original.
fuente