Κορυφαίες 11 (και περισσότερες!) Λειτουργίες JavaScript που πρέπει να γνωρίζετε

Κωδικός έξυπνος! Γίνετε πιο γρήγορος, πιο παραγωγικός και πιο χαρούμενος προγραμματιστής JavaScript κατακτώντας αυτές τις πιο σημαντικές και επαναλαμβανόμενες λειτουργίες στη γλώσσα.

Είτε είναι backend είτε frontend (ή ακόμα διαστημόπλοια), η JavaScript είναι παντού. Είναι επίσης μια αρκετά ευέλικτη γλώσσα (που σημαίνει ότι έχει σκληροπυρηνικά λειτουργικά μοτίβα προγραμματισμού καθώς και καλές τάξεις) και η ομοιότητά της με άλλες γλώσσες τύπου C διευκολύνει τη μετάβαση για προγραμματιστές από άλλες γλώσσες.

Αν θέλεις ανεβάστε επίπεδο το παιχνίδι JS σας, σας προτείνω να μάθετε, να εξασκηθείτε και τελικά να κατακτήσετε τις ακόλουθες βασικές λειτουργίες που είναι διαθέσιμες στη γλώσσα. Δεν είναι όλα αυτά αυστηρά «απαραίτητα» για την επίλυση προβλημάτων, αλλά μπορούν να σας βοηθήσουν σε πολλές περιπτώσεις, ενώ σε άλλες, μπορεί να μειώσουν την ποσότητα του κώδικα που πρέπει να γράψετε.

χάρτης()

Θα ήταν αίρεση να γράψετε ένα άρθρο για σημαντικές λειτουργίες JavaScript και να μην αναφέρετε το map()! 😆😆 Μαζί με το filter() και το reduce(), το map() σχηματίζει μια ιερή τριάδα. Αυτές είναι λειτουργίες που θα χρησιμοποιείτε ξανά και ξανά στην καριέρα σας, επομένως αξίζουν κάτι παραπάνω από μια ματιά. Ας τα αντιμετωπίσουμε ένα προς ένα, ξεκινώντας με το map().

Η map() είναι μια από εκείνες τις συναρτήσεις που προκαλούν το μεγαλύτερο πρόβλημα στους ανθρώπους που μαθαίνουν JavaScript. Γιατί; Όχι επειδή υπάρχει κάτι εγγενώς περίπλοκο σε αυτό, αλλά επειδή ο τρόπος που λειτουργεί αυτή η συνάρτηση είναι μια ιδέα που λαμβάνεται από αυτό που ονομάζεται Λειτουργικός Προγραμματισμός. Και δεδομένου ότι δεν είμαστε εκτεθειμένοι στον Λειτουργικό Προγραμματισμό – τα σχολεία μας και η βιομηχανία είναι γεμάτη από αντικειμενοστρεφείς γλώσσες – οι λειτουργίες φαίνονται παράξενες ή ακόμα και λανθασμένες στον προκατειλημμένο εγκέφαλό μας.

Η JavaScript είναι πολύ πιο λειτουργική από την Αντικειμενοστραφή, αν και οι σύγχρονες εκδόσεις της κάνουν ό,τι μπορούν για να κρύψουν αυτό το γεγονός. Αλλά αυτό είναι ένα ολόκληρο κουτάκι με σκουλήκια που μπορώ να ανοίξω ίσως κάποια άλλη μέρα. 🤣 Εντάξει, λοιπόν, χάρτης() . . .

Η map() είναι μια πολύ απλή συνάρτηση. προσκολλάται σε έναν πίνακα και μας βοηθά να μετατρέψουμε κάθε στοιχείο σε κάτι άλλο, με αποτέλεσμα έναν νέο πίνακα. Ο τρόπος ακριβώς μετατροπής ενός αντικειμένου παρέχεται ως άλλη συνάρτηση, η οποία κατά σύμβαση είναι ανώνυμη.

Αυτό είναι το μόνο που υπάρχει! Η σύνταξη μπορεί να χρειαστεί λίγη εξοικείωση, αλλά ουσιαστικά αυτό κάνουμε σε μια συνάρτηση map(). Γιατί μπορεί να θέλουμε να χρησιμοποιήσουμε τη map(); Εξαρτάται από το τι προσπαθούμε να πετύχουμε. Για παράδειγμα, ας υποθέσουμε ότι καταγράψαμε τη θερμοκρασία για κάθε ημέρα της τελευταίας εβδομάδας και την αποθηκεύσαμε ως μια απλή διάταξη. Ωστόσο, τώρα μας λένε ότι τα όργανα δεν ήταν πολύ ακριβή και ανέφεραν 1,5 βαθμό λιγότερη θερμοκρασία από ό,τι θα έπρεπε.

Μπορούμε να κάνουμε αυτή τη διόρθωση χρησιμοποιώντας τη συνάρτηση map() ως εξής:

const weeklyReadings = [20, 22, 20.5, 19, 21, 21.5, 23];

const correctedWeeklyReadings = weeklyReadings.map(reading => reading + 1.5);

console.log(correctedWeeklyReadings); // gives [ 21.5, 23.5, 22, 20.5, 22.5, 23, 24.5 ]

Ένα άλλο, πολύ πρακτικό, παράδειγμα προέρχεται από τον κόσμο του React, όπου η δημιουργία λιστών στοιχείων DOM από πίνακες είναι ένα κοινό μοτίβο. Έτσι, κάτι σαν αυτό είναι κοινό:

