2012-05-10 13 views
5

Estoy buscando poder extender el prototipo de función en javascript (es decir, agregar una función a todas las funciones). El propósito es convertirlo en un formato para el intercambio entre otro idioma (es decir, ruby, que solo puede comunicarse a través de cadenas [en esta configuración particular]). Ya tengo un sistema para que pueda pasar alrededor de otros tipos mediante la definición de un método to_js en objetos de rubí y un método to_ruby en javascript objetos, al igual queExtendiendo el prototipo de función

Number.prototype.to_ruby = function() { return this.toString(); } 

Esto está trabajando para todo lo demás que yo quiero que, pero no para funciones. Yo puedo conseguir que funcione en cromo de la siguiente manera:

_empty = function() {}; 
_empty.__proto__.to_ruby = function() { 
    return 'JSFunction.new(' + this.toString().to_ruby() + ')'; 
}; 

Pero esto no funciona en IE (que es un requisito del sistema).

Sé que tengo un objeto en alguna parte manteniendo un registro de funciones por una ID o similar, pero no puedo garantizar que se utilizarán con la misma instancia que las creó.

Todo lo demás no tan sólo pudiera escribir una función de reparto especial caso con ella (es decir, isFunction(instance) ? fn_to_ruby(instance) : instance.to_ruby(), pero yo prefiero mantener este modelo, si es posible.

+0

¡Hah! Yo solo estoy buscando lo mismo. SketchUp Ruby <-> JavaScript bridge. : D – thomthom

Respuesta

2

__proto__ no es una propiedad estándar. Pruebe este enfoque:

(function(){}).constructor.prototype.to_ruby = function(){ 
    return 'JSFunction.new(' + this.toString().to_ruby() + ')'; 
}; 
+0

¡Ah! Agregar el '.constructor' me da la funcionalidad que estaba buscando, ¡gracias! – DanielB

+2

Debe recibir el pago del personaje. '(function() {}). constructor.prototype' es solo' Function.prototype'. Y al llamar 'someObj.to_ruby()' será idéntico a '" "+ someObj' – RobG

+0

@RobG, estás en lo correcto, y por supuesto ahora que puedo verlo, tiene mucho sentido. gracias :) – DanielB

-1

El __proto__ no es parte de ningún estándar JavaScript es sólo Pesudo un estándar que algunos de los fabricantes de navegadores han decidido implementar. IE es uno que no ha puesto en práctica.

Si desea modificar cualquier tipo en el sistema de tipo JavaScript, entonces tendrá para modificar el prototipo Object:

Object.prototype.foo = function() { console.log('foo'); }; 
(1).foo(); 
'asd'.foo(); 
(true).foo(); 
({ bar: 'baz' }).foo(); 
3

Como dijo Slace, puede agregar el método a todos los objetos añadiéndolo a Object.prototype, pero eso no es realmente kosher ya que puede afectar gravemente escrita de bucles for..in.

puedes añadir simplemente a las funciones mediante Function.prototype:

Function.prototype.to_ruby = function() { 
    return this.toString(); 
} 

Sin embargo, hay una regla general que no debe modificar los objetos incorporados, sobre todo porque nunca se sabe cuándo va a volver en tu contra usted (por ejemplo, una nueva versión de ECMAScript implementa una propiedad con el mismo nombre). Tal vez usted es mejor que escribir una sola toRuby función:

function toRuby(obj) { 
    return obj.toString(); 
} 

pero también se puede también utilizar el operador + para concatenar con una cadena para llamar al método toString implícitamente:

'' + obj; // returns obj.toString() 

que devolverá exactamente el mismo resultado que ambos anteriores. Tu elección.

+0

Entiendo su argumento, pero tengo una serie de diferentes tipos de objetos que todos deben devolver de forma ligeramente diferente. Así que esto funcionaría para tipos básicos como números y cadenas (suponiendo que no necesitan ser escapados) pero para matrices, objetos tipo hash y tipos personalizados, tendría que escribir un caso especial para cada uno, y continuar editando que como requiero más o menos objetos. – DanielB

+0

En ese caso, puede escribir una sola función 'toRuby()' y decirle cómo convertir el objeto pasado, p. 'toRuby (someFn, 'fn')', 'toRuby (someObj, 'obj')' o similar. – RobG

+0

Eso es lo que originalmente tenía, pero a medida que aumentaba el número de posibles tipos de objetos, pensé que sería más fácil tener un método to_ruby en los objetos que admitían la conversión. De esa forma podría probar fácilmente el soporte y realizar la conversión. – DanielB

Cuestiones relacionadas