portaldacalheta.pt
  • Κύριος
  • Επενδυτές & Χρηματοδότηση
  • Σχεδιασμός Διεπαφής Χρήστη
  • Τεχνολογία
  • Διαχείριση Έργου
Διεπαφή Ιστού

Πρωτότυπες αλυσίδες JavaScript, αλυσίδες πεδίου και απόδοση: Τι πρέπει να γνωρίζετε



JavaScript: Περισσότερο από ό, τι συναντά το βλέμμα

Το JavaScript μπορεί να φαίνεται σαν μια πολύ εύκολη γλώσσα για πρώτη φορά. Ίσως λόγω της ευέλικτης σύνταξής του. Ή ίσως λόγω της ομοιότητάς του με άλλες γνωστές γλώσσες όπως η Java. Ή ίσως επειδή έχει τόσο λίγους τύπους δεδομένων σε σύγκριση με γλώσσες όπως Java, Ruby ή .NET.

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



Στο JavaScript, οι αναζητήσεις δεδομένων διέπονται από δύο πράγματα: πρωτότυπη κληρονομιά και αλυσίδα πεδίου . Ως προγραμματιστής, η σαφής κατανόηση αυτών των δύο μηχανισμών είναι απαραίτητη, καθώς κάτι τέτοιο μπορεί να βελτιώσει τη δομή και συχνά την απόδοση του κώδικα σας.



Αναζήτηση ιδιοκτησίας μέσω της αλυσίδας πρωτοτύπων

Κατά την πρόσβαση σε μια ιδιότητα σε μια γλώσσα που βασίζεται σε πρωτότυπα όπως το JavaScript, πραγματοποιείται μια δυναμική αναζήτηση που περιλαμβάνει διαφορετικά επίπεδα μέσα στο πρωτότυπο δέντρο του αντικειμένου.



Σε JavaScript, κάθε συνάρτηση είναι ένα αντικείμενο. Όταν καλείται μια συνάρτηση με το new τελεστής, δημιουργείται ένα νέο αντικείμενο. Για παράδειγμα:

function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } var p1 = new Person('John', 'Doe'); var p2 = new Person('Robert', 'Doe');

Στο παραπάνω παράδειγμα, p1 και p2 είναι δύο διαφορετικά αντικείμενα, το καθένα δημιουργήθηκε χρησιμοποιώντας το Person λειτουργούν ως κατασκευαστής. Είναι ανεξάρτητες περιπτώσεις Person, όπως αποδεικνύεται από αυτό το απόσπασμα κώδικα:



console.log(p1 instanceof Person); // prints 'true' console.log(p2 instanceof Person); // prints 'true' console.log(p1 === p2); // prints 'false'

Δεδομένου ότι οι λειτουργίες JavaScript είναι αντικείμενα, μπορούν να έχουν ιδιότητες. Μια ιδιαίτερα σημαντική ιδιότητα που έχει κάθε συνάρτηση ονομάζεται prototype.

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



Η σχέση μεταξύ πρωτοτύπου JavaScript και αλυσίδας πεδίου είναι σημαντική

Το πρωτότυπο κάθε συνάρτησης μπορεί να επεκταθεί για να ορίσει τις δικές του προσαρμοσμένες μεθόδους και ιδιότητες.



Όταν δημιουργείτε ένα αντικείμενο (επικαλούμενος τη συνάρτηση χρησιμοποιώντας τον τελεστή new), κληρονομεί όλες τις ιδιότητες στο πρωτότυπο αυτής της συνάρτησης. Λάβετε υπόψη, ωστόσο, ότι αυτές οι περιπτώσεις δεν θα έχουν άμεση πρόσβαση στο prototype αντικείμενο αλλά μόνο στις ιδιότητές του. Για παράδειγμα:

// Extending the Person prototype from our earlier example to // also include a 'getFullName' method: Person.prototype.getFullName = function() { return this.firstName + ' ' + this.lastName; } // Referencing the p1 object from our earlier example console.log(p1.getFullName()); // prints 'John Doe' // but p1 can’t directly access the 'prototype' object... console.log(p1.prototype); // prints 'undefined' console.log(p1.prototype.getFullName()); // generates an error