export default ({ products }) => {
    return products.map(product => {
        return (
            <div className="product" key={product.id}>
                <div className="p-name">{product.name}</div>
                <div className="p-desc">{product.description}</div>
            </div>
        );
    });
};

Εδώ, έχουμε ένα λειτουργικό στοιχείο React που λαμβάνει μια λίστα προϊόντων ως στηρίγματα. Από αυτή τη λίστα (πίνακας), στη συνέχεια δημιουργεί μια λίστα με “divs” HTML, μετατρέποντας ουσιαστικά κάθε αντικείμενο προϊόντος σε HTML. Το αντικείμενο του αρχικού προϊόντος παραμένει ανέγγιχτο.

Μπορείτε να υποστηρίξετε ότι η map() δεν είναι παρά ένας βρόχος δοξασμένος για και θα είχατε απόλυτο δίκιο. Παρατηρήστε όμως ότι μόλις κάνετε αυτό το επιχείρημα, μιλάει το αντικειμενοστρεφές εκπαιδευμένο μυαλό σας, ενώ αυτές οι συναρτήσεις και η λογική τους προέρχονται από τον Λειτουργικό Προγραμματισμό, όπου η ομοιομορφία, η συμπαγής και η κομψότητα γίνονται σεβαστά. 🙂

φίλτρο()

Το filter() είναι μια εξαιρετικά χρήσιμη συνάρτηση που θα βρείτε να εφαρμόζετε ξανά και ξανά σε πολλές περιπτώσεις. Όπως υποδηλώνει το όνομα, αυτή η συνάρτηση φιλτράρει έναν πίνακα με βάση τους κανόνες/λογική που παρέχετε και επιστρέφει έναν νέο πίνακα που περιέχει στοιχεία που ικανοποιούν αυτούς τους κανόνες.

Ας χρησιμοποιήσουμε ξανά το παράδειγμά μας για τον καιρό. Ας υποθέσουμε ότι έχουμε έναν πίνακα που περιέχει τις μέγιστες θερμοκρασίες για κάθε ημέρα της προηγούμενης εβδομάδας. τώρα, θέλουμε να μάθουμε πόσες από αυτές τις μέρες ήταν πιο κρύες. Ναι, το “πιο κρύο” είναι ένας υποκειμενικός όρος, οπότε ας υποθέσουμε ότι αναζητούμε ημέρες όπου η θερμοκρασία ήταν κάτω από 20. Μπορούμε να το κάνουμε χρησιμοποιώντας τη συνάρτηση filter() ως εξής:

const weeklyReadings = [20, 22, 20.5, 19, 21, 21.5, 23];

const colderDays = weeklyReadings.filter(dayTemperature => {
    return dayTemperature < 20;
});

console.log("Total colder days in week were: " + colderDays.length); // 1

Σημειώστε ότι η ανώνυμη συνάρτηση που περνάμε στο filter() πρέπει να επιστρέψει μια Boolean τιμή: true ή false. Αυτός είναι ο τρόπος με τον οποίο το filter() θα γνωρίζει εάν θα συμπεριλάβει ή όχι αυτό το στοιχείο στον φιλτραρισμένο πίνακα. Είστε ελεύθεροι να γράψετε οποιαδήποτε πολύπλοκη λογική μέσα σε αυτήν την ανώνυμη συνάρτηση. μπορείτε να πραγματοποιείτε κλήσεις API και να διαβάζετε εισόδους χρηστών και ούτω καθεξής, αρκεί να βεβαιωθείτε ότι στο τέλος, επιστρέφετε μια τιμή Boolean.

Προσοχή: Αυτή είναι μια δευτερεύουσα σημείωση που αισθάνομαι υποχρεωμένος να παράσχω με βάση την εμπειρία μου ως προγραμματιστής JavaScript. Είτε αυτό οφείλεται σε προχειρότητα είτε σε λάθος βασικά στοιχεία, πολλοί προγραμματιστές δημιουργούν διακριτικά σφάλματα στα προγράμματά τους όταν χρησιμοποιούν το filter(). Ας ξαναγράψουμε τον προηγούμενο κώδικα για να περιέχει το σφάλμα:

const weeklyReadings = [20, 22, 20.5, 19, 21, 21.5, 23];

const colderDays = weeklyReadings.filter(dayTemperature => {
    return dayTemperature < 20;
});

if(colderDays) {
    console.log("Yes, there were colder days last week");
} else {
    console.log("No, there were no colder days");
}

Παρατηρήστε κάτι; Μεγάλη δουλειά αν το έκανες! Η συνθήκη if προς το τέλος ελέγχει το colderDays, που είναι στην πραγματικότητα ένας πίνακας! Θα εκπλαγείτε πόσες φορές οι άνθρωποι κάνουν αυτό το λάθος καθώς αγωνίζονται να τηρήσουν τις προθεσμίες ή τον κώδικα με χαμηλά κέφια (για οποιονδήποτε λόγο). Το πρόβλημα με αυτήν την κατάσταση είναι ότι η JavaScript είναι μια παράξενη και ασυνεπής γλώσσα από πολλές απόψεις, και η «αλήθεια» των πραγμάτων είναι ένα από αυτά. Ενώ [] == το true επιστρέφει false, κάνοντας σας να πιστεύετε ότι ο παραπάνω κώδικας δεν έχει σπάσει, η πραγματικότητα είναι ότι μέσα σε μια συνθήκη if, [] αξιολογείται ως αληθινό! Με άλλα λόγια, ο κώδικας που γράψαμε δεν θα πει ποτέ ότι δεν υπήρχαν πιο κρύες μέρες την περασμένη εβδομάδα.

  Τι συμβαίνει όταν αποκλείετε κάποιον στο Match;

