Pregunta ¿Cuál es la palabra clave 'nueva' en JavaScript?


los new La palabra clave en JavaScript puede ser bastante confusa cuando se la encuentra por primera vez, ya que las personas tienden a pensar que JavaScript no es un lenguaje de programación orientado a objetos.

  • ¿Qué es?
  • ¿Qué problemas resuelve?
  • ¿Cuándo es apropiado y cuándo no?

1555
2017-10-29 21:32


origen


Respuestas:


Hace 5 cosas:

  1. Crea un nuevo objeto. El tipo de este objeto es simplemente objeto.
  2. Establece el nuevo objeto interno, inaccesible, [[prototipo]] (es decir. __proto__) propiedad para ser la función externa del constructor, accesible, prototipo objeto (cada objeto de función tiene automáticamente un prototipo propiedad).
  3. Hace que el this punto variable al objeto recién creado.
  4. Ejecuta la función constructora, utilizando el objeto recién creado cada vez que this es mencionado.
  5. Devuelve el objeto recién creado, a menos que la función del constructor devuelva un no-null referencia de objeto En este caso, esa referencia de objeto se devuelve en su lugar.

Nota: función constructora refiere la función después del new palabra clave, como en

new ConstructorFunction(arg1, arg2)

Una vez hecho esto, si se solicita una propiedad indefinida del nuevo objeto, el script verificará el objeto [[prototipo]] objeto para la propiedad en su lugar. Así es como puede obtener algo similar a la herencia de clase tradicional en JavaScript.

La parte más difícil de esto es el punto número 2. Cada objeto (incluidas las funciones) tiene esta propiedad interna llamada [[prototipo]]. Puede solamente establecerse en el momento de creación del objeto, ya sea con nuevo, con Object.createo basado en el literal (funciones predeterminadas para Function.prototype, numbers to Number.prototype, etc.). Solo se puede leer con Object.getPrototypeOf (someObject). Ahi esta no otra forma de establecer o leer este valor.

Funciones, además de las ocultas [[prototipo]] propiedad, también tienen una propiedad llamada prototipo, y es esto que puede acceder y modificar para proporcionar propiedades heredadas y métodos para los objetos que crea.


Aquí hay un ejemplo:

ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes 
// it a constructor.

ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that 
// we can alter. I just added a property called 'b' to it. Like 
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with

obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1.  At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'.

obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks 
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'

Es como herencia de clase porque ahora, cualquier objeto que hagas usando new ObjMaker() también parece haber heredado la propiedad 'b'.

Si quieres algo como una subclase, entonces haz esto:

SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);

SubObjMaker.prototype.c = 'third';  
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype

obj2.c;
// returns 'third', from SubObjMaker.prototype

obj2.b;
// returns 'second', from ObjMaker.prototype

obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype 
// was created with the ObjMaker function, which assigned a for us

Leí un montón de basura sobre este tema antes de encontrar finalmente esta página, donde esto se explica muy bien con buenos diagramas.


1958
2017-10-29 22:22



Supongamos que tiene esta función:

var Foo = function(){
  this.A = 1;
  this.B = 2;
};

Si llamas esto como una función independiente como esta:

Foo();

La ejecución de esta función agregará dos propiedades a la window objeto (A y B) Lo agrega a la window porque window es el objeto que llamó a la función cuando la ejecutas así, y this en una función es el objeto que llamó a la función. En Javascript al menos.

Ahora, llámalo así con new:

var bar = new Foo();

Qué pasa cuando agregas new a una llamada de función es que se crea un nuevo objeto (solo var bar = new Object()) y que el this dentro de la función apunta a la nueva Object que acaba de crear, en lugar de al objeto que llamó a la función. Asi que bar ahora es un objeto con las propiedades A y B. Cualquier función puede ser un constructor, simplemente no tiene sentido.


359
2018-06-20 23:46



Además de la respuesta de Daniel Howard, esto es lo que new lo hace (o al menos parece que lo hace):

function New(func) {
    var res = {};
    if (func.prototype !== null) {
        res.__proto__ = func.prototype;
    }
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }
    return res;
}

Mientras

var obj = New(A, 1, 2);

es equivalente a

var obj = new A(1, 2);

146
2018-05-27 09:23



Para principiantes para entenderlo mejor

pruebe el siguiente código en la consola del navegador.

function Foo() { 
    return this; 
}

var a = Foo();       //returns window object
var b = new Foo();   //returns empty object of foo

a instanceof Window;  // true
a instanceof Foo;     // false

b instanceof Window;  // false
b instanceof Foo;     // true

