Ο πλήρης οδηγός για αυτό σε JavaScript

Στο JavaScript, κάθε λειτουργία έχει μια thisαναφορά που δημιουργείται αυτόματα όταν την δηλώνετε.

Τα JavaScript thisείναι αρκετά παρόμοια με μια thisαναφορά σε άλλες γλώσσες που βασίζονται στην τάξη, όπως η Java ή το C # (το JavaScript είναι μια γλώσσα που βασίζεται σε πρωτότυπο και δεν υπάρχει έννοια "κλάσης"): Υποδεικνύει το αντικείμενο που καλεί στη συνάρτηση (αυτό το αντικείμενο καλείται μερικές φορές ως πλαίσιο ). Ωστόσο, στοthis JavaScript, η αναφορά εσωτερικών συναρτήσεων μπορεί να συνδεθεί με διαφορετικά αντικείμενα ανάλογα με το πού καλείται η συνάρτηση .

Ακολουθούν 5 βασικοί κανόνες για thisδέσμευση σε JavaScript:

Κανόνας 1

Όταν μια συνάρτηση καλείται στο καθολικό πεδίο, η thisαναφορά δεσμεύεται από προεπιλογή στο καθολικό αντικείμενο ( windowστο πρόγραμμα περιήγησης ή globalστο Node.js). Για παράδειγμα:

function foo() { this.a = 2; } foo(); console.log(a); // 2

Σημείωση: Εάν δηλώσετε τη foo()συνάρτηση παραπάνω σε αυστηρή λειτουργία, τότε καλείτε αυτήν τη λειτουργία σε παγκόσμιο πεδίο, thisθα είναι undefinedκαι η ανάθεση this.a = 2θα ρίξει Uncaught TypeErrorεξαίρεση.

Κανόνας 2

Ας εξετάσουμε το παρακάτω παράδειγμα:

function foo() { this.a = 2; } const obj = { foo: foo }; obj.foo(); console.log(obj.a); // 2

Σαφώς, στο παραπάνω απόσπασμα, η foo()συνάρτηση καλείται με περιβάλλον είναι objαντικείμενο και η thisαναφορά τώρα είναι δεσμευμένη obj. Έτσι, όταν μια συνάρτηση καλείται με ένα αντικείμενο περιβάλλοντος, η thisαναφορά θα δεσμεύεται σε αυτό το αντικείμενο.

Κανόνας 3

.call, .applyκαι .bindμπορούν όλα να χρησιμοποιηθούν στον ιστότοπο κλήσεων για να δεσμεύονται ρητά this. Η χρήση .bind(this)είναι κάτι που μπορεί να δείτε σε πολλά στοιχεία του React.

const foo = function() { console.log(this.bar) } foo.call({ bar: 1 }) // 1

Ακολουθεί ένα γρήγορο παράδειγμα για το πώς χρησιμοποιείται το καθένα για τη δέσμευση this:

  • .call(): fn.call(thisObj, fnParam1, fnParam2)
  • .apply(): fn.apply(thisObj, [fnParam1, fnParam2])
  • .bind(): const newFn = fn.bind(thisObj, fnParam1, fnParam2)

Κανόνας 4

function Point2D(x, y) { this.x = x; this.y = y; } const p1 = new Point2D(1, 2); console.log(p1.x); // 1 console.log(p1.y); // 2

Το πράγμα που πρέπει να παρατηρήσετε ότι είναι η Point2Dσυνάρτηση που λέγεται με τη newλέξη-κλειδί και η thisαναφορά δεσμεύεται να p1αντιταχθεί. Έτσι, όταν μια συνάρτηση καλείται με newλέξη-κλειδί, θα δημιουργήσει ένα νέο αντικείμενο και η thisαναφορά θα δεσμευτεί σε αυτό το αντικείμενο.

Σημείωση: Καθώς καλείτε μια συνάρτηση με newλέξη-κλειδί, την ονομάζουμε επίσης ως συνάρτηση κατασκευαστή .

Κανόνας 5

Το JavaScript καθορίζει την τιμή του thisχρόνου εκτέλεσης, με βάση το τρέχον πλαίσιο. Έτσι this, μερικές φορές μπορεί να δείξει κάτι άλλο από αυτό που περιμένετε.

Εξετάστε αυτό το παράδειγμα μιας κατηγορίας Cat με μια μέθοδο που ονομάζεται makeSound(), ακολουθώντας το μοτίβο στον Κανόνα 4 (παραπάνω) με μια συνάρτηση κατασκευαστή και τη newλέξη-κλειδί.

const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.makeSound(); // Fat Daddy says: Mrrooowww

Τώρα ας προσπαθήσουμε να δώσουμε στη γάτα έναν τρόπο στους annoy()ανθρώπους επαναλαμβάνοντας τον ήχο του 100 φορές, κάθε μισό δευτερόλεπτο.

const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(function() { this.makeSound(); // <-- this line fails with `this.makeSound is not a function` count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();

Αυτό δεν λειτουργεί γιατί στο πλαίσιο της setIntervalεπανάκλησης δημιουργήσαμε ένα νέο πλαίσιο με παγκόσμιο εύρος, οπότε thisδεν επισημαίνουμε πλέον την παρουσία γατών μας. Σε ένα πρόγραμμα περιήγησης ιστού, thisθα δείξει αντ 'αυτού το αντικείμενο Window, το οποίο δεν έχει makeSound()μέθοδο.

Μερικοί τρόποι για να λειτουργήσει:

  1. Πριν από τη δημιουργία του νέου περιβάλλοντος, αντιστοιχίστε thisσε μια τοπική μεταβλητή με το όνομα meή self, ή οτιδήποτε άλλο θέλετε, και χρησιμοποιήστε αυτήν τη μεταβλητή μέσα στην επιστροφή κλήσης.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const self = this; const t = setInterval(function() { self.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();
  1. Με το ES6 μπορείτε να αποφύγετε την εκχώρηση thisσε μια τοπική μεταβλητή χρησιμοποιώντας μια συνάρτηση βέλους, η οποία συνδέεται thisμε το περιβάλλον του περιβάλλοντος κώδικα όπου ορίζεται.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(() => { this.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();