Απώλεια περιβάλλοντος σε JavaScript
Ας υποθέσουμε ότι έχουμε μια συνάρτηση εντός συνάρτησης. Ας
ονομάσουμε την εξωτερική συνάρτηση parent, και
την εσωτερική - child:
function parent() {
function child() {
}
}
Από προηγούμενα μαθήματα γνωρίζετε ότι εάν ορίσετε οποιαδήποτε μεταβλητή στην εξωτερική συνάρτηση - θα είναι προσβάσιμη στην εσωτερική:
function parent() {
let str = 'abcde';
function child() {
console.log(str); // θα τυπώσει 'abcde'
}
child(); // καλούμε την εσωτερική συνάρτηση
}
parent(); // καλούμε την εξωτερική συνάρτηση
Υπάρχει, ωστόσο, μια απόχρωση: η εσωτερική συνάρτηση έχει
πρόσβαση σε όλες τις μεταβλητές της εξωτερικής, αλλά δεν
έχει πρόσβαση στο this. Δηλαδή: εάν
η εξωτερική συνάρτηση είναι δεσμευμένη σε κάποιο DOM
στοιχείο, τότε το this σε αυτήν θα δείχνει
σε αυτό το στοιχείο, αλλά το this της εσωτερικής
συνάρτησης - δεν θα δείχνει!
Σε τι θα δείχνει τότε το this
της εσωτερικής συνάρτησης; Απάντηση: θα είναι ίσο με
undefined (σε αυστηρή λειτουργία), αφού
η συνάρτηση δεν είναι δεσμευμένη σε τίποτα.
Ας το δοκιμάσουμε στην πράξη. Ας υποθέσουμε ότι μας δίνεται ένα πεδίο εισόδου:
<input id="elem" value="text">
Ας δεσμεύσουμε σε αυτό το πεδίο εισόδου τη συνάρτηση parent,
η οποία θα καλείται όταν το πεδίο εισόδου χάσει την εστίαση:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
// Θα κληθεί όταν χαθεί η εστίαση:
function parent() {
// εδώ θα υπάρχει κάποιος κώδικας
function child() {
// εδώ θα υπάρχει κάποιος κώδικας
}
child(); // καλούμε την θυγατρική συνάρτηση
}
Ας τυπώσουμε το περιεχόμενο του this στην
κονσόλα σε δύο σημεία: μέσα στη συνάρτηση parent
και μέσα στη συνάρτηση child:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
function parent() {
console.log(this); // θα τυπώσει αναφορά στο πεδίο εισόδου μας
function child() {
console.log(this); // θα τυπώσει undefined
}
child();
}
Εκτελέστε αυτόν τον κώδικα, αφήστε το πεδίο εισόδου να χάσει την εστίαση
και κοιτάξτε στην κονσόλα - θα δείτε ότι
το πρώτο console.log θα τυπώσει στην κονσόλα
την αναφορά στο πεδίο εισόδου μας, και το δεύτερο - απλά undefined.
Μια τέτοια κατάσταση, όταν το this με απροσδόκητο
τρόπο δεν δείχνει σε αυτό που χρειαζόμαστε, ονομάζεται απώλεια περιβάλλοντος.
Ας υποθέσουμε τώρα ότι και στις δύο συναρτήσεις
θα τυπώνουμε το value του πεδίου εισόδου. Προσδιορίστε,
τι θα τυπωθεί στις γραμμές κώδικα, που σημειώνονται
με σχόλια:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
function parent() {
console.log(this.value); // τι θα τυπώσει;
function child() {
console.log(this.value); // τι θα τυπώσει;
}
child();
}