Η επιδιόρθωση είναι πολύ απλή, όπως δίνεται στον κώδικα πριν από τον παραπάνω κώδικα. Ελέγχουμε για colderDays.length, το οποίο είναι εγγυημένο ότι θα μας δώσει έναν ακέραιο αριθμό (μηδέν ή παραπάνω) και έτσι λειτουργεί με συνέπεια σε λογικές συγκρίσεις. Σημειώστε ότι το filter() θα επιστρέφει πάντα, πάντα, πάντα έναν πίνακα, κενό ή μη, ώστε να μπορούμε να βασιστούμε σε αυτό και να γράφουμε τις λογικές μας συγκρίσεις με σιγουριά.

Ήταν μια μεγαλύτερη παράκαμψη από ό,τι σχεδίαζα, αλλά σφάλματα όπως αυτό αξίζει να επισημανθούν με δέκα χιλιάδες λέξεις, όλα με κεφαλαία αν χρειαστεί. Ελπίζω να μην σας τσιμπήσει αυτό και να γλιτώσετε από εκατοντάδες ώρες προσπάθειας εντοπισμού σφαλμάτων! 🙂

περιορίζω()

Από όλες τις λειτουργίες σε αυτό το άρθρο, καθώς και στην τυπική βιβλιοθήκη JavaScript, η reduce() συγκαταλέγεται μεταξύ των κορυφαίων για το “μπερδεμένο και περίεργο”. Αν και αυτή η λειτουργία είναι εξαιρετικά σημαντική και οδηγεί σε κομψό κώδικα σε πολλές περιπτώσεις, αποφεύγεται από τους περισσότερους προγραμματιστές JavaScript και προτιμούν να γράφουν πιο αναλυτικό κώδικα.

Ο λόγος είναι αυτός — και θα είμαι ειλικρινής εδώ! — Το reduce() είναι δύσκολο να κατανοηθεί, τόσο με την έννοια όσο και με την έννοια της εκτέλεσης. Όταν διαβάζεις την περιγραφή του, το έχεις ξαναδιαβάσει αρκετές φορές και ακόμα, αμφιβάλλεις για τον εαυτό σου αν το διάβασες λάθος. και όταν το βλέπετε σε δράση και προσπαθείτε να οραματιστείτε πώς λειτουργεί, ο εγκέφαλός σας στρίβει σε χίλιους κόμβους! 🤭

Τώρα, μη φοβάσαι. Η συνάρτηση reduce() δεν είναι πουθενά πολυπλοκότητα και εκφοβισμό, ας πούμε, Β+ Δέντρα και τους αλγόριθμους τους. Απλώς αυτού του είδους η λογική σπάνια συναντάται κατά τη διάρκεια της καθημερινής δουλειάς του μέσου προγραμματιστή.

Έτσι, έχοντας τρομάξει τα φώτα της ημέρας και μετά σας είπα αμέσως να μην ανησυχείτε, θα ήθελα επιτέλους να σας δείξω τι είναι αυτή η λειτουργία και γιατί ακριβώς μπορεί να τη χρειαστούμε.

Όπως υποδηλώνει το όνομα, η reduce() χρησιμοποιείται για να μειώσει κάτι. Το πράγμα που μειώνει είναι ένας πίνακας και το πράγμα στο οποίο μειώνει τον δεδομένο πίνακα είναι μια ενιαία τιμή (αριθμός, συμβολοσειρά, συνάρτηση, αντικείμενο, οτιδήποτε). Ακολουθεί ένας απλούστερος τρόπος για να το θέσουμε — η reduce() μετατρέπει έναν πίνακα σε μια ενιαία τιμή. Σημειώστε ότι η τιμή που επιστρέφει από την reduce() δεν είναι πίνακας, όπως συμβαίνει με τη map() και τη filter(). Το να το καταλάβουμε αυτό είναι ήδη η μισή μάχη. 🙂

Τώρα, είναι προφανές ότι αν πρόκειται να μετασχηματίσουμε (μειώσουμε) έναν πίνακα, πρέπει να παρέχουμε την απαραίτητη λογική. και με βάση την εμπειρία σας ως προγραμματιστής JS, έχετε ήδη μαντέψει ότι το κάνουμε αυτό χρησιμοποιώντας μια συνάρτηση. Αυτή η συνάρτηση είναι αυτό που ονομάζουμε συνάρτηση μειωτήρα, η οποία σχηματίζει το πρώτο όρισμα για την reduce(). Το δεύτερο όρισμα είναι μια αρχική τιμή, όπως ένας αριθμός, μια συμβολοσειρά κ.λπ. (Θα εξηγήσω σε λίγο τι στο καλό είναι αυτή η “αρχική τιμή”).

Με βάση τη μέχρι τώρα κατανόησή μας, μπορούμε να πούμε ότι μια κλήση για μείωση() μοιάζει με αυτό: array.reduce(reducerFunction, startingValue). Τώρα ας ασχοληθούμε με την καρδιά του όλου θέματος: τη λειτουργία μειωτήρα. Όπως έχει ήδη διαπιστωθεί, η συνάρτηση μειωτήρα είναι αυτή που λέει στη reduce() πώς να μετατρέψει τον πίνακα σε μια ενιαία τιμή. Χρειάζονται δύο ορίσματα: μια μεταβλητή για να λειτουργεί ως συσσωρευτής (μην ανησυχείτε, θα το εξηγήσω και αυτό) και μια μεταβλητή για την αποθήκευση της τρέχουσας τιμής.

