Frage zum Javascript-Interview: Lass [1,2,3] .sum () laufen

Nov 17 2020

Javascript Interview Frage: make [1,2,3].sum()genaue Ausführung von Code ohne Verwendung Prototypeund Object.defineProperty, Object.defineProperties.

Da es sich um eine Interviewfrage handelte, gehe ich davon aus, dass es Möglichkeiten gibt, sie zum Laufen zu bringen.

Jede Hilfe / Richtung geschätzt.

Vielen Dank

Antworten

8 Dai Nov 17 2020 at 03:09

Vorwort: Fragen wie diese zeigen nicht wirklich, dass jemand ein "guter" Programmierer ist. Es bedeutet nur, dass er mit Tricks in der Sprache vertraut ist, die nicht zu besser wartbarem Code führen . Ich würde mich davor hüten, für ein Unternehmen oder Team zu arbeiten, das regelmäßig solche Tricks anwendet.

(Und in meinem persönlichen Fall: Ich habe als SE bei Microsoft an der Chakra-JavaScript-Engine gearbeitet und denke gerne, dass ich JavaScript / ECMAScript sehr gut kenne, und ich musste noch lange darüber nachdenken, wie dies ohne möglich ist Verwenden von prototypeoder defineProperty- deshalb denke ich nicht, dass dies eine gute technische Interviewfrage ist, wenn sie eine klare Antwort erwartet haben - aber wenn dies eine Interviewfrage war, die Sie dazu veranlassen soll, Fragen an den Interviewer zu stellen, ist das anders.


Option 1: Globale Fehlerbehandlungsroutine:

Hier ist ein schrecklicher Weg:

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 hat eine vereinfachte Version veröffentlicht, die dies vermeidet eval, obwohl eine lokale Version verwendet wird try:

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

Option 2: ArrayKonstruktor überschreiben

Wenn Sie eine ältere JavaScript-Engine verwenden (erstellt vor 2010 oder ECMAScript 5), wird bei einem Skript, das den ArrayKonstruktor überschreibt , dieser Konstruktor verwendet, wenn das Skript auf ein Array-Literal stößt. Die .sumMethode kann auf folgende Weise hinzugefügt werden:

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 );

Option 3: Hinterhältig mit der prototypeImmobilie sein:

Wie andere in den Kommentaren erwähnt haben, können Sie das prototypeMitglied trotzdem mutieren oder verwenden, Object.definePropertywenn Sie als Zeichenfolgen auf diese Mitglieder zugreifen:

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

Wie viel können wir hier die Linien umgehen?

Unter der Annahme , dass wir die folgende Zeile zu arbeiten wollen , [1, 2, 3].sum();dann können wir ganz einfach nur machen es tut etwas . Beachten Sie, dass es aufgrund der Regeln für das automatische Einfügen von Semikolons nicht erforderlich ist , dass ein Array vorhanden ist. Möglicherweise handelt es sich um einen Array- Zugriff mit einem Komma-Operator .

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

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

Oder um es klarer zu machen, hier ist der entsprechende Code:

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

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

Da ich keine Definition sumdafür sehe, was zu tun ist, deckt das oben Gesagte alle aufgeführten Anforderungen ab - keine Prototypen-Spielereien, keine zusätzlichen Eigenschaften.

OK, technisch gesehen , sumnicht fassen alles, aber hier ist eine Abhilfe: Definieren Sie es wie folgt aus

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

Nun ist es technisch eine Funktion, die zwei Zahlen summiert. Es ist schließlich nicht erforderlich, die Sequenz zu summieren 1, 2, 3, die vor dem Aufruf von angezeigt wird sum.

2 LuisLimas Nov 17 2020 at 03:06

Dies ist eine Möglichkeit:

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

Technisch verwenden Sie nicht Prototype, Sie verwenden __proto__. Was ist das gleiche mit einem anderen Namen ... (aber nur für Instanzen)