2011-05-11 14 views
38

¿Se puede llamar a una función como un objeto? Por ejemplo:javascript: función y objeto ...?

function Tip(txt){  
    this.content = txt; 
    this.shown = false; 
} 

Y:

var tip = new Tip(elem.attr('title')); 

Mis preguntas:

  1. se puede llamar a new para una función, como para un objeto?
  2. El uso de "esto" es posible porque usa que funciona como un objeto?

Respuesta

108

Está buscando el constructor concepto.

Todas las funciones de JavaScript are objects y se pueden utilizar para crear objetos:

function make_person(firstname, lastname, age) { 
    person = {}; 
    person.firstname = firstname; 
    person.lastname = lastname; 
    person.age = age; 
    return person; 
} 
make_person("Joe", "Smith", 23); 
// {firstname: "Joe", lastname: "Smith", age: 23} 

Sin embargo, con el fin de crear nuevos objetos de un tipo determinado (es decir, que heredan un prototipo, tener un constructor , etc.), una función puede hacer referencia a this y si se llama con el operador new y devolverá un objeto con todos los atributos definidos en this en la función - this en tales casos hace referencia al nuevo objeto que somos creando.

function make_person_object(firstname, lastname, age) { 
    this.firstname = firstname; 
    this.lastname = lastname; 
    this.age = age; 
    // Note, we did not include a return statement 
} 

La diferencia clave a tener en cuenta entre make_person y make_person_object es que llamar new make_person() (en lugar de simplemente make_person()) no va a hacer nada diferente ... tanto producirá el mismo objeto. Llamando make_person_object() sin que el operador new sin embargo, va a definir sus atributos en la thisthis objeto actual

este modo (generalmente window si se está operando en el navegador.):

var Joe = make_person_object("Joe", "Smith", 23); 
console.log(Joe); // undefined 
console.log(window.firstname) // "Joe" (oops) 

var John = new make_person_object("John", "Smith", 45); 
console.log(John); // {firstname: "John", lastname: "Smith", age: 45} 

Además, como señala @RobG , esta forma de hacer las cosas crea una referencia a la propiedad prototype de make_person_object en cada "Persona" que creamos. Esto nos permite añadir métodos y atributos a las personas después de los hechos:

Convención
// Assuming all that came before 
make_person_object.prototype.full_name = "N/A"; 
make_person_object.prototype.greet = function(){ 
    console.log("Hello! I'm", this.full_name, "Call me", this.firstname); 
}; 
John.full_name // "N/A" 
John.full_name = "John Smith"; 
make_person_object.full_name // Still "N/A" 
John.greet(); // "Hello! I'm John Smith Call me John" 

cuenta que las funciones constructoras como make_person_object se capitalizan, singularizado y "nouned" (a falta de un término mejor) - por lo tanto que se tener un constructor Person, en lugar de un make_person_object que podría confundirse con una función normal.

Consulte también:

+6

omitió la parte más importante: el nuevo objeto al que hace referencia el 'de este constructor' hereda propiedades del prototipo del constructor. – RobG

+2

@RobG - ¡bien que yo * lo hice *! He actualizado la respuesta para incluir algunos ejemplos de esto. ¡Gracias por ayudar a mejorarlo! –

+1

Fantástica respuesta. Verdaderamente genial. Cubrí qué hacer y luego me enseñó a comprenderlo. Cada pregunta que tuve leyendo fue respondida en la siguiente sección después. ¡¡Gracias!! – redfox05

15

Cada función tiene una referencia a this. si llama al Tip(), this se referirá al objeto global. Si llama al new Tip(), se crea un nuevo objeto con una referencia a Tip.prototype y this se referirá a ese nuevo objeto.

No puede usar new en los objetos, por ejemplo new {} throws TypeError: object is not a function. Si se refiere a new Object(), entonces eso funciona ya que Object es una función.

1

La función actúa como un constructor en una clase. Alternativamente, se puede hacer:

function Tip(txt) { 
return { 
content: txt, 
shown: false 
} 
} 

y obtener una nueva instancia con: var myTip = new Tip("my epic tip"); Esto es similar a, por ejemplo, C#:

public class Tip { 
string text = ""; 
public Tip(string txt) { 
text = txt; 
} 
} 

Así que, en cierto modo. 1) Llamaste a alguien nuevo ya que la función esencialmente actúa como una clase, y 2) this se refiere a la instancia actual de la clase.

+2

La función no se utiliza como un objeto. Se crea un nuevo objeto cuando se usa 'new' y se llama a la función en el alcance de esa función –

+0

@Adam righto. Leí la fraseología exacta de su pregunta. lección aprendida. ;-) –

