>  기사  >  웹 프론트엔드  >  JavaScript가 string_javascript를 분할할 때 생성되는 null 문자에 대한 솔루션 팁

JavaScript가 string_javascript를 분할할 때 생성되는 null 문자에 대한 솔루션 팁

WBOY
WBOY원래의
2016-05-16 16:35:131618검색

문제 설명

JavaScript의 분할 메소드를 사용하여 문자열을 분할할 때, 특히 정규 표현식을 구분 기호로 사용할 때 일부 빈 문자열 ""이 나타납니다.

관련 질문

문자열을 그룹화할 때 Javascript 정규 표현식이 빈 문자열 그룹을 생성합니까?

위 질문에서 피험자가 문자열을 분할하기 위해 정규식을 사용했을 때 여러 개의 빈 문자열 ""이 생성되었습니다. 코드는 다음과 같습니다.

코드 복사 코드는 다음과 같습니다.

'张sdf4상법asdfwengfenaa33网s'.split(/([u4e00-u9fa5]{1})/gi);
//출력 ["", "张", "sdf", "4", "", "上", "", "법", "asdf", "王", "", "fen", "aa33 ", "网", "s"]

그렇다면 이렇게 빈 문자열이 있는 이유는 무엇일까요?

문제 분석

구글에서 검색해 보니 관련 결과도 많지 않고, 있다고 해도 자세한 설명이 많지 않은 것 같아서 간략하게 소개를 한 뒤 ECMAScript 스펙에 대한 링크를 걸어 드렸습니다. 진짜 이유를 알고 싶으면 일단 짚고 넘어가서 규정을 읽어봐야 할 것 같습니다.

관련기준

그럼 다음은 국제 관례에 따라 ECMAScript의 표준 타운홀부터 시작하겠습니다.

코드 복사 코드는 다음과 같습니다.

String.prototype.split(구분자, 제한)

이 장에서는 분할 방법의 실행 단계를 자세히 소개합니다. 관심이 있으시면 단계별로 주의 깊게 읽으십시오. 여기서는 부적절할 경우 빈 문자열 생성과 관련된 단계만 설명하겠습니다. 모두가 제안을 환영합니다.

관련 단계

몇 가지 단계 추출:

전체 과정에서 가장 중요한 단계는 13단계의 주기이며, 이 주기가 수행하는 주요 작업은 다음과 같습니다.
•p와 q의 값을 정의합니다. 각 루프의 시작 부분에서 p와 q의 값이 동일합니다(이 단계는 루프 외부에 있음). • 문자열을 분할하려면 SplitMatch(S, q, R) 메서드를 호출하세요.
• 반환된 다양한 결과에 따라 다양한 분기가 실행되며 주요 분기는 ⅲ 분기입니다. •분기 ⅲ는 8개의 작은 단계로 나누어 반환된 결과를 미리 정의된 배열 A
에 채웁니다. •이 8개의 작은 단계에서 1단계의 기능은 원래 문자열의 하위 문자열을 반환하는 것입니다. 시작 위치는 p(포함)이고 끝 위치는 q(포함되지 않음)입니다. 참고: 이 단계에서 빈 문자열은 다음과 같습니다. 아래에서 쉽게 참조할 수 있도록 잘린 문자열로 표시했습니다.
• 이전 단계의 하위 문자열을 배열 A에 추가
•다음 몇 단계는 관련 변수를 업데이트하고 다음 주기를 계속하는 것입니다. (7단계의 기능은 정규식의 캡처 그룹을 배열 A에 저장하는 것이며 빈 문자열 생성과는 아무런 관련이 없습니다)

SplitMatch(S, q, R)

다음으로 SplitMatch(S, q, R) 메서드의 기능을 이해해야 합니다. 이 방법은 분할 사양에서 더 자세히 언급됩니다. 주로 하는 일은 구분 기호 유형에 따라 해당 작업을 수행하는 것입니다.

•구분자가 RegExp 유형인 경우 RegExp의 내부 메소드 [[Match]]를 호출하여 일치에 실패하면 실패가 반환됩니다. 그렇지 않으면 MatchResult 유형의 결과가 반환됩니다.

• 구분자가 문자열인 경우 일치 여부를 판단하여 실패를 반환하며, MatchResult 형태의 결과를 성공적으로 반환한다.

경기결과

위 단계에서는 MatchResult 유형의 또 다른 변수를 소개합니다. 문서를 확인하여 이러한 유형의 변수에는 endIndex와 캡처라는 두 가지 속성이 있음을 발견했습니다. endIndex의 값은 문자열 일치 위치에 1을 더한 것입니다. 캡처는 구분 기호가 정규 표현식인 경우 요소로 이해될 수 있습니다. 그 안에는 그룹에서 캡처한 값이 있습니다. 구분 기호가 문자열이면 빈 배열입니다.

다음

위의 단계를 보면 문자열을 가로채는 단계에서 분할된 문자열이 생성되는 것을 볼 수 있습니다(정규식의 그룹 캡처는 제외). 그 기능은 지정된 시작(포함)과 끝 위치(포함되지 않음) 사이의 문자열을 가로채는 것입니다. 그러면 언제 ""를 반환합니까? 시작 위치와 끝 위치의 값이 동일한 특별한 경우가 있습니다. 이는 사양에서 문자열을 가로채기 위한 표준 단계를 제공하지 않기 때문에 단지 추측일 뿐입니다.

여기까지 왔는데, 한발 더 나아가보면 어떨까요?

그래서 구체적인 구현 방법을 찾을 수 있는지 알아보기 위해 V8 소스 코드를 검색해 보았습니다. 관련 코드, 소스 코드 링크를 찾았습니다

다음은 그중 하나를 발췌한 것입니다.


코드 복사 코드는 다음과 같습니다.

함수 StringSplitJS(구분자, 제한) {
...
...
//구분자가 문자열인 경우
if (!IS_REGEXP(구분자)) {
var Separator_string = TO_STRING_INLINE(구분자);

if (한계 === 0) return [];

// ECMA-262에서는 구분 기호가 정의되지 않은 경우 결과가 다음과 같아야 한다고 말합니다.
// 전체 문자열을 포함하는 크기 1의 배열입니다.
(IS_UNDEFINED(구분자))인 경우 [제목]을 반환합니다.

var 분리_길이 = 분리_문자열.길이;

//구분자는 빈 문자열이고 문자 배열이 직접 반환됩니다.
If (separator_length === 0) return %StringToArray(subject,limit);

var 결과 = %StringSplit(제목, 구분 기호_문자열, 제한);

결과 반환;
}

if (한계 === 0) return [];

// 구분자가 정규식인 경우 StringSplitOnRegExp를 호출합니다
Return StringSplitOnRegExp(제목, 구분 기호, 제한, 길이);
}

//여기서 일부 코드는 생략하세요

배열을 채울 때 문자열을 가로채기 위해 %_SubString 메서드가 호출되는 코드를 발견했습니다. 안타깝게도 해당 정의를 찾지 못했다면 알려주세요. 그런데 JavaScript의 substring 메서드에 해당하는 StringSubstring 메서드가 %_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가 무시되므로 추가적인 이점이 있습니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.