Υπάρχει ένα σημαντικό και κάπως λεπτό σημείο εδώ: Ακόμα κι αν p1 δημιουργήθηκε πριν από το getFullName ορίστηκε μέθοδος, θα εξακολουθεί να έχει πρόσβαση σε αυτό, επειδή το πρωτότυπο του είναι το Person πρωτότυπο.



(Αξίζει να σημειωθεί ότι τα προγράμματα περιήγησης αποθηκεύουν επίσης μια αναφορά στο πρωτότυπο οποιουδήποτε αντικειμένου σε μια ιδιότητα __proto__, αλλά είναι πραγματικά κακή πρακτική για άμεση πρόσβαση στο πρωτότυπο μέσω του __proto__ ιδιοκτησία, καθώς δεν αποτελεί μέρος του προτύπου Προδιαγραφή γλώσσας ECMAScript , οπότε μην το κάνετε! )

Από το p1 παρουσία του Person το αντικείμενο δεν έχει το ίδιο άμεση πρόσβαση στο prototype αντικείμενο, αν θέλουμε αντικατάσταση getFullName στο p1, θα το κάναμε ως εξής:



// We reference p1.getFullName, *NOT* p1.prototype.getFullName, // since p1.prototype does not exist: p1.getFullName = function(){ return 'I am anonymous'; }

Τώρα p1 έχει το δικό του getFullName ιδιοκτησία. Αλλά το p2 Το παράδειγμα (δημιουργήθηκε στο προηγούμενο παράδειγμα) δεν έχει οποιαδήποτε τέτοια ιδιοκτησία. Επομένως, επικαλούμενη p1.getFullName() έχει πρόσβαση στο getFullName μέθοδος του p1 το ίδιο το παράδειγμα, κατά την επίκληση p2.getFullName() ανεβαίνει την πρωτότυπη αλυσίδα στο Person πρωτότυπο αντικείμενο προς επίλυση getFullName:

console.log(p1.getFullName()); // prints 'I am anonymous' console.log(p2.getFullName()); // prints 'Robert Doe'

Δείτε πώς σχετίζονται τα P1 και P2 με το πρωτότυπο Person σε αυτό το παράδειγμα πρωτότυπου JavaScript.

Ένα άλλο σημαντικό πράγμα που πρέπει να γνωρίζετε είναι ότι είναι επίσης δυνατό δυναμικά αλλάξτε το πρωτότυπο ενός αντικειμένου. Για παράδειγμα:

function Parent() { this.someVar = 'someValue'; }; // extend Parent’s prototype to define a 'sayHello' method Parent.prototype.sayHello = function(){ console.log('Hello'); }; function Child(){ // this makes sure that the parent's constructor is called and that // any state is initialized correctly. Parent.call(this); }; // extend Child's prototype to define an 'otherVar' property... Child.prototype.otherVar = 'otherValue'; // ... but then set the Child's prototype to the Parent prototype // (whose prototype doesn’t have any 'otherVar' property defined, // so the Child prototype no longer has ‘otherVar’ defined!) Child.prototype = Object.create(Parent.prototype); var child = new Child(); child.sayHello(); // prints 'Hello' console.log(child.someVar); // prints 'someValue' console.log(child.otherVar); // prints 'undefined'

Όταν χρησιμοποιείτε πρωτότυπη κληρονομιά, θυμηθείτε να ορίσετε ιδιότητες στο πρωτότυπο μετά είτε κληρονόμησε από τη γονική τάξη είτε έχει καθορίσει ένα εναλλακτικό πρωτότυπο.

Αυτό το διάγραμμα δείχνει ένα παράδειγμα της σχέσης μεταξύ πρωτοτύπων JavaScript σε μια αλυσίδα πρωτοτύπων.