Ahora puedes leer la respuesta wiki de la comunidad :)


85
2017-10-29 21:34



así que probablemente no sea para crear   instancias de objeto

Se usa exactamente para eso. Usted define un constructor de funciones así:

function Person(name) {
    this.name = name;
}

var john = new Person('John');

Sin embargo, el beneficio adicional que tiene ECMAScript es que puede extenderse con el .prototype propiedad, entonces podemos hacer algo como ...

Person.prototype.getName = function() { return this.name; }

Todos los objetos creados a partir de este constructor ahora tendrán una getName debido a la cadena de prototipos a la que tienen acceso.


33
2017-10-29 21:36



JavaScript es un lenguaje de programación orientado a objetos y se usa exactamente para crear instancias. Se basa en prototipos, en lugar de en clases, pero eso no significa que no esté orientado a objetos.


26
2017-10-29 21:37



Javascript es un lenguaje de programación dinámica que admite el paradigma de programación orientada a objetos y se usa para crear nuevas instancias de objetos.

Las clases no son necesarias para los objetos: Javascript es prototipo basado idioma.


13
2018-05-16 07:21



a veces el código es más fácil que las palabras:

var func1 = function (x) { this.x = x; }                    // used with 'new' only
var func2 = function (x) { var z={}; z.x = x; return z; }   // used both ways
func1.prototype.y = 11;
func2.prototype.y = 12;

A1 = new func1(1);      // has A1.x  AND  A1.y
A2 =     func1(1);      // undefined ('this' refers to 'window')
B1 = new func2(2);      // has B1.x  ONLY
B2 =     func2(2);      // has B2.x  ONLY

para mí, siempre que no prototipo, uso el estilo de func2 ya que me da un poco más de flexibilidad dentro y fuera de la función.


3
2017-10-29 21:38



los new la palabra clave es para crear nuevas instancias de objetos. Y sí, javascript es un lenguaje de programación dinámico, que admite el paradigma de programación orientada a objetos. La convención sobre el nombramiento de objetos es, siempre use letras mayúsculas para los objetos que se supone deben ser instanciados por la nueva palabra clave.

obj = new Element();

2
2017-10-05 02:28



Ya hay algunas respuestas muy buenas, pero estoy publicando una nueva para enfatizar mi observación sobre el caso III a continuación sobre lo que sucede cuando tienes una declaración de devolución explícita en una función que eres newlevantando Echa un vistazo a los casos a continuación:

Caso I:

var Foo = function(){
  this.A = 1; 
  this.B = 2;
};
console.log(Foo()); //prints undefined
console.log(window.A); //prints 1

Arriba hay un caso simple de llamar a la función anónima apuntada por Foo. Cuando llamas a esta función, regresa undefined. Como no existe una declaración de devolución explícita, el intérprete de JavaScript inserta a la fuerza return undefined; declaración al final de la función. Aquí la ventana es el objeto de invocación (contextual this) que se pone nuevo A y B propiedades.

Caso II:

var Foo = function(){
  this.A = 1;
  this.B = 2;
};
var bar = new Foo();
console.log(bar()); //illegal isn't pointing to a function but an object
console.log(bar.A); //prints 1

Aquí el intérprete de JavaScript viendo el new palabra clave crea un nuevo objeto que actúa como el objeto de invocación (contextual this) de la función anónima apuntada por Foo. En este caso A y Bconvertirse en propiedades en el objeto recién creado (en lugar del objeto ventana). Como no tiene ninguna declaración de devolución explícita, el intérprete de JavaScript inserta a la fuerza una declaración de devolución para devolver el nuevo objeto creado debido al uso de new palabra clave.

Caso III:

var Foo = function(){
  this.A = 1;
  this.B = 2;
  return {C:20,D:30}; 
};
var bar = new Foo();
console.log(bar.C);//prints 20
console.log(bar.A); //prints undefined. bar is not pointing to the object which got created due to new keyword.

Aquí de nuevo intérprete de JavaScript viendo el new palabra clave crea un nuevo objeto que actúa como el objeto de invocación (contextual this) de la función anónima apuntada por Foo. De nuevo, A y B convertirse en propiedades en el objeto recién creado. Pero esta vez tiene una declaración explícita de devolución para que el intérprete de JavaScript lo haga no hacer algo propio.

Lo que hay que notar en el caso III es que el objeto que se crea debido a new palabra clave se perdió de su radar. bar en realidad apunta a un objeto completamente diferente que no es el que el intérprete de JavaScript creó debido a new palabra clave.


2
2018-05-13 23:05