• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Array.prototype.forEach() - w jakim celu kod tej metody zawiera operator przesunięcia bitowego?

42 Warsaw Coding Academy
+1 głos
967 wizyt
pytanie zadane 4 lutego 2017 w JavaScript przez ScriptyChris Mędrzec (190,190 p.)

Analizuję kod wbudowanej w JS metody Array.prototype.forEach(). W kodzie dostępnym na MDN jako polyfill na bazie ES5 jest takie oto wyrażenie:

// 2. Let lenValue be the result of calling the Get() internal
// method of O with the argument "length".
// 3. Let len be toUint32(lenValue).
var len = O.length >>> 0;

To jest jeden z tych rzadkich momentów, gdy mimo pisania w języku wysoko poziomowym przydało by się wiedzieć, jak coś działa na poziomie bardziej matematycznym...

Ok - nie wiem, ale podmieniając natywny forEach na ten z MDN (tak po prostu w przeglądarkowej konsoli) oraz dodając tam console.log() doszedłem do wniosku, że nie znam celu, dla którego ma tam miejsce przesunięcie bitowe. Kawałek kodu, który staram się debugować:

console.log( 'O: ', O, ' /this: ', this );
var len = O.length >>> 0;
console.log( 'len: ', len, ' /len === O.length: ', len === O.length, ' /len == O.length: ', len == O.length );

I teraz tworzę sobie jakąś tablicę, na której wywołuję "spreparowany" Array.prototype.forEach() i nie rozumiem czym różni się wartość zmiennej len od O.length:

[1,3,5].forEach( elem => { console.log( 'elem: ', elem ); } )
// O:  [1, 3, 5]  /this:  [1, 3, 5]
// len:  3  /len === O.length:  true  /len == O.length:  true
// elem:  1
// elem:  3
// elem:  5

Tablica zawiera 3 elementy, a zmienna len, która otrzymała wynik przesunięcia bitowego z pola length, też wskazuje 3.

Zapisałem sobie jeszcze coś takiego:

3 >>> 0
// 3

A zatem wynik tego całego przesunięcia bitowego jest równy z długością tablicy. Ponadto porównanie z użyciem podwójnego jak i potrójnego operatora porównania == / === wykazało true. Jeśli tak, to po co wykonywać taką operację? Długość tablicy nie może być ujemna, nie może być wartością niecałkowitą - więc po co to stosować, skoro wynik jest równy po prostu długości tablicy?

1 odpowiedź

+2 głosów
odpowiedź 4 lutego 2017 przez niezalogowany
wybrane 23 lipca 2017 przez ScriptyChris
 
Najlepsza

 Jeśli tak, to po co wykonywać taką operację? Długość tablicy nie może być ujemna, nie może być wartością niecałkowitą

Według specyfikacji nie może być również większa niż 2^32 - 1

Może... albo nie może. W rzeczywistości to przeglądarka (a nie specyfikacja) ustala co length może, a co nie. Z tego powodu trzeba sprawdzić co tam siedzi - i w razie potrzeby sparsować do wartości zgodnej ze specyfikacją.

Zadanie? Zamienić dowolną wartość na nieujemną liczbę całkowitą mniejszą niż 2^32 (rzecz ujmując: toUint32)

Najprostsza implementacja? Przesunięcie bitowe o 0 bitów w prawo, z wypełnieniem zerami.

Stąd: O.length >>> 0

komentarz 4 lutego 2017 przez ScriptyChris Mędrzec (190,190 p.)

Faktycznie:

( Math.pow( 2, 32 ) ) >>> 0
// 0

( Math.pow( 2, 32 ) - 1 ) >>> 0
// 4294967295

( Math.pow( 2, 32 ) + 123 ) >>> 0
// 123


Czyli, stosując metodę forEach(), jeśli długość tablicy przewyższy wartość 2^32 - 1, to zostanie ona (dzięki przesunięciu bitowemu) "skrócona" do wartości, która stanowi tą nadwyżkę (jak w ostatnim przykładzie z powyższego kodu)?

Ja nie mogę stworzyć tablicy, która będzie zawierać więcej elementów niż 2^26, bo przeglądarka mi crashuje:

const arr = [];

for ( let i = 0; i < ( Math.pow( 2, 26 ) ); i++ ) {
	arr.push( i );
}
67108864

Przy próbie wypisania arr, jest crash.

A jeśli udało by się wykonać forEach() na tak dużej tablicy, to czy "skrócenie" jej do wartości, która stanowi nadwyżkę nie będzie przekłamaniem? Chcąc wykonać forEach() otrzymamy nieprawidłowe wyniki, bo przesunięcie bitowe "obetnie" nam za dużą wartość - chyba że się mylę, ale wg mnie to dziwne. Nie lepiej było by, przy za dużych wielkościach tablic, po prostu wyrzucać błąd, zamiast stosować przesunięcie bitowe?

1
komentarz 4 lutego 2017 przez niezalogowany

Krzycho92,

użyj konstruktora const arr = new Array(2**32 - 1)

raczej nie próbowałbym jej wyświetlać :v  console.log(arr.length)

komentarz 4 lutego 2017 przez ScriptyChris Mędrzec (190,190 p.)

Ok, da się stworzyć... Ale to nie odpowiedziało na moje pytanie - czy zastosowanie operatora przesunięcia bitowego nie spowoduje jakiegoś przekłamania podczas stosowania metody forEach na tablicy, której długość przekracza wspomniany limit? :)

komentarz 4 lutego 2017 przez niezalogowany
Spróbuj przekroczyć limit i spójrz w konsole
komentarz 4 lutego 2017 przez ScriptyChris Mędrzec (190,190 p.)
const arr1 = new Array(2**32) 

Uncaught RangeError: Invalid array length
    at <anonymous>:1:14

Zatem, jeśli nie ma możliwości stworzenia w JS tablicy o długości powyżej 2^32 - 1, jaki jest sens stosowania operatora przesunięcia bitowego? Moim zdaniem inny, niż obcięcie limitu - bo nie ma możliwości stworzenia tablicy o takiej długości, a zatem nie będzie tym bardziej możliwe wywołanie na niej jakiejkolwiek funkcji.

const array = [];
array.length = 2**32;

Również powoduje ten sam błąd.

1
komentarz 5 lutego 2017 przez niezalogowany

Zatem, jeśli nie ma możliwości stworzenia w JS tablicy o długości powyżej 2^32 - 1,

Wydaje mi się, że tutaj bardziej chodzi o pozbycie się śmieci typu string, null, infinity.. czy cokolwiek by tam złego trafiło z nieznanych powodów - to polyfill na ES5... nigdy nie wiadomo co mogło się dziać w takim IE6. Może atrybut length był configurable? 

Niżej w kodzie mamy while - lepiej dmuchać na zimne.

Btw - jeśli to polyfill na ES5, z założenia to co robi powinno być zgodne ze specyfikacją ES5.

Nic lepszego nie przychodzi mi do głowy.

Podobne pytania

+1 głos
1 odpowiedź 173 wizyt
0 głosów
1 odpowiedź 576 wizyt
pytanie zadane 22 września 2022 w PHP przez NoteDS Użytkownik (560 p.)
0 głosów
2 odpowiedzi 337 wizyt
pytanie zadane 7 października 2023 w PHP przez Piotrek2713 Mądrala (5,520 p.)

93,385 zapytań

142,384 odpowiedzi

322,540 komentarzy

62,745 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...