자바 스크립트 인터뷰 질문 : make [1,2,3] .sum () run

Nov 17 2020

자바 스크립트 인터뷰 질문 : 수 있도록 [1,2,3].sum()사용하지 않고 정확한 코드 실행 PrototypeObject.defineProperty, Object.defineProperties.

인터뷰 질문 이었기 때문에 작동하는 방법이 있다고 가정하고 있습니까?

모든 도움 / 지시 방향에 감사드립니다.

감사

답변

8 Dai Nov 17 2020 at 03:09

서문 : 이와 같은 질문은 누군가가 "좋은"프로그래머라는 것을 보여주지는 않습니다. 단지 더 유지하기 쉬운 코드로 이어지지 않는 언어의 트릭 에 익숙하다는 의미 일뿐 입니다. 이런 트릭을 정기적으로 사용하는 회사 나 팀에서 일하는 것을 조심해야합니다.

(그리고 내 개인 경우 : 나는 마이크로 소프트에서 SE 때 나는 차크라 자바 스크립트 엔진에 근무하고 나는 생각하고 싶다 나는 아주 잘 자바 스크립트 / ECMAScript를 알고 있고 나는 아직도이이없이 할 수있는 방법에 대해 오랫동안 생각했다 prototypeor를 사용하여 defineProperty-그래서 그들이 정답을 기대한다면 이것이 좋은 기술 면접 질문이라고 생각하지 않습니다. 그러나 이것이 면접관에게 질문하도록 유도하기위한 면접 질문이라면 그것은 다릅니다).


옵션 1 : 전역 오류 처리기 :

여기의 끔찍한 방법 :

window.addEventListener( 'error', function( e ) {
    
    if( e.error instanceof ErrorEvent || e.error instanceof TypeError ) {
        
        const msg = e.error.message;
        const suffixIdx = msg.indexOf( ".sum is not a function" );
        if( suffixIdx > -1 ) {
            const arrayStr = msg.substring( 0, suffixIdx );
            
            const arr = eval( arrayStr ); // <-- lolno
            const total = arr.reduce( ( sum, e ) => sum + e, 0 );
            console.log( total ); // 6
        }
    }
    
} );

[1,2,3].sum()


@NenadVracar는 eval로컬을 사용하지만 피하는 단순화 된 버전을 게시했습니다 try.

try {
    [1,2,3].sum()
} catch (err) {
    const result = err.message
    .match(/\[(.*?)\]/)[1]
    .split(',')
    .reduce((r, e) => r + +e, 0)
    
  console.log(result)
}

옵션 2 : Array생성자 재정의

이전 JavaScript 엔진 (2010 또는 ECMAScript 5 이전에 제작 됨) 을 사용하는 경우 Array생성자 를 재정의하는 스크립트 는 스크립트가 배열 리터럴을 만날 때 해당 생성자를 사용하며 .sum메서드는 다음 과 같이 추가 될 수 있습니다.

Array = function() { // <-- THIS WILL NOT WORK IN BROWSERS MADE AFTER 2010!
    this.sum = function() {
        var total = 0;
        for( var i = 0; i < this.length; i++ ) {
            total += this[i];
        }
        return total;
    };
};

let total = [1,2,3].sum();
console.log( total );

옵션 3 : prototype부동산에 은밀한 태도 :

다른 사람들이 주석에서 언급했듯이 prototype멤버를 변경 하거나 Object.defineProperty해당 멤버에 문자열로 액세스하는 경우 사용할 수 있습니다.

Array[ 'proto' + 'type' ].sum = function() {
    var total = 0;
    for( var i = 0; i < this.length; i++ ) {
        total += this[i];
    }
    return total;
};

let total = [1,2,3].sum();
console.log( total );

6 VLAZ Nov 17 2020 at 03:26

여기 선을 얼마나 줄 수 있습니까?

다음 줄이 작동하기를 원한다고 가정하면 [1, 2, 3].sum();아주 쉽게 무언가를 있습니다. 자동 세미콜론 삽입 규칙으로 인해 배열이있을 필요 가 없습니다 . 그것은 배열 수 있습니다 액세스 와 쉼표 연산자 이있다.

({3: {sum: () => console.log(6)}}) //<-- object

[1,2,3].sum(); //<-- array access

또는 더 명확하게하기 위해 다음은 동등한 코드입니다.

const obj = {
  3: {
    sum: () => console.log(6)
  }
};

obj[3].sum(); //<-- array access

sum해야 할 일에 대한 정의가 없기 때문에 위의 모든 요구 사항을 다룹니다. 프로토 타입 헛소리도, 추가 속성도 없습니다.

좋아, 기술적으로 sum는 아무 것도 요약 하지 않았지만 여기에 해결 방법이 있습니다. 다음과 같이 정의하십시오.

sum: (a, b) => a + b

이제 기술적으로 두 수를 더하는 함수입니다. 결국을 1, 2, 3호출하기 전에 나타나는 시퀀스를 합산 할 필요가 없습니다 sum.

2 LuisLimas Nov 17 2020 at 03:06

이것은 한 가지 방법입니다.

 [1,2,3].__proto__.sum = () => { console.log('this runs!'); }
 
 [1,2,3].sum();

기술적으로는을 사용하지 않고 사용 Prototype하고 있습니다 __proto__. Wich는 다른 이름으로 동일합니다 ... (하지만 인스턴스에만 해당)