034.3 Μάθημα 2
Πιστοποιητικό: |
Web Development Essentials |
---|---|
Έκδοση: |
1.0 |
Θέμα: |
034 Προγραμματισμός με JavaScript |
Σκοπός: |
034.3 Δομές Ελέγχου και Functions της JavaScript |
Μάθημα: |
2 απο 2 |
Εισαγωγή
Εκτός από το τυπικό σύνολο των ενσωματωμένων functions που παρέχει η γλώσσα προγραμματισμού JavaScript, οι προγραμματιστές μπορούν να γράψουν τα δικά τους εξατομικευμένα functions για να αντιστοιχίσουν ένα input σε ένα output κατάλληλο για τις ανάγκες της εφαρμογής. Τα εξατομικευμένα αυτά functions είναι βασικά ένα σύνολο ομαδοποιημένων εντολών που μπορούν να χρησιμοποιηθούν αλλού ως μέρος μιας έκφρασης.
Η χρήση functions είναι ένας καλός τρόπος για να αποφύγετε το γράψιμο διπλού κώδικα, επειδή τα functions μπορούν να κληθούν από διαφορετικές τοποθεσίες σε όλο το πρόγραμμα. Επιπλέον, η ομαδοποίηση statements σε functions διευκολύνει τη σύνδεση προσαρμοσμένων ενεργειών σε events, κάτι που αποτελεί κεντρική πτυχή του προγραμματισμού με JavaScript.
Ορισμός ενός Function
Καθώς ένα πρόγραμμα μεγαλώνει, γίνεται πιο δύσκολη η οργανώση αυτού που κάνει χωρίς τη χρήση funtions. Κάθε function έχει το δικό του scope μεταβλητών, επομένως οι μεταβλητές που ορίζονται μέσα σε ένα function θα είναι διαθέσιμες μόνο εντός του ίδιου function. Έτσι, δεν θα μπερδεύονται με μεταβλητές από άλλα functions. Οι global μεταβλητές εξακολουθούν να είναι προσβάσιμες μέσα από τα functions, αλλά ο προτιμότερος τρόπος απόδοσης τιμών εισόδου σε ένα function είναι μέσω των παραμέτρων του function. Για παράδειγμα, θα βασιστούμε στο funtion επικύρωσης πρώτων αριθμών από το προηγούμενο μάθημα:
// A naive prime number tester
// The number we want to evaluate
let candidate = 231;
// Auxiliary variable
let is_prime = true;
// Start with the lowest prime number after 1
let factor = 2;
// Keeps evaluating while factor is less than the candidate
while ( factor < candidate )
{
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
// The next number that will divide the candidate
factor++;
}
// Display the result in the console window
if ( is_prime )
{
console.log(candidate, "is prime");
}
else
{
console.log(candidate, "is not prime");
}
Εάν αργότερα στον κώδικα πρέπει να ελέγξετε εάν ένας αριθμός είναι πρώτος, θα πρέπει να επαναλάβετε τον κώδικα που έχει ήδη γραφτεί. Αυτή η πρακτική δεν συνιστάται, επειδή τυχόν διορθώσεις ή βελτιώσεις στον αρχικό κώδικα θα πρέπει να αναπαραχθούν με μη αυτόματο τρόπο παντού όπου έγινε αντιγραφή αυτού του ίδιου του κώδικα. Επιπλέον, η επανάληψη κώδικα επιβαρύνει το πρόγραμμα περιήγησης και το δίκτυο, επιβραδύνοντας πιθανώς την εμφάνιση της ιστοσελίδας. Αντί να το κάνετε αυτό, μετακινήστε τα κατάλληλα statements σε ένα function:
// A naive prime number tester function
function test_prime(candidate)
{
// Auxiliary variable
let is_prime = true;
// Start with the lowest prime number after 1
let factor = 2;
// Keeps evaluating while factor is less than the candidate
while ( factor < candidate )
{
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
// The next number that will divide the candidate
factor++;
}
// Send the answer back
return is_prime;
}
Η δήλωση του function ξεκινά με ένα function
statement, ακολουθούμενο από το όνομα του function και τις παραμέτρους του. Το όνομα του function πρέπει να ακολουθεί τους ίδιους κανόνες με τα ονόματα των μεταβλητών. Οι παράμετροι του function, γνωστά και ως function arguments, χωρίζονται με κόμμα και περικλείονται με παρένθεση.
Tip
|
Η παράθεση των arguments στη δήλωση του function δεν είναι υποχρεωτική. Τα arguments που μεταβιβάζονται σε ένα function μπορούν να ανακτηθούν από ένα array object |
Στο παράδειγμα, το function test_prime
έχει μόνο ένα argument: το candidate
argument, που είναι ο πρώτος αριθμός υποψήφιος προς δοκιμή. Τα arguments του function λειτουργούν όπως οι μεταβλητές, αλλά οι τιμές τους εκχωρούνται από το statement που καλεί το function. Για παράδειγμα, το statement test_prime(231)
θα καλέσει το function «test_prime» και θα εκχωρήσει την τιμή 231 στο argument candidate
, το οποίο στη συνέχεια θα είναι διαθέσιμο μέσα στο σώμα του function σαν μια συνηθισμένη μεταβλητή.
Εάν το statement που καλεί το function, χρησιμοποιεί απλές μεταβλητές για τις παραμέτρους του function, οι τιμές τους θα αντιγραφούν στα arguments του function. Αυτή η διαδικασία — η αντιγραφή των τιμών των παραμέτρων που χρησιμοποιούνται στο statement που καλεί το function, στις παραμέτρους που χρησιμοποιούνται μέσα στο function — ονομάζεται μεταβίβαση arguments κατά τιμή. Τυχόν τροποποιήσεις που γίνονται στο argument από το function, δεν επηρεάζουν την αρχική μεταβλητή που χρησιμοποιείται στο statement που καλεί το function. Ωστόσο, εάν το statement που καλεί το function χρησιμοποιεί σύνθετα objects ως arguments (δηλαδή, ένα object με ιδιότητες και μεθόδους) για τις παραμέτρους του function, θα μεταβιβαστούν ως αναφορά και το function θα μπορεί να τροποποιήσει το αρχικό object που χρησιμοποιείται στο statement που καλεί το function.
Τα arguments που μεταβιβάζονται κατά τιμή, καθώς και οι μεταβλητές που δηλώνονται μέσα στο function, δεν είναι ορατά έξω από αυτό. Δηλαδή, το πεδίο εφαρμογής τους περιορίζεται στο σώμα του function όπου δηλώθηκαν. Ωστόσο, τα functions συνήθως χρησιμοποιούνται για τη δημιουργία κάποιου output ορατού εκτός του function. Για να μοιραστεί μια τιμή με το function που το καλεί, ένα function ορίζει ένα return
statement.
Για παράδειγμα, το function test_prime
στο προηγούμενο παράδειγμα επιστρέφει την τιμή της μεταβλητής is_prime
. Επομένως, το function μπορεί να αντικαταστήσει τη μεταβλητή οπουδήποτε θα μπορούσε να χρησιμοποιηθεί στο αρχικό παράδειγμα:
// The number we want to evaluate
let candidate = 231;
// Display the result in the console window
if ( test_prime(candidate) )
{
console.log(candidate, "is prime");
}
else
{
console.log(candidate, "is not prime");
}
Το return
statement, όπως υποδηλώνει το όνομά της, επιστρέφει τον έλεγχο στο καλούμενο function. Επομένως, οπουδήποτε τοποθετείται η εντολή return
στο function, δεν εκτελείται τίποτα μετά από αυτήν. Έαν function μπορεί να περιέχει πολλαπλά return
statements. Αυτή η πρακτική μπορεί να είναι χρήσιμη εάν ορισμένες βρίσκονται μέσα σε block εντολών υπόθεσης, έτσι ώστε το function να εκτελεί ή να μην εκτελεί μια συγκεκριμένη εντολή return
κάθε φορά.
Ορισμένα functions ενδέχεται να μην επιστρέφουν μια τιμή, επομένως το return
statement δεν είναι υποχρεωτικό. Τα εσωτερικά statements του function εκτελούνται ανεξάρτητα από την παρουσία του, επομένως τα functions μπορούν επίσης να χρησιμοποιηθούν για την αλλαγή των τιμών των global μεταβλητών ή των περιεχομένων των objects που μεταβιβάζονται με αναφορά, για παράδειγμα. Παρά ταύτα, εάν το function δεν έχει return
statement, η προεπιλεγμένη επιστρεφόμενη τιμή ορίζεται σε undefined
: μια δεσμευμένη μεταβλητή που δεν έχει τιμή και δεν μπορεί να γραφτεί.
Function Expressions
Στη JavaScript, τα functions είναι απλώς άλλος ένας τύπος object. Έτσι, τα functions μπορούν να χρησιμοποιηθούν στο script όπως οι μεταβλητές. Αυτό το χαρακτηριστικό γίνεται σαφές όταν το function δηλώνεται χρησιμοποιώντας μια εναλλακτική σύνταξη, που ονομάζεται function expressions:
let test_prime = function(candidate)
{
// Auxiliary variable
let is_prime = true;
// Start with the lowest prime number after 1
let factor = 2;
// Keeps evaluating while factor is less than the candidate
while ( factor < candidate )
{
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
// The next number that will divide the candidate
factor++;
}
// Send the answer back
return is_prime;
}
Η μόνη διαφορά μεταξύ αυτού του παραδείγματος και της δήλωσης συνάρτησης στο προηγούμενο παράδειγμα βρίσκεται στην πρώτη γραμμή: let test_prime = function(candidate)
αντί για function test_prime(candidate)
. Σε ένα function expression, το όνομα test_prime
χρησιμοποιείται για το object που περιέχει το function και όχι για την ονομασία του ίδιου του function. Τα functions που ορίζονται στα function expressions καλούνται με τον ίδιο τρόπο όπως τα functions που ορίζονται χρησιμοποιώντας τη σύνταξη δήλωσης. Ωστόσο, ενώ οι δηλωμένες συναρτήσεις μπορούν να κληθούν πριν ή μετά τη δήλωσή τους, τα function expressions μπορούν να κληθούν μόνο μετά την αρχικοποίησή τους. Όπως και με τις μεταβλητές, η κλήση ενός function που ορίζεται σε ένα expression πριν από την αρχικοποίησή της θα προκαλέσει ένα σφάλμα αναφοράς.
Function Recursion
Εκτός από την εκτέλεση statements και την κλήση builtin functions, τα εξατομικευμένα functions μπορούν επίσης να καλέσουν άλλες εξατομικευμένα functions, συμπεριλαμβανομένων των ίδιων. Η κλήση ενός function από τον εαυτό της ονομάζεται function recursion [αναδρομή]. Ανάλογα με τον τύπο του προβλήματος που προσπαθείτε να λύσετε, η χρήση αναδρομικών functions μπορεί να είναι πιο απλή από τη χρήση ένθετων loops για την εκτέλεση επαναλαμβανόμενων εργασιών.
Μέχρι στιγμής, γνωρίζουμε πώς να χρησιμοποιήσουμε ένα function για να ελέγξουμε αν ένας δεδομένος αριθμός είναι πρώτος. Τώρα ας υποθέσουμε ότι θέλετε να βρείτε τον επόμενο πρώτο αριθμό, μετά από έναν δεδομένο αριθμό. Θα μπορούσατε να χρησιμοποιήσετε ένα while
loop για να αυξήσετε τον υποψήφιο αριθμό και να γράψετε ένα ένθετο loop που θα αναζητήσει ακέραιους παράγοντες για αυτόν τον υποψήφιο:
// This function returns the next prime number
// after the number given as its only argument
function next_prime(from)
{
// We are only interested in the positive primes,
// so we will consider the number 2 as the next
// prime after any number less than two.
if ( from < 2 )
{
return 2;
}
// The number 2 is the only even positive prime,
// so it will be easier to treat it separately.
if ( from == 2 )
{
return 3;
}
// Decrement "from" if it is an even number
if ( from % 2 == 0 )
{
from--;
}
// Start searching for primes greater then 3.
// The prime candidate is the next odd number
let candidate = from + 2;
// "true" keeps the loop going until a prime is found
while ( true )
{
// Auxiliary control variable
let is_prime = true;
// "candidate" is an odd number, so the loop will
// try only the odd factors, starting with 3
for ( let factor = 3; factor < candidate; factor = factor + 2 )
{
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime.
// Test the next candidate
is_prime = false;
break;
}
}
// End loop and return candidate if it is prime
if ( is_prime )
{
return candidate;
}
// If prime not found yet, try the next odd number
candidate = candidate + 2;
}
}
let from = 1024;
console.log("The next prime after", from, "is", next_prime(from));
Σημειώστε ότι πρέπει να χρησιμοποιήσουμε μια συνθήκη σταθεράς για το while
loop (την έκφραση true
μέσα στην παρένθεση) και τη βοηθητική μεταβλητή is_prime
για να ξέρουμε πότε να σταματήσουμε το loop. Αν και αυτή η λύση είναι σωστή, η χρήση ένθετων loops δεν είναι τόσο κομψή όσο η χρήση αναδρομής για την εκτέλεση της ίδιας εργασίας:
// This function returns the next prime number
// after the number given as its only argument
function next_prime(from)
{
// We are only interested in the positive primes,
// so we will consider the number 2 as the next
// prime after any number less than two.
if ( from < 2 )
{
return 2;
}
// The number 2 is the only even positive prime,
// so it will be easier to treat it separately.
if ( from == 2 )
{
return 3;
}
// Decrement "from" if it is an even number
if ( from % 2 == 0 )
{
from--;
}
// Start searching for primes greater then 3.
// The prime candidate is the next odd number
let candidate = from + 2;
// "candidate" is an odd number, so the loop will
// try only the odd factors, starting with 3
for ( let factor = 3; factor < candidate; factor = factor + 2 )
{
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime.
// Call the next_prime function recursively, this time
// using the failed candidate as the argument.
return next_prime(candidate);
}
}
// "candidate" is not divisible by any integer factor other
// than 1 and itself, therefore it is a prime number.
return candidate;
}
let from = 1024;
console.log("The next prime after", from, "is", next_prime(from));
Και τα δύο παραδείγματα του next_prime
επιστρέφουν τον επόμενο πρώτο αριθμό μετά τον αριθμό που δίνεται ως μοναδικό argument (from
). Το αναδρομικό παράδειγμα, όπως και το προηγούμενο παράδειγμα, ξεκινά ελέγχοντας τις ειδικές περιπτώσεις (δηλαδή αριθμούς μικρότερους ή ίσους με δύο). Στη συνέχεια, αυξάνει τον υποψήφιο και αρχίζει να αναζητά τυχόν ακέραιους παράγοντες με το for
loop (προσέξτε ότι το while
loop δεν υπάρχει πια). Σε εκείνο το σημείο, ο μόνος άρτιος πρώτος αριθμός έχει ήδη δοκιμαστεί, οπότε ο υποψήφιος και οι πιθανοί συντελεστές του αυξάνονται κατά δύο. (Ένας μονός αριθμός συν δύο είναι ο επόμενος περιττός αριθμός.)
Υπάρχουν μόνο δύο τρόποι εξόδου από το for
loop στο παράδειγμα. Εάν ελέγχονται όλοι οι πιθανοί παράγοντες και κανένας από αυτούς δεν έχει υπόλοιπο ίσο με το μηδέν κατά τη διαίρεση του υποψηφίου, το for
loop ολοκληρώνεται και το function επιστρέφει τον υποψήφιο ως τον επόμενο πρώτο αριθμό μετά το from
. Διαφορετικά, εάν ο factor
είναι ένας ακέραιος παράγοντας του candidate
(candidate % factor == 0
), η επιστρεφόμενη τιμή προέρχεται από το function next_prime
που καλείται αναδρομικά, αυτή τη φορά με τον επαυξημένο candidate
ως την from
παράμετρό του. Οι κλήσεις για next_prime
θα στοιβάζονται η μία πάνω στην άλλη, έως ότου ένας υποψήφιος δεν εμφανίσει τελικά κανέναν ακέραιο παράγοντα. Στη συνέχεια, το τελευταίο next_prime
instance που περιέχει τον πρώτο αριθμό θα το επιστρέψει στο προηγούμενο next_prime
instance και επομένως διαδοχικά στo πρώτo next_prime
instance. Παρόλο που κάθε κληση του function χρησιμοποιεί τα ίδια ονόματα για τις μεταβλητές, οι κλήσεις είναι απομονωμένες η μία από την άλλη, επομένως οι μεταβλητές τους διατηρούνται χωριστές στη μνήμη του υπολογιστή.
Καθοδηγούμενες Ασκήσεις
-
Τι είδους overhead μπορούν να μετριάσουν οι προγραμματιστές χρησιμοποιώντας functions;
-
Ποια είναι η διαφορά μεταξύ των function arguments που μεταβιβάζονται κατά τιμή και των function arguments που μεταβιβάζονται με αναφορά;
-
Ποια τιμή θα χρησιμοποιηθεί ως output ενός εξατομικευμένου function εάν δεν έχει return statement;
Ασκήσεις Εξερεύνησης
-
Ποια είναι η πιθανή αιτία ενός Uncaught Reference Error που εκδόθηκε κατά την κλήση ενός function που έχει δηλωθεί με τη σύνταξη expression;
-
Γράψτε ένα function που ονομάζεται
multiples_of
και που λαμβάνει τρία arguments:factor
,from
καιto
. Μέσα στο function, χρησιμοποιήστε την εντολήconsole.log()
για να εκτυπώσετε όλα τα πολλαπλάσια τουfactor
που βρίσκονται μεταξύfrom
καιto
.
Σύνοψη
Αυτό το μάθημα καλύπτει τον τρόπο σύνταξης εξατομικευμένων functions στον JavaScript κώδικα. Τα εξατομικευμένα function επιτρέπουν στον προγραμματιστή να διαιρεί την εφαρμογή σε “chunks” επαναχρησιμοποιήσιμου κώδικα, διευκολύνοντας τη σύνταξη και τη συντήρηση μεγαλύτερων προγραμμάτων. Το μάθημα περιλαμβάνει τις ακόλουθες έννοιες και διαδικασίες:
-
Πώς να ορίσετε ενα εξατομικευμένο function: δηλώσεις function και function expressions.
-
Χρησιμοποίηση παραμέτρων ως function input.
-
Χρησιμοποίηση του
return
statement για τον ορισμό του function output. -
Function recursion.
Απαντήσεις στις Καθοδηγούμενες Ασκήσεις
-
Τι είδους overhead μπορούν να μετριάσουν οι προγραμματιστές χρησιμοποιώντας functions;
Τα functions μας επιτρέπουν να επαναχρησιμοποιούμε τον κώδικα, κάτι που διευκολύνει τη συντήρηση του κώδικα. Ένα μικρότερο script αρχείο εξοικονομεί επίσης μνήμη στον υπολογιστή αλλά και χρόνο λήψης απο το internet.
-
Ποια είναι η διαφορά μεταξύ των function arguments που μεταβιβάζονται κατά τιμή και των function arguments που μεταβιβάζονται με αναφορά;
Όταν μεταβιβάζονται κατά τιμή, το argument αντιγράφεται στο function και το function δεν μπορεί να τροποποιήσει την αρχική μεταβλητή κατά της κλήση της. Όταν μεταβιβάζονται μέσω αναφοράς, το function μπορεί να χειριστεί την αρχική μεταβλητή που χρησιμοποιείται κατά την κλήση της.
-
Ποια τιμή θα χρησιμοποιηθεί ως output ενός εξατομικευμένου function εάν δεν έχει return statement;
Η επιστρεφόμενη τιμή θα οριστεί σε
undefined
.
Απαντήσεις στις Ασκήσεις Εξερεύνησης
-
Ποια είναι η πιθανή αιτία ενός Uncaught Reference Error που εκδόθηκε κατά την κλήση ενός function που έχει δηλωθεί με τη σύνταξη expression;
Το function κλήθηκε πριν από τη δήλωσή του στο script αρχείο.
-
Γράψτε ένα function που ονομάζεται
multiples_of
και που λαμβάνει τρία arguments:factor
,from
καιto
. Μέσα στο function, χρησιμοποιήστε την εντολήconsole.log()
για να εκτυπώσετε όλα τα πολλαπλάσια τουfactor
που βρίσκονται μεταξύfrom
καιto
.function multiples_of(factor, from, to) { for ( let number = from; number <= to; number++ ) { if ( number % factor == 0 ) { console.log(factor, "*", number / factor, "=", number); } } }