2016-05-25 7 views
1

Ich entschuldige mich viel für den vagen Titel, aber ich muss es näher ausführen. Hier ist der Code in Frage, die ich auf http://ariya.ofilabs.com/2013/07/prime-numbers-factorial-and-fibonacci-series-with-javascript-array.html lesen:Warum funktioniert diese JavaScript-Funktion?

function isPrime(i) { 
    return (i > 1) && Array.apply(0, Array(1 + ~~Math.sqrt(i))). 
    every(function (x, y) { 
     console.log(x + ' ' + i % y); 
     return (y < 2) || (i % y !== 0) 
    }); 
} 

isPrime(23); 
isPrime(19); 
isPrime(188); 

Just for fun, habe ich diese Protokolle, so dass wir eine Ausgabe sehen:

undefined NaN 
undefined 0 
undefined 1 
undefined 2 
undefined 3 
undefined NaN 
undefined 0 
undefined 1 
undefined 1 
undefined 3 
undefined NaN 
undefined 0 
undefined 0 

Dies ist das erste Mal, dass ich jeden haben gesehen apply und every, so mit mir, aber mein Verständnis ist, dass apply im Grunde ruft die Array-Funktion, wo das erste Argument ist die Substitution für seine this und die zweite ist die Ausgabe ... Niemals würde denken, dass wäre nützlich, aber Diese Funktion scheint zu funktionieren, also ...

Hier scheinen sie ein Array mit der Länge der Quadratwurzel der betreffenden Zahl zu erstellen. Ich denke, das macht Sinn, weil die Quadratwurzel der größtmögliche Faktor der fraglichen Zahl wäre.

OK, also von hier, wenn wir für das Array zu protokollieren waren, sagen wir, die erste Zahl, würde es so aussehen:

> var i = 23; 
undefined 
> Array.apply(0, Array(1 + ~~Math.sqrt(i))); 
[ undefined, undefined, undefined, undefined, undefined ] 

Großen, so ist es eine Reihe von fünf undefined. Ok, gut, von hier aus sollte die Methode every prüfen, ob jedes Element in diesem Array den Callback-Funktionstest (oder was auch immer) besteht.

Die Dokumentation von Microsoft drei mögliche Argumente für die every Verfahren spezifiziert:

  • Wert
  • Index
  • Array

Daher ist in diesem Beispiel x ist der Wert, dh undefined, und y ist der Index.

Unsere Ergebnisse stimmen mit dieser Schlussfolgerung überein. Allerdings bin ich noch verschachtelt über verschachtelte Return-Anweisungen (wenn die niedrigste zurückgibt, gibt seine Eltern auch zurück?), Der Operator || hier (wenn der erste Test besteht, stoppt die jede Schleife?), Und nur allgemein wie dies funktioniert.


EDIT

das Protokoll mit einem x sollten nicht a y. mein Fehler:

console.log(y + ' ' + i % y); -> console.log(x + ' ' + i % y); 

ERKLÄRUNG

Also, wie ich auf diesen Code kommen, fragen Sie?Nun, natürlich, ist der einfachste Weg für eine Primzahl in Java zu überprüfen, würde so aussehen:

public static boolean isPrime(double num) { 
    for (double i = 2.0; i < sqrt(num); i++) { 
     if (num % i == 0.0) { 
      return true; 
     } 
    } 
    return false; 
} 

oder Python

def isPrime(num): 
    x = 2 
    isPrime = True 
    while x < math.sqrt(num): 
     if num % x == 0: 
      isPrime = False 
      break 
     x = x + 1 
    return isPrime 

oder js

function isPrime(n) { 
    for (var i = 2.0; i < Math.sqrt(n); i++) { 
     if (n % i === 0.0) { 
      return false; 
     } 
    } 
    return true; 
} 

