Tanya Jawab JavaScript

Baru-baru ini, SmartSpate memutuskan untuk mengumpulkan pertanyaan tentang JavaScript dan menjawabnya. Materi, terjemahan yang kami terbitkan, berisi lebih dari dua lusin pertanyaan tentang JavaScript dan jawabannya. Rentang topik yang dibahas di sini cukup luas. Secara khusus, ini adalah fitur bahasa, masalah yang dihadapi oleh programmer saat menulis kode JS, bekerja di browser dan di Node.js.



Pertanyaan nomor 1. Warisan prototipe


Saya terbiasa dengan kelas "klasik", tetapi memutuskan untuk belajar JavaScript. Saya memiliki masalah dalam memahami model prototipe. Jika memungkinkan, jelaskan, dalam bentuk templat, kemampuan untuk membuat "kelas" dalam JavaScript, beri tahu kami tentang metode dan properti kelas yang tertutup dan terbuka. Saya mengerti bahwa banyak yang telah ditulis tentang ini, dan bahwa dalam JavaScript, metode dan properti objek, secara default, tersedia untuk umum, tetapi saya ingin memahami semua ini dengan benar. Bagaimana cara kerja pewarisan prototipe dalam JavaScript?

▍ Jawab


Warisan klasik sangat mengingatkan bagaimana orang mewarisi gen leluhur mereka. Orang memiliki beberapa kemampuan dasar yang umum, seperti berjalan dan berbicara. Selain itu, setiap orang memiliki beberapa kekhasan. Orang tidak dapat mengubah apa yang disebut "kelas" mereka, tetapi mereka dapat mengubah "properti" mereka sendiri dalam batas-batas tertentu. Pada saat yang sama, kakek nenek, ibu dan ayah tidak dapat mempengaruhi gen anak-anak atau cucu-cucu dalam proses kehidupan mereka. Jadi semuanya diatur di Bumi, tetapi mari kita bayangkan planet lain tempat mekanisme pewarisan bekerja dengan cara khusus. Katakanlah, beberapa organisme yang mampu bermutasi menggunakan mekanisme "pewarisan telepati" di sana. Ini diungkapkan dalam kenyataan bahwa mereka dapat mengubah informasi genetik keturunan mereka sendiri dalam proses kehidupan mereka.

Perhatikan contoh warisan di planet aneh ini. Objek Bapa mewarisi gen dari objek Kakek, dan objek Putra mewarisi informasi genetik dari Bapa. Setiap penghuni planet ini dapat dengan bebas bermutasi dan mengubah gen keturunan mereka. Misalnya, di "Kakek" kulit memiliki warna hijau. Tanda ini diwarisi oleh "Bapa" dan "Anak". Tiba-tiba, "Kakek" memutuskan bahwa dia lelah menjadi hijau. Sekarang dia ingin menjadi biru dan mengubah warna kulitnya (dalam hal JS - mengubah prototipe kelasnya), "secara telepati" meneruskan mutasi ini kepada "Ayah" dan "Putera". Setelah itu, "Ayah", percaya bahwa "Kakek" telah selamat dari pikiran, memutuskan untuk mengubah gennya sehingga ia berubah menjadi hijau lagi (yaitu, ia mengubah prototipe sendiri). Perubahan-perubahan ini "secara telepati" ditransmisikan ke "Anak." Akibatnya, baik "Ayah" dan "Anak" memiliki kulit hijau lagi. Pada saat yang sama, "Kakek" masih berwarna biru. Sekarang, tidak peduli apa yang dia lakukan dengan warnanya, itu tidak akan mempengaruhi orang lain. Dan semua ini disebabkan oleh fakta bahwa "Bapa" secara eksplisit mengatur warna kulitnya dalam "prototipe" -nya, dan "Anak" mewarisi warna ini. Kemudian "Anak" berpikir seperti ini: "Aku akan menjadi hitam. Dan biarkan keturunan saya mewarisi warna dari ayah saya. " Untuk melakukan ini, ia mengubah hartanya sendiri (dan bukan properti prototipe-nya) sedemikian rupa sehingga hartanya akan mempengaruhi warnanya, tetapi tidak akan mempengaruhi keturunannya. Kami menyatakan semua ini dalam bentuk kode:

