ultima tipos orientado objetos objeto ejemplos datos crear javascript object methods prototype

orientado - tipos de datos en javascript ejemplos



¿Cómo hacer un método que pueda afectar cualquier tipo de valor? (10)

Antes de comenzar, hay pocas declaraciones importantes para recordar y tener en cuenta (verdadero para todas las cadenas literales / primitivas, objeto String, número literal / primitivo, objeto Number, etc.):

  • Todos los objetos en JavaScript descienden de Object y heredan métodos y propiedades de Object.prototype - String , Number , etc (muy parecido a Java).
  • JS tiene 6 tipos primitivos: cadena , número , booleano , nulo , indefinido y símbolo
  • JS tiene sus objetos correspondientes de envoltura: String , Number , Boolean y Symbol
  • Como puede ver arriba, JS tiene una cadena como primitiva y un Object
  • Primitivo no es del tipo Object .
  • String literal es un objeto primitivo y String es de tipo Object .
  • El operador instanceof comprueba si un objeto tiene en su cadena de prototipo la propiedad prototipo de un constructor. (la primera condición para obtener VERDADERO aquí es que instanceof se debe usar contra un objeto o su subclase )
  • El operador typeof devuelve una cadena que indica el tipo del operando no evaluado.

Cadena como primitiva:
La cadena primitiva o literal se puede construir de las siguientes maneras:

var str1 = “Hello”; var str2 = String(“Hello”); typeof str1; //Output = "string" typeof str2; //Output = "string" str1 instanceof (String || Object) //Output = false because it is a primitive not object str2 instanceof (String || Object) //Output = false because it is a primitive not object

Cadena como objeto:
El objeto String se puede construir llamando a su constructor desde un nuevo objeto:

var str3 = new String(“Hello”); typeof str3; //Output = "string" str3 instanceof (String) //Output = true because it is a String object str3 instanceof (Object) //Output = true because it is an Object

Sobre todo, puede parecer poco obvio, pero era necesario sentar las bases.
Ahora, déjame hablar sobre tu caso.

Object.prototype.isString = function() { return typeof this === "string"; } "5".isString() //returns false "".isString() //returns false var str = "string" str.isString() //returns false

Obtiene FALSE como o / p debido a un concepto llamado Auto-boxing. Cuando llamas a cualquier método en una cadena literal, entonces se convierte a un objeto String. Lea esto de MSDN - "Métodos para cadenas literales", para estar seguro en usted mismo.

Entonces, en su prototipo, cuando verifique el tipo usando typeof , nunca será un literal ( typeof == "string" ) porque ya está convertido en un objeto. Esa es la razón por la que recibes una typeof falsa, si compruebas el tipo de object entonces serás cierto, y voy a hablar en detalle a continuación:

  • typeof dará información sobre qué tipo de entidad es: un objeto o una primitiva (cadena, número, etc.) o una función.
  • instanceof dará información sobre qué tipo de objeto JS es: objeto o cadena o número o booleano o símbolo

Ahora déjame hablar sobre la solución que se te proporciona. Dice que hagas un chequeo de instanceof , que es 100% correcto, pero con una nota que al llegar a tu prototipo podría ser de tipo de objeto o tipo de función. Entonces, la solución que les brindo a continuación les dará una imagen de lo mismo.

Mi recomendación es tener una función genérica que te devuelva el tipo de instancia, y luego puedes hacer lo que quieras en función de si es un Número o una Cadena, etc. isString es bueno, pero luego debes escribir isNumber , etc., entonces en su lugar, tiene una función única que le devolverá el tipo de instancia e incluso puede manejar el tipo de función.
A continuación está mi solución:

Object.prototype.getInstanceType = function() { console.log(this.valueOf()); console.log(typeof this); if(typeof this == "object"){ if(this instanceof String){ return "String"; } else if(this instanceof Boolean){ return "Boolean"; } else if(this instanceof Number){ return "Number"; } else if(this instanceof Symbol){ return "Symbol"; } else{ return "object or array"; //JSON type object (not Object) and array } } else if(typeof this == "function"){ return "Function"; } else{ //This should never happen, as per my knowledge, glad if folks would like to add... return "Nothing at all"; } }

Salida:

new String("Hello").getInstanceType() //String "Hello".getInstanceType() //String (5).getInstanceType() //Number (true).getInstanceType() //Boolean Symbol().getInstanceType() //Symbol var ddd = function(){} var obj = {} obj.getInstanceType() //object or array var arr = [] arr.getInstanceType() //object or array ddd.getInstanceType() //Function ($).getInstanceType() //Function, because without double quotes, $ will treated as a function ("$").getInstanceType() //String, since it came in double quotes, it became a String

Para concluir: sus 2 preocupaciones como a continuación

Pero lo que necesito hacer es usar eso en cualquier valor, y acceder al valor en la función.

Puede acceder al valor en su función usando this . En mi solución, puede ver console.log(this.valueOf());

¿Hay alguna solución para que esto sea propiedad de cualquier Objeto si uso Object.prototype?

Puede lograrlo desde Object.prototype.getInstanceType según la solución anterior, y puede invocarlo en cualquier objeto JS válido y obtendrá la información deseada.

¡Espero que esto ayude!

Advertencia: la creación de extensiones a objetos y / o propiedades nativas se considera de mala calidad y puede causar problemas. No use esto si se trata de un código que no está utilizando únicamente para usted o si no sabe cómo usarlo correctamente.

Sé que puedes usar Object , String , Number , Boolean , etc. para definir un método, algo como esto:

String.prototype.myFunction = function(){return this;} //only works on strings.

Pero lo que necesito hacer es usar eso en cualquier valor, y acceder al valor en la función.

Busqué en Google y miré here , pero no pude encontrar nada adecuado.

18/02/15 Editar: ¿Hay alguna solución para que esto sea una propiedad de cualquier objeto si uso Object.prototype ?
Por solicitud, aquí está la función actual que se utiliza para isString()

function isString(ins) { return typeof ins === "string"; }

Siguiendo algunas respuestas, he encontrado algunos códigos y errores causados ​​por él.

Object.prototype.isString = function() { return typeof this === "string"; } "5".isString() //returns false "".isString() //returns false var str = "string" str.isString() //returns false


Como algunos otros han señalado que su código es casi correcto, espere el tipo de typeof this === ''string'' que no funciona debido al comportamiento peculiar de JavaScript cuando se trata de primitivas vs. objetos. Una de las formas más sólidas para probar si un objeto es una cadena es con Object.prototype.toString.call(this) === ''[object String]'' (vea este artículo ). Con esto en mente, simplemente podría escribir su implementación de isString así:

Object.prototype.isString = function () { return Object.prototype.toString.call(this) === ''[object String]''; }; "abc".isString(); // ==> true "".isString(); // ==> true 1..isString(); // ==> false {}.isString(); // ==> false


De la descripción del Object MDN :

Todos los objetos en JavaScript descienden de Object

Por lo tanto, puede agregar métodos a Object.prototype , que luego puede Object.prototype sobre cualquier cosa . Por ejemplo:

Object.prototype.isString = function() { return this.constructor.name === ''String''; } console.log("hi".isString()); //logs true console.log([].isString()); //logs false console.log(5..isString()); //logs false

Podría crear estas funciones de isX para cada tipo de primitiva que haya, si lo desea. De cualquier manera, puede agregar métodos a cada tipo, ya que todo en JavaScript desciende de un Object .

Espero que ayude y buena suerte :)

--editar--

Quería señalar que el hecho de que pueda hacer esto no significa que deba hacerlo . En general, es una mala práctica ampliar la funcionalidad incorporada de JavaScript, más aún para una biblioteca que otros usarán. Depende de su caso de uso, sin embargo. La mejor de las suertes.


Dejando a un lado las discusiones, que esta no es una buena práctica y no es un enfoque común como el wrapper-constructor, deberías lograr esto pidiendo el nombre del constructor :

Object.defineProperty(Object.prototype, ''isString'', { value: function() { return this.constructor.name === "String"; } });

o con el método de ejemplo también mencionado anteriormente:

Object.defineProperty(Object.prototype, ''isString'', { value: function() { return this instanceof String; } });

La explicación de por qué su método no funcionó se está ocupando en esta publicación .

Si desea que su nueva propiedad definida sea enumerable, configurable o escribible, debe echar un vistazo a los documentos para defineProperty .


El código publicado que amplía el prototipo de objeto funcionará, si se corrige.

Sin embargo, hace una suposición incorrecta acerca de qué es this dentro del método invocado. Con el código publicado, el siguiente resultado es correcto y de esperar (salvo algunos viejos errores de implementación);

"5".isString() //returns false

Esto se debe a que JavaScript " ajustará " o "promocionará" el valor primitivo al tipo de objeto correspondiente antes de invocar el método; this es realmente un objeto String, no un valor de cadena. (JavaScript falsifica de manera efectiva los métodos de llamada en valores primitivos).

Reemplace la función con:

Object.prototype.isString = function() { return this instanceof String; }

Entonces:

"5".isString() // => true (a string was "promoted" to a String) (5).isString() // => false (`this` is a Number)

Otra solución a esto es usar polimorfismo; con los mismos "inconvenientes" 1 de modificar prototipos estándar.

Object.prototype.isString = function () { return false; } String.prototype.isString = function () { return true; }

1 La preocupación de agregar una nueva propiedad enumerable a los prototipos globales se puede mitigar con el uso de defineProperty que crea una propiedad "no enumerable" de forma predeterminada.

Simplemente cambia

x.prototype.y = ..

a

Object.defineProperty(x.prototype, ''y'', { value: .. })

(No defiendo el uso de la modificación del prototipo, solo explica el resultado problemático original y señala una forma de evitar el comportamiento de enumeración).


En primer lugar, ¿por qué la definición de propiedades en Object (u otros tipos de construcción) está mal visto? Aparecen en lugares inesperados. Aquí hay un código que muestra el número total de pies que tienen algunos personajes:

var feetMap = { jerry : 4, donald : 2, humpty: 0 } function countFeet(feetMap) { var allFeet = 0; for (var character in feetMap) { allFeet += feetMap[character]; } return allFeet; } console.log(''BEFORE DEFINITION'', countFeet(feetMap)); Object.prototype.isString = function() { return typeof this === "string"; }; console.log(''AFTER DEFINITION'', countFeet(feetMap));

Tenga en cuenta que la simple definición de su función isString influirá en el resultado de la función countFeet que ahora itera sobre una propiedad inesperada. Por supuesto, esto se puede evitar si la iteración se protegió con la comprobación hasOwnProperty, o si la propiedad se definió como no enumerable.

Otra razón para evitar la definición de propiedades en los tipos integrados es la posibilidad de colisión. Si todos definieran su propio método isNumber que ofreciera resultados ligeramente diferentes en función de los casos de uso (uno podría considerar la cadena "42" como un número y otro podría decir que no), los errores sutiles aparecerían por todas partes cuando las personas usaran múltiples bibliotecas.

La pregunta es: ¿por qué necesita un método que pueda afectar a cualquier tipo de valor? Un método debe ser algo inherente a la clase de objetos a la que pertenece. Tener un método isString no tiene sentido en un objeto Number, simplemente no tiene ninguna relevancia para Numbers.

Lo que tiene más sentido es tener una función / método que pueda devolver el tipo del valor que se le asigna como parámetro:

var Util = Util || {}; Util.isString(value) { return typeof value === "string"; } Util.isString(''test'') // true Util.isString(5) // false

La razón por la cual tu código actual

Object.prototype.isString = function() { return typeof this === "string"; } "5".isString() //returns false "".isString() //returns false var str = "string" str.isString() //returns false

no funciona es porque cuando accede a una propiedad en un valor primitivo, JS crea un objeto contenedor de los tipos apropiados y resuelve la propiedad en ese objeto contenedor (luego de lo cual lo descarta). Aquí hay un ejemplo que debería dilucidarlo:

Object.prototype.getWrapper = function(){ return this; } console.log((5).getWrapper()); // Number [[PrimitiveValue]]:5 console.log("42".getWrapper()); // String [[PrimitiveValue]]:"42"

Tenga en cuenta que el valor primitivo 5 y el objeto nuevo Número (5) son conceptos diferentes.

Puede modificar su función para que funcione principalmente devolviendo el tipo del valor primitivo. Además, no olvides hacer que no sea enumerable para que no aparezca cuando iteres sobre objetos aleatorios.

Object.defineProperty(Object.prototype, ''isString'', { value : function() { return typeof this.valueOf() === "string"; }, enumerable : false }); "5".isString() //returns true "".isString() //returns true var str = "string" str.isString() //returns true


Esto se debe a que los literales de cadena son del tipo de cadena nativa, no una instancia del objeto String, de hecho, no se puede llamar a ningún método desde el prototipo de Objeto o Cadena.

Lo que está sucediendo es que cuando intentas llamar a cualquier método sobre una variable cuyo tipo es cadena, Javascript coacciona automáticamente ese valor a un objeto String recién construido .

Asi que

"abc".isString();

Es lo mismo que:

(new String("abc")).isString();

El efecto secundario de eso es que lo que está recibiendo en su método isString () es un Objeto (variable de tipo) que, también, es una instancia del objeto String.

Tal vez podrías verlo más claramente con un ejemplo simplificado:

var a = "Hello"; console.log(typeof a); // string var b = new String("Hello"); console.log(typeof b); // object

Por cierto, la mejor probabilidad de que tengas que detectar cadena en tu función, como muchos otros dijeron, es comprobar si es una instancia del objeto String con:

foo instanceof String

Si también desea verificar otros tipos posibles, debe hacer una doble comprobación como la siguiente:

function someOtherFn(ins) { var myType = typeOf ins; if (myType == "object" && ins instanceof String) myType = "string"; // Do more stuf... }


Para mostrarte un ejemplo:

String.prototype.myFunction = function() { return this+"asd"; };

esta función agregará "asd" a cada cadena cuando se myFunction() .

var s = "123"; s = s.myFunction(); //s is now "123asd"


Una "función de operador de punto" se llama método. La forma más limpia de crear un método en JavaScript que pueda funcionar en cualquier tipo de datos es crear un contenedor. Por ejemplo:

var Wrapper = defclass({ constructor: function (value) { this.value = value; }, isString: function () { return typeof this.value === "string"; }, describe: function () { if (this.isString()) { alert(''"'' + this.value + ''" is a string.''); } else { alert(this.value + " is not a string."); } } }); var n = new Wrapper(Math.PI); var s = new Wrapper("Hello World!"); n.describe(); // 3.141592653589793 is not a string. s.describe(); // "Hello World!" is a string. function defclass(prototype) { var constructor = prototype.constructor; constructor.prototype = prototype; return constructor; }

Al crear su propio constructor de envoltura, se asegura de que:

  1. Tu código no afecta el código de otras personas.
  2. El código de otras personas no juega con tu código.
  3. Mantiene limpio el alcance global y los prototipos nativos.

Varias bibliotecas populares de JavaScript como underscore y lodash crean constructores de envoltura para este propósito.


Object.prototype.isString = function() { return typeof this === "string"; } "5".isString() //returns false "".isString() //returns false var str = "string" str.isString() //returns false

Si alguien puede explicar una solución para que la función sea propiedad de cualquier objeto, y por qué el método actual no funciona, proporcionaré 125 rep.

Responder:

Bueno, en javascript, cuando llamas a un submétodo / propiedad de un objeto,
como "myFunction" (object.myFunction u object ["MyFunction"])
comenzará a ver si el objeto en sí lo tiene.
SI NO: seguirá la cadena del prototipo (como la superclase en oop normal),
hasta que encuentre un "padre / superclase" con el método / propiedad.
El último paso en esta cadena de prototipos es Object.
Si Object dosnt tiene el método, devolverá "undefined".

Al extender la clase Object en sí siempre verá cualquier objeto llamando al método como un Objeto (In oop: Todas las clases también son Object además el propio Classtype) Esto es como perder un "cast" en OOP normal.

Entonces la razón por la cual su función devuelve falso es que es un "objeto" no una "cadena" en este contexto
Intente hacer esta función:

Object.prototype.typeString = function() { return typeof this; } "5".typeString() //returns "object"

Como todos dicen que es realmente mala idea extender cualquiera de las clases JS nativas , pero una solución alternativa comenzaría con algo como esto:

Object.prototype.objectTypeString = function(){ return Object.prototype.toString.call(this); }

Aquí hay un violín: http://jsfiddle.net/fwLpty10/13/

Tenga en cuenta que el dosificado nulo tiene un prototipo y NaN (NotANumber) se convierte en un Número !!! Esto significa que siempre tendrá que verificar si una variable es nula , antes de llamar a este método.

Object.prototype.isString = function(){ return Object.prototype.toString.call(this) === "[object String]"; };

Violín final: http://jsfiddle.net/xwshjk4x/5/

El truco aquí es que este método devuelve el resultado del método toString, que se llama con "this", lo que significa que, en el contexto del método toString, el objeto al que lo llama es su propia clase (no cualquier supertipo en la cadena de prototipos)