Ξέρω ξέρω . . . αυτή ήταν πολλή ορολογία για μια μεμονωμένη λειτουργία που δεν είναι καν υποχρεωτική στο JavaScript. 😝😝 Και αυτός είναι ο λόγος που οι άνθρωποι ξεφεύγουν από τη μείωση(). Αλλά αν το μάθετε βήμα-βήμα, όχι μόνο θα το κατανοήσετε αλλά και θα το εκτιμήσετε καθώς γίνεστε καλύτερος προγραμματιστής.

Εντάξει, λοιπόν, πίσω στο θέμα. Η “αρχική τιμή” που μεταβιβάζεται στην reduce() είναι . . . Λοιπόν, η αρχική τιμή για τον υπολογισμό που θέλετε να χρησιμοποιήσετε. Για παράδειγμα, εάν πρόκειται να κάνετε πολλαπλασιασμό στη συνάρτηση μειωτήρα, μια αρχική τιμή 1 έχει νόημα. για επιπλέον, μπορείτε να ξεκινήσετε με 0, και ούτω καθεξής.

Τώρα ας δούμε την υπογραφή για τη λειτουργία μειωτήρα. Μια συνάρτηση μειωτήρα που μεταβιβάζεται στη reduce() έχει την ακόλουθη μορφή: ReducerFunction(accumulator, currentValue). Το “Acumulator” είναι απλώς ένα φανταχτερό όνομα για τη μεταβλητή που συλλέγει και διατηρεί το αποτέλεσμα του υπολογισμού. είναι ακριβώς σαν να χρησιμοποιείτε μια μεταβλητή που ονομάζεται total για να αθροίσετε όλα τα στοιχεία σε έναν πίνακα χρησιμοποιώντας κάτι σαν σύνολο += arr[i]. Αυτός είναι ακριβώς ο τρόπος με τον οποίο εφαρμόζεται η συνάρτηση μειωτήρα στο reduce(): ο συσσωρευτής ορίζεται αρχικά στην αρχική τιμή που παρέχετε και, στη συνέχεια, ένα προς ένα επισκέπτονται τα στοιχεία του πίνακα, εκτελείται ο υπολογισμός και το αποτέλεσμα αποθηκεύεται στο ο συσσωρευτής και ούτω καθεξής. . .

Λοιπόν, ποια είναι αυτή η “τρέχουσα τιμή” σε μια συνάρτηση μειωτήρα; Είναι η ίδια ιδέα που θα φανταζόσασταν νοερά αν σας ζητούσα να διασχίσετε έναν πίνακα: θα έπαιρνα μια μεταβλητή για να ξεκινήσει από το μηδέν δείκτη και θα την μετακινούσες βήμα προς τα εμπρός. Ενώ το κάνετε αυτό, αν σας ζητήσω να σταματήσετε ξαφνικά, θα βρεθείτε σε ένα από τα στοιχεία του πίνακα, σωστά; Αυτό εννοούμε με τον όρο τρέχουσα τιμή: είναι η τιμή της μεταβλητής που χρησιμοποιείται για την αναπαράσταση του στοιχείου του πίνακα που εξετάζεται αυτήν τη στιγμή (σκεφτείτε να κάνετε βρόχο πάνω από έναν πίνακα αν αυτό βοηθάει).

Με όλα αυτά, ήρθε η ώρα να δούμε ένα απλό παράδειγμα και να δούμε πώς όλη αυτή η ορολογία συνδυάζεται σε μια πραγματική κλήση reduce(). Ας υποθέσουμε ότι έχουμε έναν πίνακα που περιέχει τους πρώτους n φυσικούς αριθμούς (1, 2, 3 . . . n) και μας ενδιαφέρει να βρούμε το παραγοντικό του n. Ξέρουμε ότι για να βρούμε n! χρειάζεται απλώς να πολλαπλασιάσουμε τα πάντα, κάτι που μας οδηγεί σε αυτήν την υλοποίηση:

const numbers = [1, 2, 3, 4, 5];
const factorial = numbers.reduce((acc, item) => acc * item, 1);
console.log(factorial); // 120