var Grandfather = function () {}; //  Grandfather Grandfather.prototype.color = 'green'; var Father = function () {}; //  Father Father.prototype = new Grandfather (); //  - ,        var Son = function () {}; //  Son Son.prototype = new Father (); // Son   Father var u = new Grandfather (); //   Grandfather var f = new Father (); //   Father var s = new Son (); //   Son //     console.log ([u.color, f.color, s.color]); // ["green", "green", "green"] //  Grandfather        Grandfather.prototype.color = 'blue'; console.log ([u.color, f.color, s.color]); // ["blue", "blue", "blue"] //  Father      -   ,     Father.prototype.color = 'green'; //      : // Grandfather.prototype.color = 'green'; console.log ([u.color, f.color, s.color]); // ["blue", "green", "green"] // ,        Grandfather     color,      Grandfather.prototype.color = 'blue'; console.log ([u.color, f.color, s.color]); // ["blue", "green", "green"] //  Son,  ,       Grandfather,    s.color = 'black'; //        console.log ([u.color, f.color, s.color]); // ["blue", "green", "black"] var SonsSon = function () {}; //  SonsSon -   Son SonsSon.prototype = new Son (); //  var ss = new SonsSon (); //   SonsSon //         console.log ([u.color, f.color, s.color, ss.color]); // ["blue", "green", "black", "green"] 

Pertanyaan nomor 2. Buat Objek


Jika Anda membuat instance objek baru menggunakan kata kunci new , lalu bagaimana Anda bisa melindungi diri dari kesalahan? Beginilah biasanya saya bekerja:

  1. Saya selalu membangun fungsi konstruktor sehingga mereka mulai dengan huruf kapital.
  2. Saya memverifikasi kebenaran operasi menggunakan this instanceof Function_Name (saya mencoba untuk tidak menggunakan konstruk dari tipe this instanceof arguments.callee karena alasan kinerja).
  3. Pendekatan ini mirip dengan yang sebelumnya, tetapi perbandingannya dibuat dengan window , karena saya tidak suka membuat kode nama-nama entitas dan tidak perlu menulis kode untuk lingkungan selain browser.

Apa model paling nyaman untuk membuat objek?

▍ Jawab


Cara terbaik, baik secara ideologis maupun berdasarkan keakraban metode ini, untuk membuat objek menggunakan kata kunci new . Dalam hal ini, fungsi konstruktor harus diberi nama yang dimulai dengan huruf kapital.

Saya lebih suka berpegang pada aturan dan tidak melakukan pemeriksaan tambahan this pada konstruktor. Jika konstruktor dipanggil tanpa yang new dan pekerjaan dimulai dalam lingkup global, ini dapat dibandingkan dengan "penipuan diri sendiri". Pada saat yang sama, saya sama sekali tidak menyarankan Anda menangani situasi di perancang tempat mereka dipanggil tanpa kata kunci new . Misalnya, mungkin terlihat seperti ini: jika konstruktor dipanggil tanpa yang new , maka, bagaimanapun, objek baru dibuat dan dikembalikan. Pendekatan ini secara ideologis salah dan mengarah pada kesalahan.
Berikut ini contoh bekerja dengan konstruktor.

 var Obj = function () {   "use strict";   this.pew = 100; }; //  let o = new Obj(); o.pew++; console.log(o.pew); //101 // .   Obj (); // TypeError: this is undefined 

Lebih baik tidak menggunakan kata kunci new untuk metode pabrik dan untuk kasus-kasus ketika tidak diperlukan konstruktor, ketika akan lebih mudah untuk membuat objek menggunakan objek literal. Katakanlah kode konstruktor yang ditunjukkan pada contoh berikut secara eksplisit berlebihan:

 //    . var Obj = function () {    if (! (this instanceof Obj)) {        return new Obj ();    }    this.pew = 100; }; 

Jika, bahkan untuk membuat objek kecil, Anda masih memerlukan konstruktor, lebih baik melakukannya:

 var Obj = function () {    "use strict";    this.pew = 100; }; 

Di sini, seperti yang ditunjukkan di atas, karena kenyataan bahwa konstruktor bekerja dalam mode ketat, kesalahan akan terjadi ketika memanggilnya tanpa yang new .