Συνοψίζοντας, οι αναζητήσεις ιδιοτήτων μέσω της αλυσίδας πρωτότυπου JavaScript λειτουργούν ως εξής:

  • Εάν το αντικείμενο έχει μια ιδιότητα με το δεδομένο όνομα, επιστρέφεται η τιμή. (Ο hasOwnProperty μέθοδος μπορεί να χρησιμοποιηθεί για να ελέγξει εάν ένα αντικείμενο έχει μια συγκεκριμένη ονομασία ιδιότητα.)
  • Εάν το αντικείμενο δεν έχει την ονομαστική ιδιότητα, ελέγχεται το πρωτότυπο του αντικειμένου
  • Δεδομένου ότι το πρωτότυπο είναι επίσης αντικείμενο, εάν δεν περιέχει ούτε την ιδιότητα, ελέγχεται το πρωτότυπο του γονέα του.
  • Αυτή η διαδικασία συνεχίζει την πρωτότυπη αλυσίδα μέχρι να βρεθεί η ιδιότητα.
  • Εάν Object.prototype έχει επιτευχθεί και δεν διαθέτει ούτε την ιδιότητα, η ιδιότητα θεωρείται undefined.

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

Μεταβλητές αναζητήσεις μέσω της αλυσίδας πεδίου

Ένας άλλος μηχανισμός αναζήτησης στο JavaScript βασίζεται στο πεδίο εφαρμογής.

Για να κατανοήσετε πώς λειτουργεί αυτό, είναι απαραίτητο να εισαγάγετε την έννοια του πλαίσιο εκτέλεσης .

είναι το llc μου s ή c corp;

Στο JavaScript, υπάρχουν δύο τύποι πλαισίων εκτέλεσης:

  • Παγκόσμιο πλαίσιο, που δημιουργήθηκε όταν ξεκινά μια διαδικασία JavaScript
  • Τοπικό περιβάλλον, που δημιουργείται όταν καλείται μια συνάρτηση

Τα περιβάλλοντα εκτέλεσης οργανώνονται σε μια στοίβα. Στο κάτω μέρος της στοίβας, υπάρχει πάντα το παγκόσμιο πλαίσιο, το οποίο είναι μοναδικό για κάθε πρόγραμμα JavaScript. Κάθε φορά που συναντά μια συνάρτηση, δημιουργείται ένα νέο πλαίσιο εκτέλεσης και ωθείται στην κορυφή της στοίβας. Μόλις ολοκληρωθεί η εκτέλεση της λειτουργίας, το περιβάλλον της βγαίνει από τη στοίβα.

Εξετάστε τον ακόλουθο κώδικα:

// global context var message = 'Hello World'; var sayHello = function(n){ // local context 1 created and pushed onto context stack var i = 0; var innerSayHello = function() { // local context 2 created and pushed onto context stack console.log((i + 1) + ': ' + message); // local context 2 popped off of context stack } for (i = 0; i

Σε κάθε πλαίσιο εκτέλεσης υπάρχει ένα ειδικό αντικείμενο που ονομάζεται a αλυσίδα πεδίου που χρησιμοποιείται για την επίλυση μεταβλητών. Μια αλυσίδα πεδίων είναι ουσιαστικά μια στοίβα προσβάσιμων περιοχών, από το πιο άμεσο πλαίσιο έως το παγκόσμιο πλαίσιο. (Για να είμαστε λίγο πιο ακριβείς, το αντικείμενο στην κορυφή της στοίβας ονομάζεται Αντικείμενο ενεργοποίησης που περιέχει αναφορές στις τοπικές μεταβλητές για τη συνάρτηση που εκτελείται, τα ορίσματα συνάρτησης με όνομα και δύο 'ειδικά' αντικείμενα: this και arguments.) Για παράδειγμα:

Ο τρόπος με τον οποίο η αλυσίδα πεδίου σχετίζεται με τα αντικείμενα περιγράφεται σε αυτό το παράδειγμα JavaScript.

Σημειώστε στο παραπάνω διάγραμμα πώς this δείχνει το window αντικείμενο από προεπιλογή και επίσης πώς το καθολικό περιβάλλον περιέχει παραδείγματα άλλων αντικειμένων όπως console και location.

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