+0

@Adam: otra forma de crear un objeto es utilizar la sintaxis literal del objeto tal como lo hizo Thomas. Usar "nuevo" es solo una de las formas de crear objetos. – user670800

1

para # 1: Hay un objeto llamado Función (capital F)

var f = new Function ("x", "y", "retorno x * y;");

para # 2: el "esto" es diferente según el patrón de innvocación (como lo denomina Douglas Crockford). Crockford dijo que hay 4 patrones (patrón de método, patrón de función, patrón de constructor y patrón "aplicar")

+0

que llama a eval y no le da más poder del que normalmente crea las funciones de creación. También parece irrelevante para la pregunta. –

+0

no estoy seguro de lo que esto tiene que ver con el OP (tal vez soy solo yo). podría querer aclarar antes de que lleguen los votos a la baja. –

+0

@Adam: no está llamando a eval. la respuesta es relevante para su pregunta # 1 si la lees cuidadosamente. – user670800

5

Sí. En JavaScript, técnicamente todo es un objeto. Cuando usa new, crea una instancia del objeto Tip y luego llama a la función Tip como si fuera un constructor.

Si desea agregar funciones al objeto Consejo, se debe añadir que el prototipo del Consejo de este modo:

Tip.prototype.getContent = function() { 
    return this.content; 
}; 

Si usted tiene que, y luego hacer:

var tip = new Tip("this is my content."); 
alert(tip.getContent()); 

Se Le mostraré un mensaje que dice "este es mi contenido".

Solo se puede usar nuevo, sin embargo, si el objeto tiene una implementación funcional. Así que esto no funcionará:

var Tip = { content: txt, show: false }; 
var tipObj = new Tip(); 
0
  1. De hecho, cada tipo de datos como matriz, las funciones son objetos.
  2. Cuando tomamos la función como una declaración de clase, esto funciona.
0

He luchado para comprender estos conceptos (funciones como objetos, objetos prototipo, propiedad __proto__, propiedad del constructor) durante casi 8 años (2008-2016). Primero comencé David Flanagan "Guía Definitiva de JavaScript 5/6th ed" durante 4-5 años después de múltiples lecturas de los Capítulos 6,8,9; no tenía ningún sentido para mí, pero después de luchar en Internet, tuve que ser capaz de gestionar funciones (función típica de C++ con propiedades) como objetos; porque objeto también puede tener métodos. Y afortunadamente en 7mo año 2015, comencé Wrox Nicholas C.Zakas "JavaScript profesional para desarrolladores web 3rd ed" Capítulo 6,7; y fue realmente muy útil para entender los cuatro conceptos anteriores. Tradicionalmente, en C/C++/C# se piensa que las funciones modifican un objeto; o en otras palabras, están hechos para "hacer algo" mientras que los Objetos están hechos para mantener el estado del contexto de ejecución global con métodos para cambiar su propio estado de objeto. Entonces, si las funciones pueden ser objetos de primera clase, ¿por qué los objetos no pueden ser como funciones?

La pregunta clave aquí debería ser ¿POR QUÉ? ¿Por qué no la entidad conceptual única como "función asociativa" o "argumentos encadenados"? Y aquí está mi entendimiento: Browser exe es una única aplicación de subprocesos y este exe controla el intérprete de JS que llama con una cadena de alcance predefinida (algo similar a una cadena de comandos con argumentos); ahora, en tiempo de ejecución, el motor JS (no el intérprete) carga el código en forma de elevación (ya que no hay un método principal para elevar los códigos clave y su llamada). En este código elevado si las funciones no son tratadas como objetos, entonces deben mantenerse en un contexto de llamada separado (cadena fuera del alcance) que es fácilmente posible en c/C++/C# (bcoz de hilo múltiple y memoria ilimitada) pero no en JS . Por lo tanto, "hacer algo en un objeto encadenado" hace que una función de script java sea un objeto de primera clase. De hecho, los objetos JS también hacen lo mismo; la única diferencia es que "llamar a un objeto" no está en los objetos donde "llamar a una función" es un contexto encadenado que tiene sentido. Las funciones también pueden considerarse como "un grupo de variables con instrucciones de lenguaje ensamblador con enlace de dirección (cadena)". La parte de enlace es otro lado de la historia como top-> bottom linking (objeto prototipo) vs bottom-> top linking (propiedad __ proto__) vs object blue print-> object instances (propiedad del constructor). Hace algunos meses, encontré la siguiente imagen útil para entender los enlaces.

http://judis.me/wordpress/wp-content/uploads/2015/08/JavaScriptDiagram.png "modelo de objetos JS"

Cuestiones relacionadas