Pertanyaan nomor 3. Intersepsi klik mouse


Bagaimana, menggunakan JavaScript, untuk mengetahui tombol mouse mana yang diklik?

▍ Jawab


Mengklik tombol mouse menghasilkan peristiwa mousedown dan mousedown . Dalam hal ini, peristiwa click hanya dihasilkan oleh tombol kiri mouse. Dalam pengendali event, Anda perlu memeriksa kode yang terletak di properti event.button untuk mengetahui tombol mana yang ditekan (0 - kiri, 1 - tengah, 2 - kanan). Namun, di IE semuanya terlihat sedikit berbeda. Pertimbangkan sebuah contoh:

 var button = document.getElementById ('button'),              // 0 1 2    buttonMap = ['Left', 'Middle', 'Right'],    handler = function (event) {        event = event || window.event;        alert (buttonMap [event.button] + 'id:' + event.button);    }; if (button.addEventListener) {     button.addEventListener ('mousedown', handler, false); } else {     // IE 0 1 2 3 4     buttonMap = ['???', 'Left', 'Right', '???', 'Middle'];     button.attachEvent ('onmousedown', handler); } 

Pustaka jQuery mempertimbangkan fitur IE ini, jadi ketika menggunakannya di browser apa pun, cukup periksa nilai event.which properti alih-alih mengacaukan event.button :

 $('button').mousedown(function (event) {   alert(['Left', 'Middle', 'Right'][event.which]); }); 

Pertanyaan nomor 4. Intersepsi penekanan tombol pada tombol keyboard


Apakah mungkin untuk mencegat, melalui JavaScript, menekan tombol panah (khususnya, menekan tombol Turun dan Atas), sehingga, setelah mengkliknya, browser tidak akan menggulir halaman? Jika ini memungkinkan, lalu apa saja fitur penerapan ini di berbagai browser? Misalkan halaman ditampilkan pada halaman yang tidak sepenuhnya sesuai pada layar. Bergerak melalui sel-sel tabel ini harus diatur menggunakan tombol panah, dan diperlukan bahwa browser tidak menggulir halaman ketika Anda mengklik tombol tersebut.

▍ Jawab


Untuk mengimplementasikan sesuatu seperti ini, pertama-tama, Anda perlu menonaktifkan respons sistem standar untuk mengendalikan tindakan. Misalnya, tombol panah dan roda mouse menggulir halaman, mengklik kanan pada halaman menampilkan menu konteks, ketika Anda mengklik tombol submit , fungsi form.submit() , ketika Anda mengklik bidang input, itu mendapat fokus input, ketika Anda mengklik pada tautan, browser memuat halaman yang dituju.