Aber sagen wollte ich Suche nach dem größten Primfaktor einer Zahl wie 600851475143 Diese Schleifenmethoden würden zu lange dauern, oder? Ich denke, dieser "Hack", wie wir ihn beschreiben, ist vielleicht noch weniger effizient, weil er Arrays anstelle von Ganzzahlen oder Gleitkommazahlen verwendet, aber ich war immer noch auf der Suche nach einem effizienteren Weg, dieses Problem zu lösen.

+1

ich auf jeden Fall erhalten nicht die gleiche 'console.log()' Ausgabe, wie Sie, und ich bin nicht überrascht. 'y' sollte niemals' undefiniert' sein. – Pointy

+0

Der Blog, wo Sie gefunden haben, hat einen ganzen Artikel über diesen 'Array()' Trick. – Pointy

+0

Ja, ich habe den Blog gelesen, bin aber auf diesem Teil steckengeblieben. Kann es nicht herausfinden, also kam hier her. – pward

Antwort

4

Der Code in diesem Beitrag ist im Grunde Mist. Menschen beizubringen, Code zu schreiben, während gleichzeitig Hacks verwendet werden, ist Müll. Ja, Hacks haben ihren Platz (Optimierung), aber Pädagogen sollten Lösungen zeigen, die nicht von ihnen abhängen.

Hack 1

// the 0 isn't even relevant here. it should be null 
Array.apply(0, Array(1 + ...)) 

Hack 2

// This is just Math.floor(x), but trying to be clever 
~~x 

Hack 3

// this is an outright sin; totally unreadable code 
// I bet most people don't know the binding precedence of % over + 
y + ' ' + i % y 

// this is evaluated as 
y + ' ' + (i % y) 

// example 
2 + ' ' + (5 % 2) //=> "2 1" 

Ich bin immer noch unscharf zu geschachtelten return-Anweisungen (wenn der lo Westen eine Rendite, hat seine Eltern zurückkehren auch?),

A Nr return nur die Funktion kehrt die Aussage in

der

existiert || hier Operator (wenn der erste Test bestanden wird, funktioniert die jede Schleife Anschlag?)

Nr Array.prototype.every wird false zurückkehren, sobald der Rückruf eine false zurückgibt. Wenn ein false nie aus dem Rückruf zurückgegeben wird, gibt .every `true zurück.

function isEven(x) { return x % 2 === 0; } 
[2,4,5,6].every(isEven); //=> false, stops at the 5 
[2,4,6].every(isEven); //=> true 

Hier ist ein Beispiel von .every Kurzschlüsse

[1,2,3,4,5,6].every(x=> {console.log(x, x<4); return x<4;}); 
// 1 true 
// 2 true 
// 3 true 
// 4 false 
//=> false 

Sehen Sie, wie es stoppt, sobald der Rückruf false zurückkehrt? Die Elemente 5 und 6 werden nicht einmal ausgewertet.

... und nur allgemein, wie das funktioniert.

&& Art von Werken wie Array.prototype.every und || Art von Werken wie Array.prototype.some.

&& wird false zurückgeben, sobald die erste false angetroffen wird; mit anderen Worten, es erwartet alle Argumente zu true sein.

|| wird true zurückgeben, sobald die erste true angetroffen wird; mit anderen Worten erwartet es nur einige Argument zu true sein.

Relevant: short circuit evaluation

+0

Stimmen Sie der * crap * Charakterisierung zu. Es ist eine Art cleverer Trick, aber es verstößt gegen die erste Regel der Veröffentlichung von Beispielcode auf Ihrem Blog: Je schlechter der Code ist, desto größer ist die Anzahl der Personen, die ihn in Software einbetten, die eines Tages für Ihr Überleben entscheidend sein könnte. – Pointy

+0

Nun, warum gibt nicht jeder Index-0-Member "(y <2)"? – pward

+0

Ich meine, der einzige Grund, warum ich zu diesem Blog gekommen bin, war, dass die for-Schleife, die ich verwendete, um nach Primfaktoren einer auf dem Euler-Projekt veröffentlichten Nummer zu suchen, zu lange dauerte. – pward