필터 메소드를 Array에 추가하는 Mozilla 코드를 보았는데 혼란 스러웠습니다.
var len = this.length >>> 0;
>>> 전에 JavaScript에서 사용 된 적이 없습니다.
그것은 무엇이며 무엇을합니까?
Array.prototype.push
/ Array.prototype.pop
- hexmen.com/blog/2006/12/push-and-pop (그는 시험, 하하를했다하지만).
필터 메소드를 Array에 추가하는 Mozilla 코드를 보았는데 혼란 스러웠습니다.
var len = this.length >>> 0;
>>> 전에 JavaScript에서 사용 된 적이 없습니다.
그것은 무엇이며 무엇을합니까?
Array.prototype.push
/ Array.prototype.pop
- hexmen.com/blog/2006/12/push-and-pop (그는 시험, 하하를했다하지만).
답변:
숫자가 아닌 숫자를 숫자로 변환하는 것이 아니라 부호없는 32 비트 정수로 표현할 수있는 숫자로 변환합니다.
자바 스크립트의 숫자가 배정 밀도 수레 (*)는 비트 연산자가 있지만 ( <<
, >>
, &
, |
및~
)는 32 비트 정수에 대한 운영의 관점에서 정의된다. 비트 단위 연산을 수행하면 계산을 수행 한 다음 숫자로 다시 변환하기 전에 숫자를 32 비트 부호있는 정수로 변환하여 32보다 작은 분수와 상위 비트를 잃게됩니다.
따라서 0 비트의 오른쪽 이동과 같이 실제 효과없이 비트 단위 연산을 수행하면 >>0
숫자를 반올림하여 32 비트 int 범위에있게됩니다. 또한 삼항 >>>
연산자는 부호없는 연산을 수행 한 후 계산 결과를 다른 사람이하는 부호있는 정수가 아닌 부호없는 정수로 Number로 변환하므로 음수를 32 비트 2의 보수로 변환하는 데 사용할 수 있습니다. 큰 숫자로 버전. 를 사용 >>>0
하면 0에서 0xFFFFFFFF 사이의 정수를 사용할 수 있습니다.
이 경우 ECMAScript는 32 비트 부호없는 정수로 배열 인덱스를 정의하기 때문에 유용합니다. 따라서 array.filter
ECMAScript Fifth Edition 표준의 내용을 정확하게 복제하는 방식 으로 구현하려는 경우 숫자를 32 비트 부호없는 int로 캐스트합니다.
(실제로는 거의 실제적인 필요성이 거기의 희망 사람들이 설정 될 수 없습니다 등 array.length
으로 0.5
, -1
, 1e21
또는 'LEMONS'
.하지만 당신은 모르실 있도록이, 우리는 약을 얘기 자바 스크립트 저자는 ...)
요약:
1>>>0 === 1
-1>>>0 === 0xFFFFFFFF -1>>0 === -1
1.7>>>0 === 1
0x100000002>>>0 === 2
1e21>>>0 === 0xDEA00000 1e21>>0 === -0x21600000
Infinity>>>0 === 0
NaN>>>0 === 0
null>>>0 === 0
'1'>>>0 === 1
'x'>>>0 === 0
Object>>>0 === 0
(* : 그것들은 플로트처럼 행동하는 것으로 정의되어 있습니다. 일부 JavaScript 엔진은 성능상의 이유로 가능할 때 실제로 int를 사용했다고해도 놀라지 않을 것입니다. 의 장점.)
RangeError: invalid array length
.
Array.prototype.filter.call
)에서 호출 되도록 허용하므로 array
실제로는 실제가 Array
아닐 수도 있습니다. 다른 사용자 정의 클래스 일 수 있습니다. (안타깝게도, 그것은 호스트 객체이기 때문에 실제로 그렇게하고 싶을 때 NodeList가 될 수는 없습니다. arguments
의사 배열 로 현실적으로 할 수있는 유일한 장소는 남겨 둡니다 .)
if
평가의 왼쪽이 정수가 아님을 식별하려고 할 때 진술의 내용은 무엇 입니까? 'lemons'>>>0 === 0 && 0 >>>0 === 0
사실로 평가? 레몬은 분명히 한마디지만 ..?
부호없는 오른쪽 이동 연산자는 속성이 부호없는 32 비트 정수임 을 보장하기 위해 Mozilla 의 모든 배열 여분의 메소드 구현에 사용됩니다.length
됩니다.
length
배열 객체 의 속성은 사양에서 다음과 같이 설명 됩니다.
모든 Array 객체에는 값이 항상 2 32 미만의 음이 아닌 정수인 length 속성이 있습니다.
이 연산자는 가장 짧은 방법이며 내부 배열 방법은 ToUint32
조작을 하지만 해당 메소드는 액세스 할 수 없으며 구현 목적으로 스펙에 존재합니다.
Mozilla 배열 엑스트라 구현은 ECMAScript 5를 준수 하려고 시도 합니다.Array.prototype.indexOf
방법 (§ 15.4.4.14)을보십시오.
1. O가 this 값을 전달하는 ToObject를 호출 한 결과로 둡니다. 논쟁으로. 2. lenValue가 O의 [[Get]] 내부 메소드를 호출 한 결과가되게하십시오. "길이"인수 3. len하자 ToUint32 (lenValue)로 설정하십시오 . ....
보시다시피 ToUint32
ES3 구현에서 ES5 사양을 준수하기 위해 메소드 의 동작을 재현하기를 원합니다. 앞에서 말했듯이 부호없는 오른쪽 시프트 연산자 가 가장 쉬운 방법입니다.
ToUint32
나에게는 약간 불필요 해 보인다.
Array.prototype
메소드는 의도적으로 일반적 이라는 것을 명심하십시오 . 예를 들어, 배열과 같은 객체 에 사용될 수 있습니다 Array.prototype.indexOf.call({0:'foo', 1:'bar', length: 2}, 'bar') == 1;
. arguments
객체는 좋은 예입니다. 들어 순수 배열 객체는 유형 변경하는 것은 불가능 length
그들이 특별한 구현하기 때문에, 속성을 [Put
할당이 이루어집니다] 내부 메서드 및 length
속성을 다시 변환되어 ToUint32
다른 조치는 위의 인덱스를 삭제 등, 촬영 새로운 길이 ...
이것이 부호없는 오른쪽 비트 시프트 연산자입니다. 이것과 부호있는 오른쪽 비트 시프트 연산자 의 차이점 은 부호없는 오른쪽 비트 시프트 연산자 ( >>> )가 왼쪽에서 0으로 채워지고 부호있는 오른쪽 비트 시프트 연산자 ( >> )가 부호 비트로 채워진다는 것입니다 이동할 때 숫자 값의 부호를 유지합니다.
>>>
정수 +
가 아닌 정수로 변환합니다 .
디리스 는 운영자가 무엇이며 무엇을 하는지를 충분히 설명했습니다. 그 의미는 다음과 같습니다 / 사용 된 이유 :
원하는 방향을 이동하는 것은 0
반환에게 원래의 번호를 수행하고 주조 할 것이다 null
에 0
. 당신이보고있는 예제 코드 가 숫자 인 경우에도 숫자 this.length >>> 0
임을 확인하는 데 사용 하는 것 같습니다len
this.length
는 정의되지 않은 .
많은 사람들에게 비트 단위 연산은 불분명합니다 (더글러스 크로포드 / jslint는 그러한 것들을 사용하지 말 것을 제안합니다). 그렇다는 것이 잘못되었다는 것을 의미하는 것은 아니지만 코드를 더 읽기 쉽게 만드는 더 유리하고 친숙한 방법이 있습니다. 그 보장하기 위해 더 명확한 방법 len
이다는 0
다음 두 가지 방법 중 하나입니다.
// Cast this.length to a number
var len = +this.length;
또는
// Cast this.length to a number, or use 0 if this.length is
// NaN/undefined (evaluates to false)
var len = +this.length || 0;
NaN
.. 예 +{}
... 그것은이 결합하는 것이 가장입니다+length||0
>>>
는 IS 부호 오른쪽 시프트 연산자 ( 페이지. 자바 스크립트 1.5 사양의 76 )에 반대로 >>
상기 서명 오른쪽 시프트 연산자.
>>>
음수를 이동 하면 부호 비트가 유지되지 않으므로 음수를 이동 한 결과가 변경 됩니다 . 이것의 결과는 예를 들어 해석기에서 이해할 수 있습니다.
$ 1 >> 0
1
$ 0 >> 0
0
$ -1 >> 0
-1
$ 1 >>> 0
1
$ 0 >>> 0
0
$ -1 >>> 0
4294967295
$(-1 >>> 0).toString(16)
"ffffffff"
$ "cabbage" >>> 0
0
따라서 여기서 수행하려는 것은 길이를 가져 오거나 "cabbage"
위 의 예에 따라 길이가 정의되지 않았거나 정수가 아닌 경우 0을 얻는 것 입니다. 나는이 경우 this.length
결코 없을 것이라고 가정하는 것이 안전하다고 생각 한다 < 0
. 그럼에도 불구하고, 나는 이 예제가 두 가지 이유로 불쾌한 핵 이라고 주장합니다 .
<<<
음수 를 사용할 때 의 동작으로 , 위의 예에서 부작용이 발생하지 않았을 수 있습니다.
이 질문의 존재가 확인하기 때문에 코드의 의도는 분명하지 않습니다 .
모범 사례는 성능이 절대적으로 중요하지 않은 한 더 읽기 쉬운 것을 사용하는 것입니다.
isNaN(parseInt(foo)) ? 0 : parseInt(foo)
-1 >>> 0
언제라도 일어날 수 있습니까? 그렇다면 4294967295로 바꾸는 것이 정말 바람직합니까? 이로 인해 루프가 필요한 것보다 몇 번 더 실행될 수 있습니다.
this.length
알 수 없습니다. "sane"구현의 경우 문자열 길이는 음수가 아니어야하지만 "sane"환경에서는 this.length
항상 정수를 반환하는 속성이 있다고 가정 할 수 있습니다 .
두 가지 이유 :
>>>의 결과는 "통합"입니다
undefined >>> 0 = 0 (JS가 LFS를 숫자 컨텍스트로 강제 변환하려고 시도하기 때문에 "foo"에서 작동합니다. >>> 0 등)
JS의 숫자는 내부 표현이 double이라는 것을 기억하십시오. 그것은 길이에 대한 기본적인 입력 상태의 "빠른"방법입니다.
그러나 -1 >>> 0 (원하는 길이가 아닐 수도 있습니다!)
아래 샘플 Java 코드가 잘 설명되어 있습니다.
int x = 64;
System.out.println("x >>> 3 = " + (x >>> 3));
System.out.println("x >> 3 = " + (x >> 3));
System.out.println(Integer.toBinaryString(x >>> 3));
System.out.println(Integer.toBinaryString(x >> 3));
출력은 다음과 같습니다.
x >>> 3 = 536870904
x >> 3 = -8
11111111111111111111111111000
11111111111111111111111111111000