Πολλά συμβαίνουν σε αυτές τις τρεις γραμμές κώδικα, οπότε ας τον αποσυσκευάσουμε μία προς μία στο πλαίσιο της (πολύ μεγάλης) συζήτησης που είχαμε μέχρι τώρα. Όπως είναι προφανές, οι αριθμοί είναι ο πίνακας που περιέχει όλους τους αριθμούς που θέλουμε να πολλαπλασιάσουμε. Στη συνέχεια, ρίξτε μια ματιά στην κλήση numbers.reduce(), που λέει ότι η αρχική τιμή για το acc θα πρέπει να είναι 1 (επειδή δεν επηρεάζει ή καταστρέφει κανέναν πολλαπλασιασμό). Στη συνέχεια, ελέγξτε το σώμα της συνάρτησης μειωτήρα, `(acc, item) => acc * item, το οποίο απλώς λέει ότι η επιστρεφόμενη τιμή για κάθε επανάληψη στον πίνακα πρέπει να είναι αυτό το στοιχείο πολλαπλασιαζόμενο με ό,τι υπάρχει ήδη στον συσσωρευτή. Η επανάληψη και η ουσιαστική αποθήκευση του πολλαπλασιασμού στον συσσωρευτή είναι αυτό που συμβαίνει στα παρασκήνια και είναι ένας από τους μεγαλύτερους λόγους που το reduce() είναι ένα τέτοιο εμπόδιο για τους προγραμματιστές JavaScript.

  Επιδιόρθωση Δεν είναι δυνατή η έναρξη του προγράμματος Η πρόσβαση στο Visual Studio δεν επιτρέπεται

Γιατί να χρησιμοποιήσετε τη μείωση();

Είναι μια πραγματικά υπέροχη ερώτηση και για να είμαι ειλικρινής, δεν έχω μια σίγουρη απάντηση. Ό,τι κάνει η reduce() μπορεί να γίνει μέσω βρόχων, forEach(), κ.λπ. Ωστόσο, αυτές οι τεχνικές καταλήγουν σε πολύ περισσότερο κώδικα, καθιστώντας δύσκολη την ανάγνωση, ειδικά αν βιάζεστε. Έπειτα, υπάρχει η ανησυχία για το αμετάβλητο: με τη μείωση() και παρόμοιες συναρτήσεις, μπορείτε να είστε σίγουροι ότι τα αρχικά σας δεδομένα δεν έχουν μεταλλαχθεί. Αυτό από μόνο του εξαλείφει ολόκληρες κατηγορίες σφαλμάτων, ειδικά σε κατανεμημένες εφαρμογές.

Τέλος, η reduce() είναι πολύ πιο ευέλικτη, με την έννοια ότι ο συσσωρευτής μπορεί να είναι ένα αντικείμενο, ένας πίνακας ή ακόμα και μια συνάρτηση εάν χρειάζεται. το ίδιο ισχύει για την αρχική τιμή και άλλα μέρη της κλήσης συνάρτησης — σχεδόν τα πάντα μπορούν να εισέλθουν και σχεδόν τα πάντα μπορούν να βγουν, επομένως υπάρχει εξαιρετική ευελιξία στο σχεδιασμό επαναχρησιμοποιήσιμου κώδικα.

Εάν δεν είστε ακόμα πεπεισμένοι, αυτό είναι επίσης εντάξει. η ίδια η κοινότητα JavaScript διχάζεται έντονα σχετικά με τη «συμπαγή», την «κομψότητα» και τη «δύναμη» της μείωσης(), οπότε δεν πειράζει αν δεν τη χρησιμοποιήσετε. 🙂 Αλλά φροντίστε να δείτε μερικά προσεγμένα παραδείγματα πριν αποφασίσετε να βάλετε στο bin reduce().

μερικοί()

Ας υποθέσουμε ότι έχετε μια σειρά από αντικείμενα, με κάθε αντικείμενο να αντιπροσωπεύει ένα άτομο. Θέλετε να μάθετε αν υπάρχουν άτομα στη σειρά που είναι άνω των 35 ετών. Σημειώστε ότι δεν χρειάζεται να μετρήσετε πόσα είναι αυτά τα άτομα, πόσο μάλλον να ανακτήσετε μια λίστα με αυτά. Αυτό που λέμε εδώ είναι το ισοδύναμο του «ένα ή περισσότερα» ή «τουλάχιστον ένα».

Πώς το κάνεις αυτό;

Ναι, θα μπορούσατε να δημιουργήσετε μια μεταβλητή σημαίας και να κάνετε βρόχο πάνω από τον πίνακα για να λύσετε αυτό το πρόβλημα ως εξής:

const persons = [
    {
        name: 'Person 1',
        age: 32
    },
    
    {
        name: 'Person 2',
        age: 40
    },
];

let foundOver35 = false;

for (let i = 0; i < persons.length; i ++) {
    if(persons[i].age > 35) {
        foundOver35 = true;
        break;
    }
}

if(foundOver35) {
    console.log("Yup, there are a few people here!")
}

Το πρόβλημα? Ο κώδικας είναι πολύ σαν C ή Java, κατά τη γνώμη μου. Το “Verbose” είναι μια άλλη λέξη που έρχεται στο μυαλό. Ο έμπειρος JS μπορεί να σκέφτεται το “άσχημο”, “φρικτό”, κ.λπ. 😝 Και δικαίως, θα έλεγα. Ένας τρόπος για να βελτιώσετε αυτό το κομμάτι κώδικα είναι να χρησιμοποιήσετε κάτι όπως το map(), αλλά ακόμα και τότε η λύση είναι λίγο άβολη.

Αποδεικνύεται ότι έχουμε μια αρκετά προσεγμένη συνάρτηση που ονομάζεται some() που είναι ήδη διαθέσιμη στη βασική γλώσσα. Αυτή η συνάρτηση λειτουργεί σε πίνακες και δέχεται μια προσαρμοσμένη συνάρτηση «φιλτραρίσματος», επιστρέφοντας μια Boolean τιμή true ή false. Ουσιαστικά, κάνει αυτό που προσπαθούσαμε να κάνουμε τα τελευταία λεπτά, μόνο πολύ συνοπτικά και κομψά. Δείτε πώς μπορούμε να το χρησιμοποιήσουμε:

const persons = [
    {
        name: 'Person 1',
        age: 32
    },
    
    {
        name: 'Person 2',
        age: 40
    },
];

if(persons.some(person => {
    return person.age > 35
})) {
    console.log("Found some people!")
}

Ίδια εισαγωγή, το ίδιο αποτέλεσμα με πριν. αλλά παρατηρήστε τη μαζική μείωση του κώδικα! Παρατηρήστε επίσης πόσο δραστικά μειώνεται η γνωστική επιβάρυνση επειδή δεν χρειάζεται πλέον να αναλύουμε τον κώδικα γραμμή προς γραμμή σαν να ήμασταν οι ίδιοι ο διερμηνέας! Ο κώδικας τώρα σχεδόν διαβάζεται σαν φυσική γλώσσα.

κάθε()

Ακριβώς όπως κάποια(), έχουμε μια άλλη χρήσιμη συνάρτηση που ονομάζεται every(). Όπως μπορείτε να μαντέψετε μέχρι τώρα, και αυτό επιστρέφει μια Boolean τιμή ανάλογα με το αν όλα τα στοιχεία του πίνακα περνούν τη δεδομένη δοκιμή. Φυσικά, το τεστ για να περάσεις παρέχεται ως ανώνυμη συνάρτηση τις περισσότερες φορές. Θα σας απαλλαγώ από τον πόνο του πώς μπορεί να μοιάζει μια αφελής έκδοση του κώδικα, οπότε ορίστε πώς χρησιμοποιείται το κάθε():

const entries = [
    {
        id: 1
    },
    
    {
        id: 2
    },
    
    {
        id: 3  
    },
];

if(entries.every(entry => {
    return Number.isInteger(entry.id) && entry.id > 0;
})) {
    console.log("All the entries have a valid id")
}

Όπως είναι προφανές, ο κώδικας ελέγχει όλα τα αντικείμενα του πίνακα για μια έγκυρη ιδιότητα αναγνωριστικού. Ο ορισμός του “έγκυρου” εξαρτάται από το πλαίσιο του προβλήματος, αλλά όπως μπορείτε να δείτε, για αυτόν τον κώδικα, θεώρησα μη αρνητικούς ακέραιους αριθμούς. Για άλλη μια φορά, βλέπουμε πόσο απλός και κομψός είναι ο κώδικας στην ανάγνωση, που είναι ο μοναδικός στόχος αυτής της (και παρόμοιας) λειτουργίας(ών).

περιλαμβάνει()

Πώς ελέγχετε για την ύπαρξη υποσυμβολοσειρών και στοιχείων πίνακα; Λοιπόν, αν είστε σαν εμένα, αναζητάτε γρήγορα την indexOf() και, στη συνέχεια, αναζητάτε τα έγγραφα για να σας ενημερώσουμε για τις πιθανές τιμές επιστροφής του. Είναι μια σημαντική ταλαιπωρία και οι τιμές επιστροφής είναι δύσκολο να θυμηθούν (γρήγορα — τι σημαίνει μια διαδικασία που επιστρέφει το 2 στο λειτουργικό σύστημα;).

Αλλά υπάρχει μια ωραία εναλλακτική που μπορούμε να χρησιμοποιήσουμε: περιλαμβάνει(). Η χρήση είναι τόσο απλή όσο το όνομα και ο κωδικός που προκύπτει είναι εξαιρετικά συγκινητικός. Λάβετε υπόψη ότι η αντιστοίχιση γίνεται από την include() γίνεται με διάκριση πεζών-κεφαλαίων, αλλά υποθέτω ότι αυτό είναι που περιμένουμε ούτως ή άλλως όλοι οι διαισθητικοί. Και τώρα, ώρα για κάποιο κωδικό!

const numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(4));
const name = "Ankush";
console.log(name.includes('ank')); // false, because first letter is in small caps
console.log(name.includes('Ank')); // true, as expected

Ωστόσο, μην περιμένετε πολλά από αυτήν την ταπεινή μέθοδο:

const user = {a: 10, b: 20};
console.log(user.includes('a')); // blows up, as objects don't have a "includes" method

Δεν μπορεί να κοιτάξει μέσα σε αντικείμενα καθώς απλά δεν ορίζεται για αντικείμενα. Όμως, γνωρίζουμε ότι λειτουργεί σε πίνακες, οπότε ίσως μπορούμε να κάνουμε κάποιο κόλπο εδώ . . . 🤔.

const persons = [{name: 'Phil'}, {name: 'Jane'}];
persons.includes({name: 'Phil'});

Λοιπόν, τι συμβαίνει όταν εκτελείτε αυτόν τον κώδικα; Δεν εκρήγνυται, αλλά η έξοδος είναι επίσης απογοητευτική: false. 😫😫 Στην πραγματικότητα, αυτό έχει να κάνει με τα αντικείμενα, τους δείκτες και τον τρόπο με τον οποίο η JavaScript βλέπει και διαχειρίζεται τη μνήμη, η οποία είναι ένας δικός της κόσμος. Αν θέλετε να βουτήξετε πιο βαθιά, μη διστάσετε να κάνετε τη βουτιά (ίσως ξεκινήστε εδώ), αλλά θα σταματήσω εδώ.

Μπορούμε να κάνουμε τον παραπάνω κώδικα να συμπεριφέρεται αν τον ξαναγράψουμε ως εξής, αλλά σε αυτό το σημείο, λίγο πολύ γίνεται αστείο, κατά τη γνώμη μου:

const phil = {name: 'Phil'};
const persons = [phil, {name: 'Jane'}];
persons.includes(phil); // true

Ωστόσο, δείχνει ότι μπορούμε να κάνουμε έργα include() σε αντικείμενα, οπότε υποθέτω ότι δεν είναι ολοκληρωτική καταστροφή. 😄

φέτα()

Ας υποθέσουμε ότι έχουμε μια συμβολοσειρά και σας ζητώ να επιστρέψετε ένα μέρος της που αρχίζει με “r” και τελειώνει με “z” (οι πραγματικοί χαρακτήρες δεν είναι σημαντικοί). Πώς θα το προσέγγιζες; Ίσως θα δημιουργήσατε μια νέα συμβολοσειρά και θα τη χρησιμοποιούσατε για να αποθηκεύσετε όλους τους απαραίτητους χαρακτήρες και να τους επιστρέψετε. Ή αν είστε όπως οι περισσότεροι προγραμματιστές, θα μου δίνατε δύο δείκτες πίνακα σε αντάλλαγμα: ο ένας δείχνει την αρχή της υποσυμβολοσειράς και ο άλλος το τέλος.

  Πώς να προσθέσετε μια επαφή στο Skype

Και οι δύο αυτές προσεγγίσεις είναι καλές, αλλά υπάρχει μια ιδέα που ονομάζεται τεμαχισμός που προσφέρει μια τακτοποιημένη λύση σε τέτοιες καταστάσεις. Ευτυχώς, δεν υπάρχει καμία περίεργη θεωρία για να ακολουθήσει? Η κοπή σε φέτες σημαίνει ακριβώς αυτό που ακούγεται — δημιουργώντας μια μικρότερη χορδή/πίνακα από τη δεδομένη, όπως ακριβώς δημιουργούμε φέτες φρούτων. Ας δούμε τι εννοώ, με τη βοήθεια ενός απλού παραδείγματος:

const headline = "And in tonight's special, the guest we've all been waiting for!";
const startIndex = headline.indexOf('guest');
const endIndex = headline.indexOf('waiting');
const newHeadline = headline.slice(startIndex, endIndex);
console.log(newHeadline); // guest we've all been

Όταν κάνουμε slice(), παρέχουμε δύο δείκτες στην JavaScript — τον έναν όπου θέλουμε να ξεκινήσουμε τον τεμαχισμό και τον άλλο όπου θέλουμε να σταματήσει. Το catch με το slice() είναι ότι ο τελικός δείκτης δεν περιλαμβάνεται στο τελικό αποτέλεσμα, γι’ αυτό βλέπουμε ότι λείπει η λέξη “waiting” από τη νέα επικεφαλίδα στον παραπάνω κώδικα.

Έννοιες όπως το slicing είναι πιο εμφανείς σε άλλες γλώσσες, κυρίως στην Python. Αν ρωτήσετε αυτούς τους προγραμματιστές, θα πουν ότι δεν μπορούν να φανταστούν τη ζωή χωρίς αυτήν τη λειτουργικότητα, και δικαίως όταν η γλώσσα παρέχει μια πολύ προσεγμένη σύνταξη για την κοπή.

Το κόψιμο σε φέτες είναι προσεγμένο και εξαιρετικά βολικό και δεν υπάρχει λόγος να μην το χρησιμοποιήσετε. Δεν είναι επίσης συντακτικό γεμάτη με ποινή απόδοσης, καθώς δημιουργεί ρηχά αντίγραφα του αρχικού πίνακα/συμβολοσειράς. Για προγραμματιστές JavaScript, συνιστώ ανεπιφύλακτα να εξοικειωθείτε με το slice() και να το προσθέσετε στο οπλοστάσιό σας!

συνδέω()

Η μέθοδος splice() ακούγεται σαν ξαδέρφη του slice(), και κατά κάποιο τρόπο μπορούμε να υποστηρίξουμε ότι είναι. Και οι δύο δημιουργούν νέους πίνακες/συμβολοσειρές από τους αρχικούς, με μια μικρή αλλά σημαντική διαφορά — η splice() αφαιρεί, αλλάζει ή προσθέτει στοιχεία αλλά τροποποιεί τον αρχικό πίνακα. Αυτή η «καταστροφή» της αρχικής συστοιχίας μπορεί να δημιουργήσει τεράστια προβλήματα αν δεν είστε προσεκτικοί ή δεν καταλαβαίνετε βαθιά αντίγραφα και αναφορές. Αναρωτιέμαι τι εμπόδιζε τους προγραμματιστές να χρησιμοποιήσουν την ίδια προσέγγιση όπως για το slice() και να αφήσουν τον αρχικό πίνακα ανέγγιχτο, αλλά υποθέτω ότι μπορούμε να είμαστε πιο επιεικής απέναντι σε μια γλώσσα δημιουργήθηκε σε μόλις δέκα ημέρες.

Παρά τα παράπονά μου, ας ρίξουμε μια ματιά στο πώς λειτουργεί το splice(). Θα δείξω ένα παράδειγμα όπου αφαιρούμε μερικά στοιχεία από έναν πίνακα, καθώς αυτή είναι η πιο κοινή χρήση που θα βρείτε για αυτήν τη μέθοδο. Επίσης, θα αποφύγω να παρέχω παραδείγματα προσθήκης και εισαγωγής, επειδή αυτά μπορούν εύκολα να αναζητηθούν και είναι επίσης απλά.

const items = ['eggs', 'milk', 'cheese', 'bread', 'butter'];
items.splice(2, 1);
console.log(items); // [ 'eggs', 'milk', 'bread', 'butter' ]

Η κλήση στο splice() παραπάνω λέει: ξεκινήστε από το δείκτη 2 (την τρίτη θέση, δηλαδή) του πίνακα και αφαιρέστε ένα στοιχείο. Στον δεδομένο πίνακα, το ‘τυρί’ είναι το τρίτο στοιχείο, επομένως αφαιρείται από τον πίνακα και ο πίνακας στοιχείων συντομεύεται, όπως αναμένεται. Παρεμπιπτόντως, τα στοιχεία που αφαιρέθηκαν επιστρέφονται με splice() στη φόρμα ή έναν πίνακα, οπότε αν το θέλαμε, θα μπορούσαμε να έχουμε συλλάβει το ‘cheese’ σε μια μεταβλητή.

Από την εμπειρία μου, το indexOf() και το splice() έχουν μεγάλη συνέργεια — βρίσκουμε το ευρετήριο ενός στοιχείου και μετά το αφαιρούμε από τον δεδομένο πίνακα. Ωστόσο, σημειώστε ότι δεν είναι πάντα η πιο αποτελεσματική μέθοδος και ότι συχνά η χρήση κλειδιών αντικειμένου (το ισοδύναμο ενός χάρτη κατακερματισμού) είναι πολύ πιο γρήγορη.

βάρδια()

Η shift() είναι μια εύχρηστη μέθοδος ταξινόμησης και χρησιμοποιείται για την αφαίρεση του πρώτου στοιχείου ενός πίνακα. Παρατηρήστε ότι το ίδιο πράγμα μπορεί να γίνει με το splice(), αλλά το shift() είναι λίγο πιο εύκολο να το θυμάστε και είναι διαισθητικό όταν το μόνο που χρειάζεται να κάνετε είναι να κόψετε το πρώτο στοιχείο.

const items = ['eggs', 'milk', 'cheese', 'bread', 'butter'];
items.shift()
console.log(items); // [ 'milk', 'cheese', 'bread', 'butter' ]

unshift()

Όπως η shift() αφαιρεί το πρώτο στοιχείο από έναν πίνακα, η unshift() προσθέτει ένα νέο στοιχείο στην αρχή του πίνακα. Η χρήση του είναι εξίσου απλή και συμπαγής:

const items = ['eggs', 'milk'];
items.unshift('bread')
console.log(items); // [ 'bread', 'eggs', 'milk' ]

Τούτου λεχθέντος, δεν μπορώ να συγκρατηθώ και να προειδοποιήσω τους νέους στο παιχνίδι: σε αντίθεση με τις δημοφιλείς μεθόδους push() και pop(), η shift() και η unshift() είναι εξαιρετικά αναποτελεσματική (λόγω του τρόπου με τον οποίο λειτουργούν οι υποκείμενοι αλγόριθμοι). Επομένως, εάν χρησιμοποιείτε μεγάλες συστοιχίες (για παράδειγμα, 2000+ στοιχεία), πάρα πολλές από αυτές τις κλήσεις λειτουργιών μπορεί να σταματήσουν την εφαρμογή σας.

γέμισμα()

Μερικές φορές χρειάζεται να αλλάξετε πολλά στοιχεία σε μια ενιαία τιμή ή ακόμα και να “επαναφέρετε” ολόκληρο τον πίνακα, ας πούμε έτσι. Σε αυτές τις περιπτώσεις, η fill() σάς εξοικονομεί από βρόχους και σφάλματα off-by-one. Μπορεί να χρησιμοποιηθεί για την αντικατάσταση μέρους ή του συνόλου του πίνακα με τη δεδομένη τιμή. Ας δούμε μερικά παραδείγματα:

const heights = [1, 2, 4, 5, 6, 7, 1, 1];
heights.fill(0);
console.log(heights); // [0, 0, 0, 0, 0, 0, 0, 0]

const heights2 = [1, 2, 4, 5, 6, 7, 1, 1];
heights2.fill(0, 4);
console.log(heights2); // [1, 2, 4, 5, 0, 0, 0, 0]

Άλλες λειτουργίες που αξίζει να αναφερθούν

Αν και η παραπάνω λίστα είναι αυτό που οι περισσότεροι προγραμματιστές JavaScript καταλήγουν να συναντούν και να χρησιμοποιούν στην καριέρα τους, δεν είναι σε καμία περίπτωση πλήρης. Υπάρχουν τόσες περισσότερες δευτερεύουσες αλλά χρήσιμες συναρτήσεις (μέθοδοι) στο JavaScript που δεν θα είναι δυνατό να καλυφθούν όλες σε ένα μόνο άρθρο. Τούτου λεχθέντος, μερικά που μου έρχονται στο μυαλό είναι τα εξής:

  • ΑΝΤΙΣΤΡΟΦΗ()
  • είδος()
  • καταχωρήσεις ()
  • γέμισμα()
  • εύρημα()
  • διαμέρισμα()

Σας ενθαρρύνω να τα ψάξετε τουλάχιστον για να έχετε κάποια ιδέα ότι υπάρχουν τέτοιες ανέσεις.

συμπέρασμα

Η JavaScript είναι μια μεγάλη γλώσσα, παρά τον μικρό αριθμό βασικών εννοιών για εκμάθηση. Οι πολλές λειτουργίες (μέθοδοι) που έχουμε στη διάθεσή μας αποτελούν το μεγαλύτερο μέρος αυτού του μεγάλου μεγέθους. Ωστόσο, δεδομένου ότι η JavaScript είναι μια δευτερεύουσα γλώσσα για τους περισσότερους προγραμματιστές, δεν βουτάμε αρκετά βαθιά, χάνοντας πολλές όμορφες και χρήσιμες λειτουργίες που προσφέρει. Στην πραγματικότητα, το ίδιο ισχύει για τις έννοιες του λειτουργικού προγραμματισμού, αλλά αυτό είναι ένα θέμα για άλλη μέρα! 😅

Όποτε μπορείτε, αφιερώστε λίγο χρόνο εξερευνώντας τη βασική γλώσσα (και ει δυνατόν, διάσημες βιβλιοθήκες βοηθητικών προγραμμάτων, όπως Lodash). Ακόμη και μερικά λεπτά που αφιερώνετε στην προσπάθεια αυτή θα έχουν ως αποτέλεσμα τεράστια κέρδη παραγωγικότητας και πολύ καθαρότερο και πιο συμπαγή κώδικα.