Wpis z mikrobloga

#javascript #pytanie

var foo = new Number(1);
foo.bar = 2;

// foo = 3;
// foo = Number(3);
// foo = new Number(3);

document.writeln('<pre>');

document.writeln('typeof foo = ' + typeof foo);
document.writeln('foo = ' + foo);
document.writeln('foo.bar = ' + foo.bar);

document.writeln('</pre>');

Jak zmienić wartość zmiennej foo typu Object, tak żeby nie stracić wartości przypisanej do właściwości bar obiektu foo.
Odkomentowane jednej z powyższych zakomentowanych linii powoduje utratę wartości dla foo.bar (undefined).

PS. Pytanie z czystej ciekawości (nie jest mi to potrzebne);
  • 10
@wasmaro: bardzo ciekawe pytanie. Nie jest mi znany i chyba nie ma (ale musiałbym to potwierdzić w specyfikacji) żadnego sposobu na zmianę [[Value]] (czyli wartości przechowywanej pod spodem number wrappera) bez modyfikowania referencji. Jest tylko trik żeby to obejść, tzn. jeśli zrobisz

foo.valueOf = () => 3;
to foo będzie udawać że ma wartość 3 (mimo że tak naprawdę pod spodem będzie mieć 2), tym samym nie stracisz swojej referencji.

@NietypowyRumunskiNiedzwiedz: jeśli ktoś by mi zadał takie pytanie i nie byłaby to rekrutacja np. do Google, na stanowisko eksperta ds. implementacji EcmaScriptu w Chrome, to bym sobie pomyślał, że chyba żartują :)

aczkolwiek nie da się ukryć, że jeśli ktoś jest w stanie odpowiedzieć na takie pytanie, to raczej od razu wiadomo, że w ES jest ekspertem.
foo.valueOf = () => 3;

to foo będzie udawać że ma wartość 3 (mimo że tak naprawdę pod spodem będzie mieć 1), tym samym nie stracisz swojej referencji.


@Marmite: No bardzo ciekawy sposób (przy okazji poznałem tzw. funkcje strzałkowe).
Czyli jeśli foo będzie już miało tą udawaną wartość 3, to da się później jakoś odczytać tę rzeczywiście przechowywaną pod spodem wartość, czyli 1 z przykładu?
@wasmaro: nie pisałeś o przywróceniu, tylko o odczytaniu. Number.prototype.valueOf.call(foo); odczyta oryginalną wartość, bo po prostu zignoruje funkcję valueOf, którą dodałeś na foo. Natomiast żeby "przywrócić" oryginalną wartość to musisz faktycznie tę funkcję usunąć