• 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?

Object Storage Arubacloud
+1 głos
588 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ź 143 wizyt
0 głosów
1 odpowiedź 276 wizyt
pytanie zadane 22 września 2022 w PHP przez NoteDS Użytkownik (560 p.)
0 głosów
2 odpowiedzi 155 wizyt
pytanie zadane 7 października 2023 w PHP przez Piotrek2713 Mądrala (5,380 p.)

92,572 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 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.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...