javascript - usada - ¿Qué valores puede devolver un constructor para evitar devolver esto?
retornar valor javascript para html (5)
Como nota al margen, el valor de retorno o this
es solo parte de la ecuación.
Por ejemplo, considera esto:
function Two() { return new Number(2); }
var two = new Two;
two + 2; // 4
two.valueOf = function() { return 3; }
two + 2; // 5
two.valueOf = function() { return ''2''; }
two + 2; // ''22''
Como puede ver, .valueOf()
se usa internamente y se puede explotar por diversión y beneficio. Incluso puede crear efectos secundarios, por ejemplo:
function AutoIncrementingNumber(start) {
var n = new Number, val = start || 0;
n.valueOf = function() { return val++; };
return n;
}
var auto = new AutoIncrementingNumber(42);
auto + 1; // 43
auto + 1; // 44
auto + 1; // 45
Puedo imaginar que esto debe tener algún tipo de aplicación práctica. Y tampoco tiene que ser explícitamente un Number
, si agrega .valueOf
a cualquier objeto, puede comportarse como un número:
({valueOf: function() { return Math.random(); }}) + 1; // 1.6451723610516638
Puede explotar esto para crear un objeto que siempre devuelva un nuevo GUID, por ejemplo.
¿Cuáles son las circunstancias exactas para las cuales una declaración de retorno en Javascript puede devolver un valor distinto a this
cuando se invoca un constructor con la new
palabra clave?
Ejemplo:
function Foo () {
return something;
}
var foo = new Foo ();
Si no me equivoco, si something
es una primitiva no funcional, se devolverá. De something
contrario, se devuelve something
. ¿Es esto correcto?
IOW, ¿qué valores puede llevar something
a causar (new Foo () instanceof Foo) === false
?
Cuando usa la palabra clave new
, se crea un objeto. Luego se llama a la función para inicializar el objeto.
No hay nada que la función pueda hacer para evitar que se cree el objeto, ya que eso se hace antes de que se llame a la función.
Ejemplos concretos http://jsbin.com/zivivucahi/1/edit?html,js,console,output
/*
ECMA 262 v 5
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
"4.3.2
primitive value
member of one of the types Undefined, Null, Boolean, Number, Symbol, or String as defined in clause 6"
*/
var Person = function(x){
return x;
};
console.log(Person.constructor);
console.log(Person.prototype.constructor);
console.log(typeof(Person));
console.log(typeof(Person.prototype));
function log(x){
console.log(x instanceof Person);
console.log(typeof x);
console.log(typeof x.prototype);
}
log(new Person(undefined));
log(new Person(null));
log(new Person(true));
log(new Person(2));
log(new Person(""));
//returns a function not an object
log(new Person(function(){}));
//implementation?
//log(new Person(Symbol(''%'')));
La condición exacta se describe en la propiedad interna [[Construct]]
, que utiliza el new
operador:
Del ECMA-262 3ro. Especificación de la edición:
13.2.2
[[Construct]]
Cuando se llama a la propiedad
[[Construct]]
para un objeto deFunction
F
, se realizan los siguientes pasos:
- Crea un nuevo objeto ECMAScript nativo.
- Establezca la propiedad
[[Class]]
delResult(1)
en"Object"
.- Obtenga el valor de la propiedad prototipo de
F
- Si
Result(3)
es un objeto, establezca la propiedad[[Prototype]]
delResult(1)
enResult(3)
.- Si el
Result(3)
no es un objeto, establezca la propiedad[[Prototype]]
delResult(1)
en elObject
prototipo del objeto original como se describe en 15.2.3.1 .- Invoque la propiedad
[[Call]]
deF
, proporcionando elResult(1)
comothis
valor y proporcionando la lista de argumentos pasada a[[Construct]]
como los valores del argumento.- Si
Type (Result(6))
esObject
entonces devuelveResult(6)
.Result(1)
devoluciónResult(1)
.Observe los pasos 7 y 8, el nuevo objeto se devolverá solo si el tipo de
Result(6)
(el valor devuelto por la función del constructorF
) no es un Objeto.
No pude encontrar ninguna documentación sobre el asunto, pero creo que estás en lo correcto. Por ejemplo, puede devolver un new Number(5)
desde un constructor, pero no el literal 5
(que se ignora y se devuelve en su lugar).