valor - Propiedades de los objetos de la función Javascript
retornar valor de una funcion javascript (5)
No estoy seguro de que esto responda tu pregunta, pero puede darte una idea. Considere el siguiente ejemplo:
var Person = (function () {
var Person = function (name) {
this.name = name;
}
Person.greet = function () {
console.log("Hello!");
}
Person.prototype = {
greet: function () {
console.log(''Hello, my name is '' + this.name);
}
};
return Person;
})();
var bob = new Person("Bob");
Person.greet(); // logs "Hello!"
bob.greet(); // logs "Hello, my name is Bob
El objeto de función "Persona" tiene una propiedad directa de "saludo" que es una Función. OOP-wise, casi se puede pensar en eso como un método estático que se puede invocar directamente desde Person Function (Person.greet ()). Una vez que "instancia" un objeto de persona del constructor de Persona, ese nuevo objeto "bob" ahora hace referencia a sus métodos desde el objeto Person.prototype. Ahora cuando llamas a bob.greet (), usa la función de saludo en el objeto prototipo.
Espero que ayude.
Tengo un objeto de función JavaScript como;
var addNum = function(num1, num2) {
return num1 + num2;
}
Ahora si intento acceder
addNum.divide()
Quería entender la cadena de prototipos para el código anterior. Leí que en el ejemplo anterior, addNum se buscará para dividir (), seguido por Function.prototype y finalmente Object.prototype.
Pero mi pregunta es en el ejemplo anterior, ¿cómo se puede buscar addNum para dividir ()
¿Se refiere a algo así como;
var addNum = function(num1, num2) {
this.divide = function(){}
return num1 + num2;
}
No pude entender la línea donde dice que se buscará addNum para dividir ()
Por favor, ayúdame a entender lo mismo.
No, su último código solo tiene sentido si utilizó addNum
como función de constructor:
var instance = new addNum();
instance.divide();
Sin embargo, como las funciones son objetos, lo siguiente sería válido:
var addNum = function(num1, num2) {
return num1 + num2;
}
addNum.divide = function() {}
En este caso, divide
sería una propiedad de addNum
sí, no de uno de sus prototipos.
Puede crear divide
como un método static
[tipo de un]:
var addNum = function(num1, num2) {
addNum.divide = function(){return num1/num2;};
return num1 + num2;
}
// now you first have to run addNum
var onethirds = addNum(1,3); //=> 4
addNum.divide(); //=> 0.333333...
Pero no es recomendable. Mejor crea una función de constructor :
function Pair(n1,n2){
n1 = n1 || 1;
n2 = n2 || 1;
// create instance methods
this.add = function(){return n1+n2;};
this.divide = function(){return n1/n2;};
this.multiply = function(){return n1*n2;}
}
var pair1 = new Pair(2,6)
,pair2 = new Pair(1,2);
pair1.add(); //=> 8
pair2.divide(); //=> 0.5
//etc.
o un enfoque más prototípico (los métodos se agregan al prototipo del constructor, no a cada instancia):
function Pair(n1,n2){
this.n1 = n1 || 1;
this.n2 = n2 || 1;
// create prototype methods (once)
if (!Pair.prototype.add){
var proto = Pair.prototype;
proto.add = function(){return this.n1+this.n2;};
proto.divide = function(){return this.n1/this.n2;};
proto.multiply = function(){return this.n1*this.n2;}
}
}
Comprender la herencia prototípica es algo oscuro al principio, pero piénselo, como su nombre lo indica, hay algunos prototipos en JavaScript y la función es uno de ellos.
Cada vez que creas una nueva función puedes verificar su tipo con el comando typeof
. En tu caso:
var a = function(a,b) { return a + b; }
Devolverá la "function"
modo que hay dos maneras de agregar a su variable más métodos. Uno sería, como sugirió @Keith Morris, crear un nuevo constructor y tener sus métodos dentro y devolverlo. Esa es también la forma preferida porque entonces, no se contaminan los objetos básicos con métodos prototípicos que se extienden a todos y cada uno de los objetos que están representados por ellos.
Es decir, si en cambio hago esto:
Function.prototype.divide = function(a, b) { return a / b; }
Ahora puedo hacer a.divide(2, 1);
y devolvería 2
. Pero, por ejemplo, si uso jQuery
y hago jQuery.divide(2,1)
también obtendré 2
porque intenta encontrarlo en el alcance inmediato de la función. Si no, irá al prototipo de esto.
Espero que esto te lo explique un poco mejor.
Como dices tú mismo: tienes un objeto función . Las funciones son objetos en JS, al igual que los literales, las matrices o cualquier otra cosa del objeto: a una función se le pueden asignar propiedades y métodos a voluntad:
var someAnonFunction = function(foo)
{
console.log(this);
console.log(this === someAnonFunction);//will be false most of the time
};
someAnonFunction.x = 123;//assign property
someAnonFunction.y = 312;
someAnonFunction.divide = function()
{
console.log(this === someAnonFunction);//will be true most of the time
return this.x/this.y;//divide properties x & y
};
someAnonFunction.divide();
En este caso, al objeto de función al que hace referencia someAnonFunction
se le ha asignado una referencia a la función anónima, llamada divide
(de todos modos, la referencia a una función anónima se denominó dividir). Entonces no hay participación de prototipo en absoluto aquí. Object.prototype
cuenta, como dices tú mismo: todos los objetos se remontan a Object.prototype
, simplemente prueba esto:
console.log(someAnonFunction.toString === Function.prototype.toString);//functions are stringified differently than object literals
console.log(someAnonFunction.hasOwnProperty === Object.prototype.hasOwnProperty);//true
O, quizás esto sea más claro: un esquema simple de cómo una llamada método / propiedad se resuelve a un valor en JS:
[ F.divide ]<=========================================================/ /
F[divide] ===> JS checks instance for property divide | |
// || | |
|| || --> property found @instance, return value-------------------------------| |
|| || | |
|| ===========> Function.prototype.divide could not be found, check prototype | |
|| || | |
|| ||--> property found @Function.prototype, return-----------------------| |
|| || | |
|| ==========> Object.prototype.divide: not found check prototype? | |
|| || | |
|| ||--> property found @Object.prototype, return---------------------|_|
|| || |=|
|| =======>prototype is null, return "undefined.divide"~~~~~~~~~~~~~~~|X|
|| / /
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can''t read property ''x'' of undefined
Por lo tanto, si desea que el código anterior funcione usando prototipos, deberá aumentar un prototipo (en este caso, el prototipo Function.prototype
). Sepa que esto no se recomienda, de hecho el cambio de prototipos "nativos" a menudo es desaprobado. Todavía:
Function.prototype.divide = function (a, b)
{
a = +(a || 0);//coerce to number, use default value
b = +(b || 1) || 1;//division by zeroe is not allowed, default to 1
return a/b;
};
function someFunction ()
{
return ''someString'';
};
var another = function(a, b)
{
return a + b;
};
someFunction.divide(12, 6);//will return 2
another.divide(12, 4);//3
En ambos casos, el objeto de función al que hace referencia el nombre ( someFunction
u another
) se escaneará en busca de una propiedad llamada divide
, que no se encuentra. Luego, sin embargo, escaneará el Function.prototype
, donde se encuentra dicha propiedad.
Si ese no fuera el caso, JS también verificaría el Object.prototype
, si eso falla, eventualmente arrojará un error.
He publicado respuestas bastante largas sobre SO sobre este tema hace un tiempo:
¿Qué hace que my.class.js sea tan rápido? (se trata de cadenas de prototipos)
Objetos y funciones en javascript (recapitulación de funciones <=> objetos <=> constructores)
¿Cuáles son las diferencias entre estos tres patrones de definiciones de "clase" en JavaScript? (más información, aún)
Javascript - Cambia dinámicamente los contenidos de una función (toca vagamente las funciones anónimas, asignadas a variables y propiedades y cambiando su contexto)