2017-12-27 51 views
0

제품을 설명하는 색상 및 브랜드와 같은 속성이 무수히 많은 객체가 있습니다. 나는 단락 형태로 제품 설명을 동적으로 생성하는 방법을 찾고 있는데 (API가 제공하지 않기 때문에), 괄호 안에 "소품"이있는 "템플릿"을 작성하는 방법을 생각해 냈다 {{}}. 필자는 "props"를 키 값으로 대체하여 문자열에 객체 속성을 주입하여 템플릿을 "파싱"하는 함수를 작성했습니다. 예를 들어JavaScript : .exec()와 연속 일치 찾기

:

대상 : {color: 'white'}

템플릿 : "The bowl is {{color}}."

결과 : "The bowl is white." 어떤 이유

, 내 구문 분석 기능이 작동하지 않습니다. {{general_description}}은 구문 분석되지 않습니다.

var obj = { 
 
    brand: "Oneida", 
 
    general_description: "Plate", 
 
    material: "China", 
 
    color: "Bone White", 
 
    product_width: "5\"" 
 
}; 
 

 
const templatePropRe = /{{(\w*)}}/g; 
 
const parse = (template) => { 
 
    while ((result = templatePropRe.exec(template)) !== null) { 
 
    let match = result[0], 
 
     key = result[1]; 
 
    template = template.replace(match, obj[key]); 
 
    } 
 
    return template; 
 
} 
 

 
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));

는 I 연속 매치를 찾기> 예 MDN docs 아래에 제공된 예를 따랐다. 정규 표현식을 변수 (예 : templatePropRe)에 먼저 저장해야합니다. 표현식은 while 루프 조건에있을 수 없거나 무한정 반복됩니다. 그러나, 내가 그렇게하면 내 문제가 해결됩니다. here ... 아무 것도 부러지지 말아라.

String.prototype.match을 사용하여 함수를 다시 작성했지만 예상대로 작동하지만 캡처에 액세스 할 수 없으므로 먼저 stripBrackets을 사용하여 대괄호를 제거해야합니다. 작업 예제는 matchhere을 사용하십시오.

내가 알고 싶은 것은 왜 parse()RegExp.prototype.exec을 사용하는 기능이 제대로 작동하지 않는 것입니까?

+1

내 [단일 패스 접근법] (https://stackoverflow.com/a/47990731/3832970)을 확인하십시오. –

답변

1

정규식에서 /g 플래그를 제거하십시오. documentation에 따르면이 플래그가 있으면 정규식 개체 lastIndex 속성을 업데이트하여 exec()에 대한 다음 호출에서 일치하는 항목을 검색 할 위치를 나타냅니다. 수정 및 코드에서 동일한 문자열을 확인하기 때문에

1

var obj = { 
 
    brand: "Oneida", 
 
    general_description: "Plate", 
 
    material: "China", 
 
    color: "Bone White", 
 
    product_width: "5\"" 
 
}; 
 

 
const templatePropRe = /{{(\w*)}}/; 
 
const parse = (template) => { 
 
    while ((result = templatePropRe.exec(template)) !== null) { 
 
    let match = result[0], 
 
     key = result[1]; 
 
     
 
    template = template.replace(match, obj[key]); 
 
    } 
 
    
 
    return template; 
 
} 
 

 
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));

일어났다. 반면에 regExp는 매번 실행 한 후에 일치하는 부분 문자열의 인덱스를 저장합니다. 문자열의 길이를 변경하면 다음 실행으로 regEx가 예상보다 다른 시점에서 시작됩니다. 대신 (일치하는 항목을 찾아 다음 필요한 값을 첫 번째 항목을 대체하는) 2 단계 교체를 수행

var obj = { 
 
    brand: "Oneida", 
 
    general_description: "Plate", 
 
    material: "China", 
 
    color: "Bone White", 
 
    product_width: "5\"" 
 
}; 
 

 
const templatePropRe = /{{(\w*)}}/g; 
 
const parse = (template) => { 
 
    var resultStr = template; 
 
    while ((result = templatePropRe.exec(template)) !== null) { 
 
    let match = result[0], 
 
     key = result[1]; 
 
    resultStr = resultStr.replace(match, obj[key]); 
 
    } 
 
    return resultStr; 
 
} 
 

 
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));

1

(즉 새로운 발생한 같은 문제가있는 경향이있다 문자열이 기존 RegExp에 이미 유효하지 않은 색인으로 전달 된 경우) callback method as a replacement argument inside a String#replace method을 사용할 수 있습니다. 그런 식으로 결과 문자열은 각 일치시 즉시 작성되어 코드가 더 빠르게 실행됩니다.

하는 것은 예를 아래에 고정 참조 : 일치를 발견 한 후, ($0, $1) => obj[$1] ? obj[$1] : $0 코드는 다음 작업을 수행합니다 여기,

var obj = { 
 
    brand: "Oneida", 
 
    general_description: "Plate", 
 
    material: "China", 
 
    color: "Bone White", 
 
    product_width: "5\"" 
 
}; 
 
const parse = (template) => { 
 
    return template.replace(/{{(\w*)}}/g, ($0, $1) => obj[$1] ? obj[$1] : $0); 
 
    // ES5 way: 
 
    // return template.replace(/{{(\w*)}}/g, function($0, $1) { 
 
    //  return obj[$1] ? obj[$1] : $0; 
 
    // }); 
 
} 
 

 
console.log(parse('{{keep}} This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));

참고 : 전체 일치 $0 변수와 그룹에 할당 1 값은 $1에 할당됩니다. 그런 다음 $1이라는 이름의 키가 obj에있는 경우 결과 문자열의 올바른 위치에 값이 입력됩니다. 그렇지 않으면 일치 항목 전체가 되돌아갑니다 (존재하지 않는 키 이름이있는 {{...}}을 제거하려면 ''으로 바꿉니다).

+0

나는 내가 한 짓보다이게 낫다. 나는 이것을 대신 사용할 것이다. - 감사합니다! – Matthew