Ini dapat dilakukan dengan berbagai cara . Misalnya, seperti ini:

 window.addEventListener("keydown", function(e) {   //  -   if([37, 38, 39, 40].indexOf(e.keyCode) > -1) {       e.preventDefault();   } }, false); 

Halaman setelah itu biasanya tidak akan merespon penekanan tombol panah.
Satu hal penting yang perlu diperhatikan di sini. Metode preventDefault() sebelum tindakan default dilakukan. Misalnya, jika Anda mengklik bidang untuk mencegahnya mendapatkan fokus input, Anda perlu menggantung penangan yang sesuai pada suatu peristiwa yang ada di rantai peristiwa sebelum tindakan default. Dalam kasus kami, ini adalah acara mousedown :

 $('input').bind ('mousedown', function (event) {   event.preventDefault();   //    return false; }); 

Saat Anda mengklik bidang input, peristiwa berikut terjadi - dalam urutan yang ditampilkan di sini:

  1. mousedown
  2. focus (sebelum ini, objek lain yang kehilangan fokus akan memicu kejadian blur )
  3. mouseup
  4. click

Jika Anda mencoba untuk mencegah elemen dari mendapatkan fokus input, maka menggunakan event handler untuk ini dimulai dengan handler event focus tidak akan membantu kami.

Pertanyaan nomor 5. Hentikan animasi GIF dan kunci ESC


Bagaimana cara mengatasi masalah menghentikan animasi GIF saat menekan tombol ESC?

▍ Jawab


Di sini Anda dapat menggunakan pendekatan yang sama dengan yang kami pertimbangkan di atas. Di beberapa browser, menekan tombol ESC menghentikan animasi GIF dan pemuatan halaman. Ini adalah perilaku standar mereka, dan untuk mencegah mereka berperilaku dengan cara ini, metode event preventDefault() berguna bagi kita, seperti sebelumnya. Kode kunci ESC adalah 27.

Pertanyaan nomor 6. Kurung di IIFE


Bagaimana konstruk kedua kurung digunakan ketika menyatakan Ekspresi Fungsi Segera Diminta (IIFE)?

▍ Jawab


Kurung dalam situasi ini memungkinkan parser untuk memahami bahwa ada fungsi di depannya yang perlu dilakukan. Tapi dia juga perlu memahami apa tanda kurung ini - operator pengelompokan, atau konstruksi yang menunjukkan perlunya memanggil fungsi. Misalnya, jika kita menggunakan dua tanda kurung seperti yang ditunjukkan di bawah ini, kita akan SyntaxError kesalahan SyntaxError :

 function () { //  }() 

Ini disebabkan oleh fakta bahwa fungsi tersebut tidak memiliki nama (Anda harus menentukan namanya dalam deklarasi fungsi).

Mari kita coba menulis ulang kode ini, memberi nama fungsi:

 function foo() { //  }() 

Sekarang fungsi memiliki nama, konstruksi ini, secara teoritis, akan terlihat sangat normal dari sudut pandang sistem. Tetapi kesalahan tidak hilang, meskipun sekarang ada hubungannya dengan operator pengelompokan, di dalamnya tidak ada ekspresi. Perhatikan bahwa dalam kasus ini, pernyataan pengelompokan diikuti oleh operator pengelompokan, dan bukan urutan tanda kurung yang memberi tahu sistem bahwa fungsi yang mendahuluinya harus dipanggil.

Seringkali IIFE dirancang sebagai berikut:

 (function () {   //  })() 

Tetapi ada beberapa cara lain, yang intinya adalah untuk menunjukkan kepada parser bahwa sebelum itu hanya ekspresi fungsional yang perlu dieksekusi:

 !function () { //  }(); +function () { //  }(); [function() { //  }()]; var a = function () { //  }(); 

IIFE banyak digunakan dalam pemrograman JavaScript. Misalnya, konstruksi ini digunakan di jQuery. Dengan bantuannya, Anda dapat membuat penutupan. Faktanya, kita berbicara tentang fakta bahwa, dengan menggunakan IIFE, programmer dapat mengeksekusi beberapa kode dalam lingkup lokal. Ini membantu melindungi ruang lingkup global dari polusi, dan memungkinkan untuk mengoptimalkan akses ke variabel global. Desain seperti itu diperkecil dengan baik.

Pertanyaan nomor 7. Passing code sebagai tanggapan terhadap permintaan


Server, dalam proses interaksi AJAX dengan klien, di tubuh respons, mengirimkan klien sebuah alert ('Boom !!!'); . Klien menerima respons dan mengeksekusi kode ini menggunakan fungsi eval() . Apa itu namanya? Bagaimanapun, apa yang terkandung dalam respons server bukanlah JSON, bukan XML, dan bukan HTML. Apa yang dapat Anda katakan tentang eksekusi pada klien dari kode yang berasal dari server dalam bentuk tubuh tanggapan terhadap permintaan tertentu?

▍ Jawab


Bahkan, tidak ada nama khusus untuk skema semacam itu untuk interaksi client-server. Dan ini adalah skema interaksi sistem yang sangat tidak dianjurkan. Ini sama buruknya dengan menyimpan kode PHP dalam database dan kemudian mengeksekusinya menggunakan metode bahasa yang sesuai. Bahkan jika kita tidak mempertimbangkan pertimbangan ideologis, kita dapat mengatakan bahwa arsitektur seperti itu sangat tidak fleksibel, oleh karena itu, jika proyek di mana ia digunakan, akan diperlukan, ketika berkembang, untuk mengubah sesuatu, ini tidak akan mudah. Di sini kita melihat contoh arsitektur sistem yang buruk ketika data dicampur dengan elemen kode dan antarmuka. Untuk mengubah sesuatu dalam sistem seperti itu, pertama-tama Anda perlu memahami seluk-beluk arsitekturnya yang rumit, dan kemudian, setelah melakukan perubahan, sekali lagi β€œmembingungkan” segalanya. Saya tidak berbicara tentang penggunaan kembali kode.

Untuk menyederhanakan dukungan kode, Anda perlu berusaha untuk pemisahan bagian sistem yang paling mungkin dan untuk mengurangi jumlah saling ketergantungan bagian-bagian ini. Untuk memastikan konektivitas yang lemah dari bagian-bagian sistem, yaitu, untuk memastikan bahwa sebuah fragmen aplikasi dapat diekstraksi dari itu, atau, dengan kompleksitas paling sedikit, digantikan oleh yang lain, Anda dapat menggunakan mekanisme acara atau solusi arsitektur khusus, seperti MVC.

Pertanyaan nomor 8. Melakukan operasi berat di utas utama


Bagaimana cara mengatur pelaksanaan perintah intensif sumber daya tertentu dalam JavaScript dan tidak "menangguhkan" seluruh skrip?

▍ Jawab


JavaScript adalah bahasa utas tunggal. Kode halaman web dieksekusi di utas yang sama dan transformasi DOM tree dilakukan. Ada juga timer. Setiap kali Anda melakukan beberapa operasi yang menghabiskan sumber daya (siklus, panggilan ke fungsi "berat"), ini menyebabkan perlambatan pada antarmuka pengguna atau bahkan ke pemblokiran lengkapnya. Jika operasi yang dilakukan tidak memiliki beban yang sangat besar pada sistem, maka dampaknya pada antarmuka akan sangat kecil sehingga pengguna tidak akan menyadarinya. Untuk membuat komputasi yang berat di luar utas utama, konsep pekerja web diperkenalkan dalam JavaScript.

Jika penggunaan pekerja tidak memungkinkan, maka Anda perlu mengoptimalkan siklus dan fungsi "berat". Dalam buku β€œJavaScript. Optimalisasi Kinerja ”Nicholas Zakas mengatakan bahwa pengguna tidak akan melihat apa pun jika aliran antarmuka pengguna diblokir untuk 100 ms atau kurang.

Dari ide ini, kita dapat menyimpulkan bahwa perhitungan intensif sumber daya dapat dibagi menjadi beberapa fragmen, yang implementasinya membutuhkan maksimum 100 ms, setelah itu utas utama harus dibebaskan.

Berikut ini contoh kode dari buku di atas:

 function timedProcessArray(items, process, callback) {   var todo = items.concat();   //    setTimeout(function () {       var start = +new Date();       do {           process(todo.shift());       } while (todo.length > 0 && (+new Date() - start < 50));       if (todo.length > 0){           setTimeout(arguments.callee, 25);       } else {           callback(items);       }   }, 25); } function saveDocument(id) {   var tasks = [openDocument, writeText, closeDocument, updateUI];   timedProcessArray(tasks, [id], function(){       alert("Save completed!");   }); } 

Fungsi timedProcessArray() memblokir utas utama selama 25 ms, melakukan urutan tindakan, lalu melepaskannya selama 25 ms, setelah itu proses ini diulang.

Pertanyaan nomor 9. Tentang mengubah ukuran jendela browser


Bisakah saya mengetahui bahwa pengguna telah selesai mengubah ukuran jendela browser?

▍ Jawab


Tidak ada acara khusus yang memungkinkan Anda untuk mengetahuinya. Tetapi Anda bisa mengetahui apakah pengguna mengubah ukuran jendela menggunakan acara onresize . Namun metode ini tidak terlalu akurat.

Berikut adalah konsep kode untuk menyelesaikan masalah ini.

 var time = 0,   timerId,   TIME_ADMISSION = 100; // 0.1  function onresizeend () {   console.log('onresizeend'); }; function resizeWatcher () {   if (+new Date - time >= TIME_ADMISSION) {       onresizeend();       if (timerId) {           window.clearInterval(timerId);           timerId = null;       }   } }; $(window).resize(function () {   if (!timerId) {       timerId = window.setInterval(resizeWatcher, 25);   }   time = +new Date; }); 

Pertanyaan nomor 10. Membuka jendela dan tab browser baru


Bagaimana, menggunakan metode window.open() , untuk membuka jendela browser baru, dan bukan tab baru?

▍ Jawab


Bagaimana tepatnya metode window.open() berperilaku tergantung pada browser. Opera selalu membuka tab baru (meskipun terlihat seperti windows), Safari selalu membuka windows (meskipun perilaku ini dapat diubah). Perilaku Chrome, Firefox, dan Internet Explorer dapat dikontrol.

Jadi, jika parameter tambahan (posisi jendela window.open() diteruskan ke metode window.open() , jendela baru akan dibuka:

 window.open('http://www.google.com', '_blank', 'toolbar=0,location=0,menubar=0'); 

Jika hanya tautan yang diteruskan ke metode ini, maka tab browser baru akan dibuka:

 window.open('http://www.google.com'); 

Seringkali Anda perlu membuka tab browser baru. Mungkin ada masalah dengan ini di browser Safari. Secara default (tergantung pada pengaturan), browser, ketika window.open() dipanggil, membuka jendela baru. Tetapi jika Anda mengklik tautan, sambil menekan tombol Ctrl + Shift/Meta + Shift , tab baru akan terbuka (terlepas dari pengaturan). Dalam contoh berikut, kami akan mensimulasikan acara click yang muncul ketika tombol Ctrl + Shift/Meta + Shift ditekan:

 function safariOpenWindowInNewTab (href) {    var event = document.createEvent ('MouseEvents'),        mac = (navigator.userAgent.indexOf ('Macintosh')> = 0); //  Ctrl + Shift + LeftClick / Meta + Shift + LeftClick ()    //       event.initMouseEvent (        / * type * / "click",        / * canBubble * / true        / * cancelable * / true,        / * view * / window,        / * detail * / 0,        / * screenX, screenY, clientX, clientY * / 0, 0, 0, 0,        / * ctrlKey * /! mac,        / * altKey * / false,        / * shiftKey * / true        / * metaKey * / mac,        / * button * / 0,        / * relatedTarget * / null    ); //     ,   ,         $ ('<a/>', {'href': href, 'target': '_blank'}) [0] .dispatchEvent (event); } 

Pertanyaan No. 11. Menyalin objek dalam


Bagaimana cara mengatur secara efektif penyalinan objek dalam?

▍ Jawab


Jika objek yang salinannya ingin Anda buat (sebut saja oldObject ) tidak berubah, maka itu akan paling efektif untuk melakukan ini melalui prototipe (ini dilakukan dengan sangat cepat):

 function object(o) {   function F() {}   F.prototype = o;   return new F(); } var newObject = object(oldObject); 

Jika Anda perlu benar-benar melakukan operasi kloning objek, maka cara tercepat akan secara rekursif, mengoptimalkan proses ini, melalui propertinya. Mungkin ini adalah algoritma tercepat untuk membuat salinan objek yang dalam:

 var cloner = {   _clone: function _clone(obj) {       if (obj instanceof Array) {           var out = [];           for (var i = 0, len = obj.length; i < len; i++) {               var value = obj[i];               out[i] = (value !== null && typeof value === "object") ? _clone(value) : value;           }       } else {           var out = {};           for (var key in obj) {               if (obj.hasOwnProperty(key)) {                   var value = obj[key];                   out[key] = (value !== null && typeof value === "object") ? _clone(value) : value;               }           }       }       return out;   }, clone: function(it) {       return this._clone({       it: it       }).it;   } }; var newObject = cloner.clone(oldObject); 

Jika Anda menggunakan jQuery, maka Anda dapat menggunakan konstruk berikut:

 //   var newObject = jQuery.extend ({}, oldObject); //   var newObject = jQuery.extend (true, {}, oldObject); 

Pertanyaan nomor 12. Penghancur JavaScript


Bagaimana cara membuat sesuatu seperti destruktor dalam JavaScript? Bagaimana mengelola siklus hidup benda?

▍ Jawab


Dalam JavaScript, sebuah objek akan dihapus dari memori setelah referensi terakhir untuk itu menghilang:

 var a = {z: 'z'}; var b = a; var c = a; delete az; delete a; //    a console.log (b, c); // ,  ,    

Menggunakan sesuatu seperti "destruktor" dalam JavaScript hanya menghasilkan membersihkan konten objek, tetapi tidak menghapusnya dari memori.

Pertanyaan nomor 13. Pemrosesan data biner


Apakah mungkin untuk memproses data biner dalam JavaScript? Dan jika demikian, bagaimana?

▍ Jawab


Jika Anda perlu bekerja dengan data biner dalam aplikasi JavaScript, Anda dapat mencoba menggunakan perpustakaan Binary Parser . Tapi kodenya adalah neraka. Dalam ES6 + ada saran mengenai tipe StructType (ini sama dengan yang disajikan dalam C ++ oleh tipe komposit ke struct diberikan). Tipe data ini diperlukan untuk menyederhanakan bekerja dengan data biner. Bekerja dengannya mungkin terlihat seperti ini:

 const Point2D = new StructType({ x: uint32, y: uint32 }); const Color = new StructType({ r: uint8, g: uint8, b: uint8 }); const Pixel = new StructType({ point: Point2D, color: Color }); const Triangle = new ArrayType(Pixel, 3); let t = new Triangle([{ point: { x:  0, y: 0 }, color: { r: 255, g: 255, b: 255 } },                     { point: { x: 5, y: 5 }, color: { r: 128, g: 0,   b: 0 } },                     { point: { x: 10, y: 0 }, color: { r: 0,   g: 0, b: 128 } }]); 

Pertanyaan nomor 14. Mengubah variabel dalam satu fungsi dari fungsi lainnya


Bagaimana cara mengubah variabel yang terletak di satu fungsi dari fungsi lain?

▍ Jawab


Di sini Anda dapat menerapkan beberapa pendekatan:

  1. Anda dapat menggunakan tautan ke konteks fungsi yang menarik bagi kami (fungsi primer() dalam contoh berikut) dalam fungsi smth() .
  2. Anda bisa melewatkan fungsi yang dibuat dalam konteks fungsi primer() ke fungsi smth() .

     var primer = function () {    var a, b, c, d, e = {}; smth (function () {        a = 1;        b = 2;        c = 3;        d = 4;    }, e); alert ([a, b, c, d, e.pewpew]); }, smth = function (callback, e) {    callback ();    e.pewpew = "pewpew"; }; primer (); 
  3. Sebelumnya (sebelum Firefox 3.6), Anda bisa masuk ke konteks menggunakan properti __parent__ , tetapi sudah di Firefox 4 fitur ini dihapus.

Pertanyaan nomor 15. Bekerja dengan fungsi


Beri tahu kami bagaimana fungsi dapat dipanggil dalam JavaScript.

▍ Jawab


Saya kira tidak perlu berbicara tentang cara memanggil fungsi, metode dan konstruktor selama bekerja normal dengan mereka. Mari kita bicara tentang cara menggunakan metode call() dan apply() .

Menggunakan panggilan () untuk mengonfigurasi konstruktor suatu objek


 //   function extend (newObj, oldObj) {   function F () {};   F.prototype = oldObj.prototype;   newObj.prototype = new F ();   return newObj }; var Obj = function () {   this.obj_var = 100; }; Obj.prototype.obj_proto_var = 101; var NewObj = function () {   Obj.call (this); //   Obj     obj_var   this.new_obj_var = 102; }; extend (NewObj, Obj) NewObj.prototype.new_obj_proto_var = 103; new NewObj (); // {new_obj_proto_var: 103, new_obj_var: 102, obj_proto_var: 101, obj_var: 100} 

Konversi objek mirip array ke array


Objek mirip array mirip dengan array JavaScript, tetapi sebenarnya tidak. Secara khusus, ini dinyatakan dalam kenyataan bahwa objek tersebut tidak memiliki metode array biasa. Di antara objek tersebut, misalnya, objek arguments fungsi tradisional dan hasil metode getElementsByTagName () dapat dicatat.

 // document.getElementsByTagName ("div")  ,   ,    , ,  ,        document.getElementsByTagName ("div"). forEach (function (elem) {    // ... }); // TypeError: document.getElementsByTagName ("div"). forEach is not a function //    Array.prototype.slice.call(document.getElementsByTagName("div")).forEach (function (elem) {   // OK }); //        console.log(Array.prototype.slice.call ('pewpew')) // ["p", "e", "w", "p", "e", "w"] //  IE8    

Membuat objek pembungkus


Teknik ini menggunakan call() dan apply() memungkinkan Anda untuk membuat objek pembungkus. , - foo() , bar() .

:

 function bar () {console.log(arguments)} // foo (context, arg1, arg2, ...) function foo () {    var context = arguments [0];    var args = Array.prototype.slice.call (arguments, 1); //     bar    bar.apply (context, args); } 

Function.call.apply() :

 function foo() {   Function.call.apply(bar, arguments); } 

, Function.call.apply() , , foo() , bar .

β„–16.


, , ?

▍


. , Firefox 3.6, __parent__ , .

β„–17.


, , , eval() ?

▍


, . , :

 // 1:  eval() (function () {    "use strict";    var globalObject = (0, eval) ("this"); //  :)    return globalObject; } ()); // 2:    (function (global) {    // ... } (window)); // 3:      (function () {    return this; } ()); // 4:            ,       . //  -    "use strict"; (function (global) {    // global }) (this); 

β„–18.


, JavaScript, , ?

▍


JavaScript - Β« Β». . . , :

 $('#smth').click(function onSmthClick(event) {   if (smth) {       //         event.handlerFunction = onSmthClick;       event.handlerContext = this;       //         //  otherObjectSetSomeEvent   event.handlerFunction          otherObjectSetSomeEvent(event);   } else {       //  -    } }); 

β€” , . , 2 :

 $('#smth'). click (function handler1 (event) {   if (smth) {       //         leftObjectSetSomeEvent(event, function handler2 (e) {           //  -   e       });   } else {       //  -    } }); function leftObjectSetSomeEvent(event, callback) {   callback (event);   //    } 

β„–19.


JavaScript ? β€” , .

▍


click «» DOM. (, , ).

 // jQuery $(window).bind ('click', function (e) {   console.log ('Clicked on', e.target); }); //       $('#pewpew').delegate ('*', 'click', function(e) {   console.log('Clicked on', e.target); }); //     $('#pewpew').delegate('.pewpew', 'click', function (e) {   console.log ('Clicked on element with .pewpew class name'); }); 

β„–20. XHR-


XHR- jQuery?

▍


, - :

 function xhr(m, u, c, x) { with(new XMLHttpRequest) onreadystatechange = function (x) {   readyState ^ 4 || c(x.target) }, open(m, u), send() } 

- :

 function xhr(m, u, c, x) { with(new(this.XMLHttpRequest || ActiveXObject)("Microsoft.XMLHTTP")) onreadystatechange = function (x) {   readyState ^ 4 || c(x) }, open(m, u), send() } 

:

 xhr('get', '//google.com/favicon.ico', function (xhr) { console.dir(xhr) }); 

β„–21. -


(reflow) (repaint) -?

▍


  1. requestAnimationFrame() , , setInterval() setTimeout() . , , , , , . , JavaScript- CSS- SVG-. , , , , , , . , , .
  2. float- ( ).
  3. DOM. , , , DOM ( ).
  4. β€” . ( , , ). Berikut ini sebuah contoh:

     //      element.style.left = "150px;"; // ... element.style.color = "green"; //  ,   ,    element.setAttribute ('style', 'color: green; left: 150px'); 
  5. ( ).
  6. β€” ( style.display = "none" ). , .

, -, . , , , , .

  1. .
  2. DOM- ( β€” ).
  3. Document.querySelectorAll() firstElementChild .
  4. , document.getElementsByTagName() ( , DOM, ).

β„–22. Node.js


Node.js, , ?

▍


, ( PHP Apache). , , . Node.js β€” . , , cluster . (master) - (worker). , .

β„–23. runInNewContext() Node.js


runInNewContext() Node.js.

▍


. , ( Node.js- Nodester). - , runInNewContext() . , «», . «» , , runInNewContext() .

Ringkasan


JavaScript . , - , .

Pembaca yang budiman! , - , , JavaScript , ?

Source: https://habr.com/ru/post/id436454/


All Articles