문제 설명
JavaScript의 분할 메소드를 사용하여 문자열을 분할 때, 특히 정규 표현식을 구속기로 사용할 때 일부 빈 문자열 ""이 나타납니다.
관련 질문
JavaScript 정규식은 문자열을 그룹화 할 때 빈 문자열 그룹을 생성합니까?
위의 질문에서, 질문자는 정규 표현식을 사용하여 문자열을 분할하고 여러 개의 빈 문자열을 생성하고 코드는 다음과 같습니다.
코드 사본은 다음과 같습니다.
'Zhang SDF 4 가지 방법 ASDF wengf aa33net s'.split (/([/u4e00-/u9fa5] {1})/gi);
// output [ "", "Zhang", "SDF", "Four", "Up", "", "Law", "Asdf", "weng", "", "", "Fen", "aa33", "net", "s"]]]]
그렇다면이 빈 줄의 이유는 무엇입니까?
문제 분석
Google을 검색 한 후 관련 결과가 많지 않다는 것을 알았습니다. 있더라도 자세한 설명은 많지 않았습니다. 나는 대략적으로 말한 다음 ecmascript 사양에 대한 링크를 제공했습니다. 진짜 이유를 알고 싶다면 총알을 물고 규범을 볼 수 있습니다.
관련 표준
그런 다음 국제 실무에 따르면 먼저 ECMAScript의 표준 타운 빌딩으로 이동하십시오.
코드 사본은 다음과 같습니다.
string.prototype.split (분리기, 한계)
이 장에서는 분할 방법의 실행 단계를 자세히 소개합니다. 관심이 있으시면 단계별로주의 깊게 읽을 수 있습니다. 여기서 빈 줄을 생성하는 것과 관련된 단계 만 설명하겠습니다. 부적절한 요점이 있으면 모든 사람이 언급 할 수 있습니다.
관련 단계
추출하는 부분 단계 :
전체 과정에서 가장 중요한 단계는 13 번째주기이며,이주기의 주요 일은 다음과 같습니다.
• P 및 Q의 값을 정의합니다. p와 q의 값은 각 루프의 시작 부분에서 동일합니다 (이 단계는 루프 외부).
• 문자열을 분할하려면 splitmatch (s, q, r) 메소드를 호출하십시오.
• 반환 된 결과에 따라 다른 지점을 실행하고 주요 지점은 지점입니다.
• 지점은 8 개의 작은 단계로 나뉘어 리턴 된 결과를 미리 정의 된 배열로 채 웁니다.
•이 8 단계에서 1 단계의 목적은 원래 문자열의 하위 문자열을 반환하는 것입니다. 시작 위치는 P (포함)이고 종료 위치는 Q (포함)입니다. 참고 :이 단계에서는 빈 문자열이 생성되며 아래에 인용 할 수있는 편의성을 위해 문자열을 가로 채는 것으로 표시했습니다.
• 이전 단계에서 배열에 하위 문자열을 추가합니다.
• 다음 몇 단계는 관련 변수를 업데이트하고 다음 루프를 계속하는 것입니다. (7 단계의 목적은 정규 표현식의 캡처 그룹을 배열 A로 저장하는 것입니다.
splitmatch (s, q, r)
다음으로 SplitMatch (S, Q, R) 메소드가 무엇을하는지 이해해야합니다. 이 방법은 아래 분할 사양에 언급되어 있습니다. 주로하는 일은 분리기 유형에 따라 해당 작업을 수행하는 것입니다.
• Delimiter가 regexp 유형 인 경우 문자열과 일치하도록 Regexp의 내부 메소드 [[Match]]를 호출하십시오. 경기가 실패하면 반환 실패. 그렇지 않으면 MatchResult 결과를 반환하십시오.
• 구분 기호가 문자열 인 경우 일치 판단이 수행되고 실패가 반환되며 MatchResult 유형의 결과가 성공적으로 반환됩니다.
matchresult
위의 단계에서는 유형 MatchResult의 변수가 도입됩니다. 문서를 살펴보면이 유형의 변수에는 EndIndex와 캡처가있는 두 가지 속성이 있음이 밝혀졌습니다. endIndex의 값은 문자열과 1과 일치하는 위치입니다. 캡처는 배열로 이해 될 수 있습니다. 구분자가 정규 표현 일 때, 그 내부의 요소는 그룹이 캡처 한 값입니다. 구분 기자가 문자열 일 때는 빈 배열입니다.
다음
위의 단계에서 스플릿 문자열이 문자열을 가로 채는 단계에서 생성되는 것을 볼 수 있습니다 (정규 표현식의 그룹 캡처 제외). 그 기능은 지정된 시작 (포함)과 종료 위치 (포함) 사이의 문자열을 가로 채는 것입니다. 언제 "" "? 사양이 문자열을 가로 채기위한 사양 단계를 제공하지 않기 때문에 시작 위치와 종료 위치의 값이 동일하는 특별한 경우가 있습니다.
우리는 모두 여기에 왔습니다. 왜 한 걸음 앞으로 나아 가지 않습니까?
따라서 특정 구현 방법을 찾을 수 있는지 확인하기 위해 V8 소스 코드를 검색하려고했습니다. 관련 코드, 소스 코드 링크를 찾았습니다
그중 일부는 다음과 같습니다.
코드 사본은 다음과 같습니다.
함수 stringsplitjs (분리기, 한계) {
...
...
// 구분 기자는 문자열입니다
if (! is_regexp (분리기)) {
var segrecator_string = to_string_inline (분리기);
if (limit === 0) 반환 [];
// ECMA-262는 분리기가 정의되지 않은 경우 결과는
// 전체 문자열을 포함하는 크기 1 배열 1입니다.
if (is_undefined (분리기)) 반환 [주제];
var segrecator_length = sequelator_string.length;
// 분리기는 빈 문자열이며 문자 배열을 직접 반환합니다.
if (separator_length === 0) return %stringtoArray (주제, 한계);
var result = %stringsplit (대상, separator_string, limit);
반환 결과;
}
if (limit === 0) 반환 [];
// Delimiter가 정규 표현식 인 경우 stringsplitonRegexp를 호출하십시오.
return stringsplitonregexp (주제, 분리기, 한계, 길이);
}
// 여기에서 여러 코드가 생략됩니다
코드에서 배열을 채울 때 문자열을 가로 채기 위해 %_substring 메소드가 호출되는 것을 발견했습니다. 불행히도, 나는 그 관련 정의를 찾지 못했습니다. 그것을 찾은 학생들이 있다면 알려주세요. 그러나 JavaScript의 하위 문자열 방법에 해당하는 문자열 서브 스트링 방법이 %_SubString 방법을 호출하여 결과를 반환한다는 것을 발견했습니다. 그런 다음 'abc'.substring (1,1)이 반환되면 "" ""시작 위치와 종료 위치가 동일 할 때 %_substring 메소드가 반환된다는 것을 의미합니다. 시도해 보면 결과를 알 수 있습니다.
그렇다면 언제 시작 위치가 종료 위치와 같을까요 (즉, Q === P)가 발생합니까? 위의 단계를 단계별로 따라 마침내 찾았습니다.
• 원래 문자열 S가 구분 기호와 일치하면 즉시 문자열 S의 다음 위치도 구분 기와 일치합니다. 예를 들어 : 'abbbc'.split ('b '),'abbbc'.split (/(b) {1}/)
• 또 다른 경우는 문자열의 시작 부분에서 하나 또는 여러 문자가 분리기와 일치한다는 것입니다. 예를 들어 : 'abc'.split ('a '),'abc'.split (/ab/)
• 문자열 끝에 하나 또는 여러 개의 문자열이 구분 기호와 일치하고 관련 단계가 14 단계 인 경우가 있습니다.
예를 들어 : 'abc'.split ('c '),'abc'.split (/bc/)
또한, 정규 표현식을 구분 제로 사용하면 반환 된 결과에 정의되지 않은 결과가 나타날 수 있습니다.
예를 들어 : 'abc'.split (/(d)*/)
처음의 예를 살펴 보겠습니다. 위의 상황을 만족합니까?
주제에서
ECMAScript의 표준 사양을 신중하게 읽은 것은 이번이 처음입니다. 독서 과정은 실제로 매우 고통 스럽지만 이해 한 후에는 매우 행복합니다. 이 질문과 후속 질문에 감사드립니다.
그건 그렇고, 정규 표현이 분리기로 사용될 때, 글로벌 수정 자 G는 무시 될 것이며, 이는 또한 추가 이득입니다.