Είναι επίσης σημαντικό να σημειωθεί ότι ένα νέο πεδίο προστίθεται στην αλυσίδα πεδίου όταν ένα try-catch μπλοκ ή a with συναντάμε μπλοκ. Σε οποιαδήποτε από αυτές τις περιπτώσεις, δημιουργείται ένα νέο αντικείμενο και τοποθετείται στην κορυφή της αλυσίδας πεδίου:

function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; }; function persist(person) { with (person) { // The 'person' object was pushed onto the scope chain when we // entered this 'with' block, so we can simply reference // 'firstName' and 'lastName', rather than person.firstName and // person.lastName if (!firstName) { throw new Error('FirstName is mandatory'); } if (!lastName) { throw new Error('LastName is mandatory'); } } try { person.save(); } catch(error) { // A new scope containing the 'error' object is accessible here console.log('Impossible to store ' + person + ', Reason: ' + error); } } var p1 = new Person('John', 'Doe'); persist(p1);

Για να κατανοήσετε πλήρως τον τρόπο με τον οποίο εμφανίζονται οι μεταβλητές αναζητήσεις βάσει εύρους, είναι σημαντικό να έχετε υπόψη ότι στο JavaScript δεν υπάρχουν επί του παρόντος πεδία σε επίπεδο μπλοκ. Για παράδειγμα:

for (var i = 0; i <10; i++) { /* ... */ } // 'i' is still in scope! console.log(i); // prints '10'

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

Αξίζει να σημειωθεί, ωστόσο, ότι η υποστήριξη για πεδία σε επίπεδο μπλοκ μπαίνει στο JavaScript μέσω του νέου let λέξη-κλειδί. Το let Η λέξη-κλειδί είναι ήδη διαθέσιμη στο JavaScript 1.7 και πρόκειται να γίνει επίσημα υποστηριζόμενη λέξη-κλειδί JavaScript από το ECMAScript 6.

Επιπτώσεις απόδοσης JavaScript

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

Οι λειτουργίες αναζήτησης που έχουμε περιγράψει σε αυτό το παράδειγμα, είτε βασίζονται στην πρωτότυπη αλυσίδα είτε στην αλυσίδα πεδίου, επαναλαμβάνονται κάθε ώρα πρόσβασης σε μια ιδιότητα ή μεταβλητή. Όταν αυτή η αναζήτηση πραγματοποιείται εντός βρόχων ή άλλων εντατικών λειτουργιών, μπορεί να έχει σημαντικές επιπτώσεις απόδοσης JavaScript, ειδικά υπό το πρίσμα της μονής σπείρας της γλώσσας που εμποδίζει την ταυτόχρονη εμφάνιση πολλαπλών λειτουργιών.

Εξετάστε το ακόλουθο παράδειγμα:

var start = new Date().getTime(); function Parent() { this.delta = 10; }; function ChildA(){}; ChildA.prototype = new Parent(); function ChildB(){} ChildB.prototype = new ChildA(); function ChildC(){} ChildC.prototype = new ChildB(); function ChildD(){}; ChildD.prototype = new ChildC(); function ChildE(){}; ChildE.prototype = new ChildD(); function nestedFn() { var child = new ChildE(); var counter = 0; for(var i = 0; i <1000; i++) { for(var j = 0; j < 1000; j++) { for(var k = 0; k < 1000; k++) { counter += child.delta; } } } console.log('Final result: ' + counter); } nestedFn(); var end = new Date().getTime(); var diff = end - start; console.log('Total time: ' + diff + ' milliseconds');

Σε αυτό το παράδειγμα, έχουμε ένα μακρύ δέντρο κληρονομιάς και τρεις ένθετους βρόχους. Μέσα στον βαθύτερο βρόχο, η μεταβλητή μετρητή αυξάνεται με την τιμή delta. Αλλά delta βρίσκεται σχεδόν στην κορυφή του δέντρου κληρονομιάς! Αυτό σημαίνει ότι κάθε φορά child.delta έχει πρόσβαση, το πλήρες δέντρο πρέπει να πλοηγηθεί από κάτω προς τα πάνω. Αυτό μπορεί να έχει πολύ αρνητικό αντίκτυπο στην απόδοση.

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

function nestedFn() { var child = new ChildE(); var counter = 0; var delta = child.delta; // cache child.delta value in current scope for(var i = 0; i <1000; i++) { for(var j = 0; j < 1000; j++) { for(var k = 0; k < 1000; k++) { counter += delta; // no inheritance tree traversal needed! } } } console.log('Final result: ' + counter); } nestedFn(); var end = new Date().getTime(); var diff = end - start; console.log('Total time: ' + diff + ' milliseconds');

Φυσικά, αυτή η συγκεκριμένη τεχνική είναι βιώσιμη μόνο σε ένα σενάριο όπου είναι γνωστό ότι η τιμή child.delta δεν θα αλλάξει κατά την εκτέλεση των βρόχων. Διαφορετικά, το τοπικό αντίγραφο θα πρέπει να ενημερωθεί με την τρέχουσα τιμή.

Εντάξει, ας τρέξουμε και τις δύο εκδόσεις του nestedFn μέθοδο και δείτε εάν υπάρχει σημαντική διαφορά απόδοσης μεταξύ των δύο.

Θα ξεκινήσουμε τρέχοντας το πρώτο παράδειγμα στο a node.js REPL :

[email protected] :~$ node test.js Final result: 10000000000 Total time: 8270 milliseconds

Χρειάζεται περίπου 8 δευτερόλεπτα για να τρέξει. Αυτό είναι πολύ καιρό.

Τώρα ας δούμε τι συμβαίνει όταν εκτελούμε τη βελτιστοποιημένη έκδοση:

[email protected] :~$ node test2.js Final result: 10000000000 Total time: 1143 milliseconds

Αυτή τη φορά χρειάστηκε μόλις ένα δευτερόλεπτο. Πολύ πιο γρήγορα!

Σημειώστε ότι η χρήση τοπικών μεταβλητών για την αποφυγή δαπανηρών αναζητήσεων είναι μια τεχνική που μπορεί να εφαρμοστεί τόσο για αναζήτηση ιδιοτήτων (μέσω της αλυσίδας πρωτοτύπων) όσο και για μεταβλητές αναζητήσεις (μέσω της αλυσίδας πεδίου).

Επιπλέον, αυτός ο τύπος 'προσωρινής αποθήκευσης' τιμών (δηλαδή, σε μεταβλητές στο τοπικό εύρος) μπορεί επίσης να είναι επωφελής όταν χρησιμοποιείτε μερικές από τις πιο κοινές βιβλιοθήκες JavaScript. Παίρνω jQuery , για παράδειγμα. Το jQuery υποστηρίζει την έννοια των 'επιλογών', οι οποίοι βασικά είναι ένας μηχανισμός για την ανάκτηση ενός ή περισσότερων στοιχείων που ταιριάζουν στο ΚΡΙΣΗ . Η ευκολία με την οποία μπορεί κανείς να καθορίσει τους επιλογείς στο jQuery μπορεί να κάνει κάποιον να ξεχάσει πόσο δαπανηρό (από άποψη απόδοσης) μπορεί να είναι κάθε αναζήτηση επιλογέα. Κατά συνέπεια, η αποθήκευση των αποτελεσμάτων αναζήτησης επιλογών σε μια τοπική μεταβλητή μπορεί να είναι εξαιρετικά επωφελής για την απόδοση. Για παράδειγμα:

// this does the DOM search for $('.container') 'n' times for (var i = 0; i ”); } // this accomplishes the same thing... // but only does the DOM search for $('.container') once, // although it does still modify the DOM 'n' times var $container = $('.container'); for (var i = 0; i '); } // or even better yet... // this version only does the DOM search for $('.container') once // AND only modifies the DOM once var $html = ''; for (var i = 0; i '; } $('.container').append($html);

Ειδικά σε μια ιστοσελίδα με μεγάλο αριθμό στοιχείων, η δεύτερη προσέγγιση στο παραπάνω δείγμα κώδικα μπορεί δυνητικά να οδηγήσει σε σημαντικά καλύτερη απόδοση από την πρώτη.

Τύλιξε

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

Σχετίζεται με: Ως προγραμματιστής JS, αυτό είναι που με κρατάει τη νύχτα / Κάνοντας την αίσθηση της σύγχυσης ES6 Class

Μελέτη περίπτωσης: Γιατί χρησιμοποιώ AWS Cloud Infrastructure για τα προϊόντα μου

Τεχνολογία

Μελέτη περίπτωσης: Γιατί χρησιμοποιώ AWS Cloud Infrastructure για τα προϊόντα μου
Smart Home Home: Εξασφάλιση του Διαδικτύου των πραγμάτων

Smart Home Home: Εξασφάλιση του Διαδικτύου των πραγμάτων

Σχεδιασμός Ux

Δημοφιλείς Αναρτήσεις
Scaling Scala: Τρόπος Dockerize χρησιμοποιώντας Kubernetes
Scaling Scala: Τρόπος Dockerize χρησιμοποιώντας Kubernetes
Μείωση του κόστους σε ένα ψηφιακό μέλλον πετρελαίου και φυσικού αερίου
Μείωση του κόστους σε ένα ψηφιακό μέλλον πετρελαίου και φυσικού αερίου
Το GWT Toolkit: Δημιουργήστε ισχυρές διεπαφές JavaScript χρησιμοποιώντας Java
Το GWT Toolkit: Δημιουργήστε ισχυρές διεπαφές JavaScript χρησιμοποιώντας Java
Επισκόπηση των δημοφιλών δημιουργών στατικών ιστότοπων
Επισκόπηση των δημοφιλών δημιουργών στατικών ιστότοπων
Γνωρίστε το Volt, ένα πολλά υποσχόμενο Ruby Framework για δυναμικές εφαρμογές
Γνωρίστε το Volt, ένα πολλά υποσχόμενο Ruby Framework για δυναμικές εφαρμογές
 
Οι μεγάλες ερωτήσεις οδηγούν σε εξαιρετικό σχεδιασμό - Ένας οδηγός για τη διαδικασία σκέψης σχεδιασμού
Οι μεγάλες ερωτήσεις οδηγούν σε εξαιρετικό σχεδιασμό - Ένας οδηγός για τη διαδικασία σκέψης σχεδιασμού
Η Ψυχολογία του Σχεδιασμού και η Νευροεπιστήμη του Amazing UX
Η Ψυχολογία του Σχεδιασμού και η Νευροεπιστήμη του Amazing UX
APIs στα κοινωνικά δίκτυα: Η διαδικτυακή πύλη στον πραγματικό κόσμο
APIs στα κοινωνικά δίκτυα: Η διαδικτυακή πύλη στον πραγματικό κόσμο
Οδηγός επένδυσης Family Office: Μια εναλλακτική λύση στο επιχειρηματικό κεφάλαιο
Οδηγός επένδυσης Family Office: Μια εναλλακτική λύση στο επιχειρηματικό κεφάλαιο
Αρχές Σχεδιασμού - Εισαγωγή στην Οπτική Ιεραρχία
Αρχές Σχεδιασμού - Εισαγωγή στην Οπτική Ιεραρχία
Δημοφιλείς Αναρτήσεις
  • vr/ar/mr
  • πώς να χρησιμοποιήσετε θέματα bootstrap
  • Ψεύτικοι αριθμοί πιστωτικών καρτών 2017
  • c corporation εναντίον s corporation στο w9
  • βέλτιστες πρακτικές σχεδίασης ιστοσελίδων για κινητά το 2018
  • πώς να κάνετε το ρομπότ
Κατηγορίες
  • Επενδυτές & Χρηματοδότηση
  • Σχεδιασμός Διεπαφής Χρήστη
  • Τεχνολογία
  • Διαχείριση Έργου
  • © 2022 | Ολα Τα Δικαιώματα Διατηρούνται

    portaldacalheta.pt