templat js. Apa itu template Javascript dan mengapa dibutuhkan? Apa itu pola desain dan mengapa menggunakannya




Halo, habr!
Saya terkejut saat mengetahui bahwa tidak ada artikel mendetail tentang topik tersebut di hub, yang segera mendorong saya untuk memperbaiki ketidakadilan yang mencolok ini.

Dalam lingkungan di mana sisi klien dari aplikasi web menjadi semakin tebal, logika bisnis merayap ke klien, dan node.js semakin melanggar kedaulatan teknologi server, kita tidak bisa tidak memikirkan teknik merancang arsitektur di JavaScript. Dan dalam hal ini, pola desain tidak diragukan lagi akan membantu kita - metode templat untuk memecahkan masalah yang sering kita temui. Pola membantu Anda membangun arsitektur yang memerlukan sedikit usaha dari Anda saat perubahan perlu dilakukan. Namun Anda tidak boleh menganggapnya sebagai obat mujarab, yaitu, secara kasar, jika kualitas kodenya "tidak bagus", kode tersebut penuh dengan kode keras dan hubungan erat antara modul yang independen secara logis, maka tidak ada pola yang akan menyimpannya. Namun jika tugasnya adalah merancang arsitektur yang dapat diskalakan, maka pola dapat sangat membantu.
Namun, artikel ini bukan tentang pola desain itu sendiri, tetapi tentang penerapannya dalam javaScript. Pada bagian pertama artikel ini saya akan menulis tentang penggunaan pola generatif.

Singleton Jika tugasnya adalah mendeskripsikan pola ini dalam satu frase, hasilnya akan seperti ini: Singleton adalah kelas yang hanya dapat memiliki satu instance.
Solusi JavaScript paling sederhana dan jelas untuk mengimplementasikan pola ini adalah dengan menggunakan objek:

Var app = ( properti1: "nilai", properti2: "nilai", ... metode1: fungsi () ( ... ), ... )

Metode ini memiliki kelebihan dan kekurangan. Mudah untuk dijelaskan, banyak orang menggunakannya tanpa menyadari keberadaan pola apa pun, dan bentuk penulisan ini dapat dimengerti oleh pengembang JavaScript mana pun. Namun metode ini juga memiliki kelemahan yang signifikan: tujuan utama pola tunggal adalah untuk menyediakan akses ke objek tanpa menggunakan variabel global, dan metode ini menyediakan akses ke variabel aplikasi hanya dalam cakupan saat ini. Artinya kita dapat mengakses objek app dari mana saja dalam aplikasi hanya jika bersifat global. Seringkali hal ini sangat tidak dapat diterima; gaya pengembangan JavaScript yang baik adalah menggunakan paling banyak satu variabel global, yang merangkum semua yang diperlukan. Artinya kita dapat menggunakan pendekatan di atas paling banyak satu kali dalam aplikasi.
Metode kedua sedikit lebih rumit, tetapi juga lebih universal:

Fungsi SomeFunction() ( if (typeof (SomeFunction.instance) == "objek") ( return SomeFunction.instance; ) this.property1 = "value"; this.property2 = "value"; SomeFunction.instance = this; kembalikan ini ; ) BeberapaFunction.prototype.method1 = fungsi () ( )

Sekarang, dengan menggunakan sistem modular apa pun (misalnya, requirejs), kita dapat menghubungkan file dengan deskripsi fungsi konstruktor ini di mana saja dalam aplikasi kita dan mendapatkan akses ke objek kita dengan menjalankan:

Var someObj = baru SomeFunction();

Namun metode ini juga memiliki kekurangannya: instance disimpan hanya sebagai properti statis konstruktor, yang memungkinkan siapa saja untuk menimpanya. Kami ingin, dalam keadaan apa pun, kami dapat mengakses objek yang diperlukan dari sudut mana pun di aplikasi kami. Ini berarti bahwa variabel tempat kita menyimpan instance harus dijadikan pribadi, dan penutupan akan membantu kita dalam hal ini.

Fungsi SomeFunction() ( var instance; SomeFunction = function() ( return instance; ) this.property1 = "value"; this.property2 = "value"; instance = this; )

Tampaknya ini adalah solusi untuk semua masalah, tetapi masalah baru menggantikan masalah lama. Yaitu: semua properti yang termasuk dalam prototipe konstruktor setelah instance dibuat tidak akan tersedia karena pada kenyataannya, mereka akan ditulis ke konstruktor lama, dan bukan ke konstruktor yang baru didefinisikan. Namun ada jalan keluar yang layak dari situasi ini:

Fungsi SomeFunction() ( var instance; SomeFunction = function() ( return instance; ) SomeFunction.prototype = ini; instance = new SomeFunction(); instance.constructor = SomeFunction; instance.property1 = "value"; instance.property2 = " nilai"; contoh kembali; )

Metode mendeskripsikan singleton ini tidak memiliki semua kelemahan di atas dan cukup cocok untuk penggunaan universal, namun metode mendeskripsikan singleton menggunakan penutupan tidak akan berfungsi dengan requirejs, tetapi jika Anda memodifikasinya sedikit dan memindahkan variabel keluar dari penutupan yang dibuat oleh fungsi itu sendiri ke dalam fungsi yang digunakan dalam mendefinisikan, maka masalah akan terpecahkan:

Define(, function () ( var instance = null; function SomeFunction() ( if (instance) ( return instance; ) this.property1 = "value"; this.property2 = "value"; instance = this; ); return SomeFunction ;

Metode pabrik Metode pabrik mempunyai dua tujuan utama:
1) Jangan gunakan kelas yang konkret secara eksplisit
2) Gabungkan metode inisialisasi objek yang umum digunakan
Implementasi paling sederhana dari metode pabrik adalah contoh ini:

Fungsi Foo () ( //... ) fungsi Bar () ( //... ) fungsi pabrik (tipe) ( switch (tipe) ( case "foo": kembalikan Foo baru(); case "bar": kembali Batang baru();

Oleh karena itu, pembuatan objek akan terlihat seperti ini:

Foo = pabrik("foo"); batang = pabrik("batang");

Solusi yang lebih elegan dapat digunakan:

Fungsi Pabrik Hewan Peliharaan() ( ); PetFactory.register = function(nama, PetConstructor) ( if (nama instanceof Function) ( PetConstructor = nama; nama = null; ) if (!(PetConstructor instanceof Function)) ( throw ( nama: "Kesalahan", pesan: "PetConstructor adalah tidak berfungsi" ) ) this = PetConstructor; ); PetFactory.create = function(petName) ( var PetConstructor = ini; if (!(PetConstructor instanceof Function)) ( throw ( nama: "Error", pesan: "constructor "" + petName + "" undefinisi" ) ) kembalikan PetConstructor baru ();

Dalam hal ini, kami tidak membatasi diri pada jumlah kelas yang dapat dihasilkan oleh pabrik; kami dapat menambahkan kelas sebanyak yang kami suka dengan cara ini:

PetFactory.register("dog", function() ( this.say = function () ( console.log("gav"); ) ));

Atau seperti ini:

Fungsi Cat() ( ) Cat.prototype.say = fungsi () ( console.log("meow"); ) PetFactory.register(Cat);

Pabrik Abstrak Pabrik abstrak digunakan untuk membuat sekelompok objek yang saling terkait atau saling bergantung.
Misalkan kita memiliki beberapa jendela pop-up yang terdiri dari elemen yang sama, namun elemen tersebut terlihat berbeda dan bereaksi berbeda terhadap tindakan pengguna. Masing-masing elemen ini akan dibuat menggunakan metode pabrik, yang berarti bahwa setiap jenis jendela pop-up memerlukan pabrik objeknya sendiri.
Sebagai contoh, mari kita gambarkan pabrik BluePopupFactory; pabrik tersebut memiliki struktur yang persis sama dengan PetFactory, jadi kami akan menghilangkan detailnya dan hanya menggunakannya.

Fungsi BluePopup () ( //membuat jendela popup) BluePopup.prototype.attach = function (elemen) ( //melampirkan elemen ui lain ke jendela) BluePopupFactory.register("popup", BluePopup); function BluePopupButton () ( //membuat tombol untuk jendela popup biru) BluePopupButton.prototype.setText = function (teks) ( //mengatur teks pada tombol) BluePopupFactory.register("button", BluePopupButton); function BluePopupTitle () ( //membuat judul untuk jendela biru) BluePopupTitle.prototype.setText = function (teks) ( //mengatur teks judul) BluePopupFactory.register("title", BluePopupTitle);

Kita mungkin harus memiliki semacam kelas yang bertanggung jawab atas elemen antarmuka.

Fungsi UI () ( //kelas bertanggung jawab atas elemen ui)

Dan kami akan menambahkan metode createPopup ke dalamnya:

UI.createPopup = fungsi (pabrik) ( var popup = pabrik.buat("popup"), buttonOk = pabrik.buat("tombol"), buttonCancel = pabrik.buat("tombol"), judul = pabrik.buat(" title"); buttonOk.setText("OK"); buttonCancel.setText("Batal"); title.setText("Tanpa Judul"); popup.attach(); )

Seperti yang Anda lihat, createPopup menggunakan pabrik sebagai argumen, membuat popup itu sendiri dan tombol-tombol dengan judulnya, lalu melampirkannya ke jendela.
Setelah itu Anda bisa menggunakan cara seperti ini:

Var newPopup = UI.createPopup(BluePopupFactory);

Oleh karena itu, Anda dapat mendeskripsikan pabrik dalam jumlah tidak terbatas dan meneruskan pabrik yang Anda perlukan saat membuat jendela pop-up berikutnya.

Terkadang tidak diinginkan untuk membuat instance kelas secara langsung. Kemudian kami menggunakan pola generatif, yang dapat memilih mekanisme instantiasi yang optimal.

Pabrik Sederhana

Membuat pintu sendiri saat membangun rumah akan cukup sulit, jadi Anda mendapatkannya dari toko yang sudah jadi.

Pola Sebuah pabrik sederhana menghasilkan salinan yang diperlukan tanpa mengganggu klien dengan seluk-beluk proses ini.

Contoh implementasi

Mari buat antarmuka implisit untuk semua pintu:

/* Pintu getWidth() getHeight() */ class WoodenDoor ( konstruktor(lebar, tinggi)( this.width = lebar this.height = tinggi ) getWidth() ( kembalikan this.width ) getHeight() ( kembalikan this.height ) )

Kami akan mengatur pabrik yang akan memproduksinya:

Const DoorFactory = ( makeDoor: (lebar, tinggi) => New WoodenDoor(lebar, tinggi) )

Itu saja, Anda bisa bekerja:

Const door = DoorFactory.makeDoor(100, 200) console.log("Lebar:", door.getWidth()) console.log("Tinggi:", door.getHeight())

Pola ini berguna jika membuat objek memerlukan logika. Masuk akal untuk memindahkan kode berulang ke Pabrik Sederhana yang terpisah.

Metode pabrik

Manajer perekrutan bekerja dengan kandidat untuk berbagai lowongan. Alih-alih menyelidiki seluk-beluk setiap posisi, ia mendelegasikan wawancara teknis kepada sesama spesialis.

Pola ini memungkinkan Anda membuat variasi objek yang berbeda tanpa mencemari konstruktor dengan kode yang tidak perlu.

Contoh implementasi

Mari kita mulai dengan hamburger itu sendiri:

Kelas Burger ( konstruktor(pembuat) ( this.size = pembangun.ukuran ini.cheeze = pembangun.cheeze || false this.pepperoni = pembangun.pepperoni || false this.lettuce = pembangun.selada || false this.tomato = pembangun .tomat ||. salah ) )

Dan inilah Pembangunnya:

Kelas BurgerBuilder ( konstruktor(ukuran) ( this.size = ukuran ) addPepperoni() ( this.pepperoni = true kembalikan ini ) addLettuce() ( this.lettuce = true kembalikan ini ) addCheeze() ( this.cheeze = true kembalikan ini ) addTomato() ( this.tomato = true kembalikan ini ) build() ( kembalikan Burger baru(ini) ) )

Voila! Ini burger kami:

Const burger = (BurgerBuilder baru(14)) .addPepperoni() .addLettuce() .addTomato() .build()

Pola Builder diperlukan jika suatu objek dapat eksis dalam variasi yang berbeda atau proses pembuatan instance terdiri dari beberapa langkah.

Lajang

Negara ini harus memiliki satu presiden, jika tidak maka akan terjadi kekacauan.

Pola ini membungkus suatu objek dan secara dinamis mengubah perilakunya.

Contoh implementasi

Mari kita ambil kopi sebagai contoh. Kopi paling sederhana yang mengimplementasikan antarmuka yang sesuai:

/* Antarmuka kopi: getCost() getDescription() */ class SimpleCoffee( getCost() ( return 10 ) getDescription() ( return "Simple Coffee" ) )

Kami ingin dapat menambahkan berbagai bahan tambahan pada kopi, untuk ini kami akan membuat beberapa dekorator:

Kelas MilkCoffee ( konstruktor(kopi) ( this.coffee = kopi ) getCost() ( kembalikan this.coffee.getCost() + 2 ) getDescription() ( kembalikan this.coffee.getDescription() + ", milk" ) ) kelas WhipCoffee ( konstruktor(kopi) ( this.coffee = kopi ) getCost() ( kembalikan this.coffee.getCost() + 5 ) getDescription() ( kembalikan this.coffee.getDescription() + ", whip" ) ) kelas VanillaCoffee ( konstruktor (kopi) ( this.coffee = kopi ) getCost() ( kembalikan this.coffee.getCost() + 3 ) getDescription() ( kembalikan this.coffee.getDescription() + ", vanilla" ) )

Sekarang Anda bisa membuat kopi sesuai selera Anda:

Biarkan someCoffee someCoffee = new SimpleCoffee() console.log(someCoffee.getCost())// 10 console.log(someCoffee.getDescription())// Simple Coffee someCoffee = new MilkCoffee(someCoffee) console.log(someCoffee.getCost( ))// 12 console.log(someCoffee.getDescription())// Kopi biasa, susu someCoffee = new WhipCoffee(someCoffee) console.log(someCoffee.getCost())// 17 console.log(someCoffee.getDescription() )// Kopi biasa, susu, krim someCoffee = new VanillaCoffee(someCoffee) console.log(someCoffee.getCost())// 20 console.log(someCoffee.getDescription())// Kopi biasa, susu, krim, vanila

Tatapan

Untuk menyalakan komputer, cukup tekan sebuah tombol. Ini sangat sederhana, tetapi ada banyak hal rumit yang terjadi di dalam komputer yang menyala. Antarmuka sederhana untuk sistem yang kompleks adalah Façade.

Contoh implementasi

Mari membuat kelas komputer:

Komputer Kelas ( getElectricShock() ( console.log("Aduh!") ) makeSound() ( console.log("Bip bip!") ) showLoadingScreen() ( console.log("Loading..") ) bam() ( console.log("Siap digunakan!") ) closeEverything() ( console.log("Bup bup bup buzzzz!") ) sooth() ( console.log("Zzzzz") ) pullCurrent() ( console.log("Zzzzz") ) pullCurrent() ( console.log("Zzzzz") ) log("Haaah!") ) )

dan Façade sederhana karena fungsinya yang kompleks:

Kelas ComputerFacade ( konstruktor(komputer) ( this.computer = komputer ) turnOn() ( this.computer.getElectricShock() this.computer.makeSound() this.computer.showLoadingScreen() this.computer.bam() ) turnOff() ( this.computer.closeEverything() this.computer.pullCurrent() this.computer.sooth() ) )

Ini membuat bekerja dengan komputer menjadi lebih mudah:

Komputer const = ComputerFacade baru(Komputer baru()) komputer.turnOn() // Aduh! Bip bip! Loading.. Siap digunakan! komputer.turnOff() // Bup bup buzzz! Haah! Zzzzz

Oportunis

Di kereta jarak jauh, air untuk minuman panas direbus dalam wadah besar - untuk semua orang sekaligus. Ini memungkinkan Anda menghemat listrik (atau gas).

Di situs pencarian kerja, Anda dapat berlangganan opsi pekerjaan yang Anda minati. Ketika tawaran yang sesuai muncul, situs tersebut mengirimkan pemberitahuan kepada Anda.

Pola Pengamat memungkinkan Anda memberi tahu semua objek yang berkepentingan tentang perubahan yang telah terjadi.

Contoh implementasi

Pelamar ingin menerima pemberitahuan:

Const JobPost = title = (( title: title )) class JobSeeker ( konstruktor(nama) ( this._name = name ) notify(jobPost) ( console.log(this._name, "telah diberitahu tentang postingan baru:", pekerjaanPost.judul) ) )

Dan Dewan Pemberitahuan dapat mengirimkan pemberitahuan berikut:

Kelas JobBoard ( konstruktor() ( this._subscribers = ) berlangganan(jobSeeker) ( this._subscribers.push(jobSeeker) ) addJob(jobPosting) ( this._subscribers.forEach(subscriber = ( subscriber.notify(jobPosting) )) ) )

// buat pelanggan const jonDoe = new JobSeeker("John Doe") const janeDoe = new JobSeeker("Jane Doe") const kaneDoe = new JobSeeker("Kane Doe") // buat papan pesan // daftar pelamar const jobBoard = new JobBoard() jobBoard.subscribe(jonDoe) jobBoard.subscribe(janeDoe) // beri tahu pelanggan tentang lowongan baru jobBoard.addJob(JobPost("Software Engineer")) // John Doe telah diberitahu tentang postingan baru: Perangkat Lunak Insinyur // Jane Doe telah diberitahu tentang postingan baru: Insinyur Perangkat Lunak

Pengunjung

Untuk bepergian ke luar negeri, Anda perlu mendapatkan izin (visa). Namun begitu sampai di Tanah Air, Anda bisa dengan aman mengunjungi berbagai tempat tanpa meminta izin tambahan. Anda hanya perlu mengetahuinya.

Pola Pengunjung memungkinkan Anda menambahkan operasi tambahan ke objek tanpa mengubah kode sumbernya.

Contoh implementasi

Mari kita simulasikan kebun binatang dengan berbagai jenis hewan:

Kelas Monyet ( shout() ( console.log("Ooh oo aa aa!") ) terima(operasi) ( operasi.visitMonkey(ini) ) kelas Lion (raung() ( console.log("Roaaar!") ) terima (operasi) ( operasi.visitLion(ini) ) ) kelas Dolphin ( berbicara() ( console.log("Tuut tuttu tuutt!") ) menerima(operasi) ( operasi.visitDolphin(ini) ) )

Sekarang kami ingin mendengarkan suara apa yang mereka buat. Untuk melakukan ini, kami akan membuat Pengunjung:

Const berbicara = ( visitMonkey(monyet)( monkey.shout() ), visitLion(lion)( lion.roar() ), visitDolphin(dolphin)( dolphin.speak() ) )

Itu hanya mengakses setiap kelas dan memanggil metode yang diinginkan:

Const monyet = Monyet baru() const singa = Singa baru() const lumba-lumba = Lumba-lumba baru() monyet.accept(berbicara) // Ooh oo aa aa! lion.accept(berbicara) // Roaaar! dolphin.accept(berbicara) // Tuut tutt tuutt!

Pengunjung mengizinkan objek yang ada untuk tidak diubah. Dengan bantuannya, Anda dapat, misalnya, menambahkan kemampuan melompat ke semua hewan ini tanpa membuat metode tambahan.

Const jump = ( visitMonkey(monkey) ( console.log("Melompat setinggi 20 kaki! ke pohon!") ), visitLion(singa) ( console.log("Melompat setinggi 7 kaki! Kembali ke tanah!") ) , visitDolphin(lumba-lumba) ( console.log("Berjalan di atas air sedikit dan menghilang") ) )

Monkey.accept(berbicara) // Ooh oo aa aa! monkey.accept(jump) // Melompat setinggi 20 kaki! ke pohon! lion.accept(berbicara) // Roaaar! lion.accept(jump) // Melompat 7 kaki! Kembali ke tanah! dolphin.accept(berbicara) // Tuut tutt tuutt! dolphin.accept(jump) // Berjalan di atas air sedikit dan menghilang

Strategi

Untuk mengatur beberapa kumpulan data, Anda menggunakan algoritma pengurutan gelembung. Ini mampu mengatasi volume kecil dengan baik, tetapi melambat dengan volume besar. Quicksort memiliki masalah sebaliknya. Kemudian Anda memutuskan untuk mengubah algoritma tergantung pada ukuran set. Ini adalah Strategi Anda.

Templat Strategi memungkinkan Anda mengganti algoritma yang digunakan tergantung pada situasinya.

Contoh implementasi

Fungsi kelas satu akan membantu Anda mengimplementasikan Strategi dalam JavaScript.

Const bubbleSort = kumpulan data => ( console.log("Penyortiran dengan pengurutan gelembung") // ... // ... mengembalikan kumpulan data ) const quickSort = kumpulan data => ( console.log("Penyortiran dengan penyortiran cepat") / / ... // ... mengembalikan kumpulan data )

Dan ini adalah klien yang dapat menggunakan strategi apa pun:

Penyortir const = kumpulan data => ( if(dataset.length > 5)( return quickSort ) else ( return bubbleSort ) )

Sekarang Anda dapat mengurutkan array:

Const longDataSet = const shortDataSet = const sorter1 = sorter(longDataSet) const sorter2 = sorter(shortDataSet) sorter1(longDataSet) // Mengurutkan dengan quick sort sorter2(shortDataSet) // Mengurutkan dengan bubble sort

Negara

Anda menggambar di Paint. Tergantung pada pilihan Anda, kuas mengubah statusnya: ia melukis dengan warna merah, biru, atau warna lainnya.

Pola State memungkinkan Anda mengubah perilaku kelas ketika statusnya berubah.

Contoh implementasi

Mari buat editor teks di mana Anda dapat mengubah status teks - tebal, miring, dll.

Ini adalah fungsi konversi:

Const huruf besar = inputString => inputString.toUpperCase() const huruf kecil = inputString => inputString.toLowerCase() const defaultTransform = inputString => inputString

Dan inilah editornya sendiri:

Kelas TextEditor ( konstruktor(transform) ( this._transform = transform ) setTransform(transform) ( this._transform = transform ) type(words) ( console.log(this._transform(words)) ) )

Kamu bisa bekerja:

Const editor = new TextEditor(defaultTransform) editor.type("Baris pertama") editor.setTransform(upperCase) editor.type("Baris kedua") editor.type("Baris ketiga") editor.setTransform(lowerCase) editor.type ("Baris keempat") editor.type("Baris kelima") // Baris pertama // BARIS KEDUA // BARIS KETIGA // Baris keempat // baris kelima

Metode templat

Anda membangun rumah sesuai dengan rencana tertentu: pertama pondasi, lalu dinding, dan baru kemudian atap. Urutan langkah-langkah ini tidak dapat diubah, namun penerapannya dapat berbeda-beda.

Metode templat mendefinisikan "kerangka" algoritme, tetapi mendelegasikan implementasi langkah-langkah tersebut ke kelas turunan.

Contoh implementasi

Mari buat alat untuk menguji, membangun, dan menerapkan aplikasi.

Kelas dasar mendefinisikan kerangka algoritma perakitan:

Pembuat Kelas ( // Metode templat build() ( this.test() this.lint() this.assemble() this.deploy() ) )

Dan kelas anak adalah implementasi spesifik dari setiap langkah:

Kelas AndroidBuilder extends Builder ( test() ( console.log("Menjalankan tes android") ) lint() ( console.log("Linting kode android") ) assemble() ( console.log("Merakit build android" ) ) deploy() ( console.log("Menyebarkan android build ke server") ) class IosBuilder extends Builder ( test() ( console.log("Menjalankan tes ios") ) lint() ( console.log("Linting the kode ios") ) assemble() ( console.log("Merakit build ios") ) deploy() ( console.log("Menyebarkan build ios ke server") ) )

Mari kita susun proyeknya:

Const androidBuilder = new AndroidBuilder() androidBuilder.build() // Menjalankan pengujian android // Melinting kode android // Merakit build android // Men-deploy build android ke server const iosBuilder = new IosBuilder() iosBuilder.build() // Menjalankan pengujian ios // Melinting kode ios // Merakit build ios // Men-deploy build ios ke server

  • Terjemahan

Catatan Penerjemah: Topik pewarisan dalam JavaScript adalah salah satu topik tersulit bagi pemula. Dengan penambahan sintaks baru dengan kata kunci class, memahami pewarisan dengan jelas menjadi lebih mudah, meskipun tidak ada hal baru yang muncul. Artikel ini tidak menyentuh nuansa penerapan pewarisan prototipe di JavaScript, jadi jika pembaca memiliki pertanyaan, saya sarankan membaca artikel berikut: Dasar-dasar dan Kesalahpahaman tentang JavaScript dan Pengertian OOP di JavaScript [Bagian 1]

Untuk komentar apa pun terkait terjemahan, silakan hubungi kami melalui pesan pribadi.

JavaScript adalah bahasa yang sangat kuat. Begitu kuatnya sehingga banyak cara berbeda dalam mendesain dan membuat objek hidup berdampingan di dalamnya. Setiap metode memiliki pro dan kontra dan saya ingin membantu pemula mengetahuinya. Ini merupakan kelanjutan dari postingan saya sebelumnya, Hentikan "mengkategorikan" JavaScript. Saya telah menerima banyak pertanyaan dan komentar yang meminta contoh, dan untuk tujuan inilah saya memutuskan untuk menulis artikel ini.

JavaScript menggunakan pewarisan prototipikal Artinya dalam JavaScript, objek diwarisi dari objek lain. Objek sederhana dalam JavaScript yang dibuat menggunakan () kurung kurawal hanya memiliki satu prototipe: Objek.prototipe. Objek.prototipe, pada gilirannya, juga merupakan objek, dan semua properti serta metode Objek.prototipe tersedia untuk semua objek.

Array yang dibuat dengan menggunakan tanda kurung siku memiliki beberapa prototipe antara lain Objek.prototipe Dan Array.prototipe. Ini berarti semua properti dan metode Objek.prototipe Dan Array.prototipe tersedia untuk semua array. Properti dan metode dengan nama yang sama, misalnya .Nilai dari Dan .ToString, dipanggil dari prototipe terdekat, dalam hal ini dari Array.prototipe.

Definisi Prototipe dan Pembuatan Objek Metode 1: Pola Konstruktor JavaScript memiliki tipe fungsi khusus yang disebut konstruktor, yang bertindak dengan cara yang sama seperti konstruktor dalam bahasa lain. Fungsi konstruktor dipanggil hanya menggunakan kata kunci baru dan mengaitkan objek yang dibuat dengan konteks fungsi konstruktor melalui kata kunci ini. Konstruktor tipikal mungkin terlihat seperti ini:
function Animal(type)( this.type = type; ) Animal.isAnimal = function(obj, type)( if(!Animal.prototype.isPrototypeOf(obj))( return false; ) tipe kembalian ? obj.type === ketik: benar); fungsi Anjing(nama, ras)( Animal.call(ini, "anjing"); this.name = nama; this.breed = ras; ) Object.setPrototypeOf(Dog.prototype, Animal.prototype); Anjing.prototipe.bark = function())( console.log("ruff, ruff"); ); Dog.prototype.print = function())( console.log("Anjing " + nama ini + " adalah " + ras ini); ); Dog.isDog = function(obj)( return Animal.isAnimal(obj, "dog"); );
Menggunakan konstruktor ini terlihat sama dengan membuat objek dalam bahasa lain:
var sparkie = Anjing baru("Sparkie", "Border Collie"); sparkie.nama; // "Sparkie" sparkie.berkembang biak; // "Border Collie" sparkie.bark(); // konsol: "ruff, ruff" sparkie.print(); // konsol: "Anjing Sparkie adalah Border Collie" Dog.isDog(sparkie); // BENAR
kulit pohon Dan mencetak metode prototipe yang berlaku untuk semua objek yang dibuat menggunakan konstruktor Anjing. Properti nama Dan keturunan diinisialisasi di konstruktor. Ini adalah praktik umum untuk mendefinisikan semua metode dalam prototipe dan properti untuk diinisialisasi oleh konstruktor. Metode 2: Mendefinisikan Kelas dalam Kata Kunci ES2015 (ES6). kelas telah dicadangkan dalam JavaScript sejak awal dan sekarang saatnya untuk menggunakannya. Definisi kelas dalam JavaScript mirip dengan bahasa lain.
kelas Hewan ( konstruktor(tipe)( this.type = tipe; ) static isAnimal(obj, tipe)( if(!Animal.prototype.isPrototypeOf(obj))( return false; ) tipe kembali ? obj.type === tipe : benar; ) ) kelas Anjing meluas Hewan ( konstruktor(nama, ras)( super("anjing"); nama ini = nama; ras ini = ras; ) kulit())( console.log("ruff, ruff " ); ) print() ( console.log("Anjing " + nama ini + " adalah " + ras ini); ) static isDog(obj)( return Animal.isAnimal(obj, "dog"); ) )
Banyak orang menganggap sintaks ini nyaman karena menggabungkan konstruktor dan deklarasi metode statis dan prototipe dalam satu blok. Cara penggunaannya sama persis dengan cara sebelumnya.
var sparkie = Anjing baru("Sparkie", "Border Collie"); Metode 3: Deklarasi Prototipe Eksplisit, Object.create, Metode Pabrik Metode ini menunjukkan sintaks kata kunci baru sebenarnya kelas menggunakan warisan prototipikal. Cara ini juga memungkinkan Anda membuat objek baru tanpa menggunakan operator baru.
var Hewan = ( buat(tipe)( var hewan = Objek.buat(Hewan.prototipe); hewan.tipe = tipe; kembalikan hewan; ), isAnimal(obj, ketik)( if(!Animal.prototype.isPrototypeOf(obj) )( mengembalikan salah; ) mengembalikan tipe ? obj.type === tipe: true ), prototipe: () ); var Anjing = ( buat(nama, ras)( var proto = Object.assign(Animal.create("dog"), Dog.prototype); var dog = Object.create(proto); dog.name = nama; anjing. berkembang biak = berkembang biak; kembalikan anjing; ), isDog(obj)( kembalikan Animal.isAnimal(obj, "dog"); ), prototipe: ( kulit())( console.log("ruff, ruff"); ), cetak ( )( console.log("Anjing " + nama ini + " adalah " + ras ini); ) ) );
Sintaks ini nyaman karena prototipe dideklarasikan secara eksplisit. Jelas apa yang didefinisikan dalam prototipe dan apa yang didefinisikan dalam objek itu sendiri. metode Objek.buat nyaman karena memungkinkan Anda membuat objek dari prototipe tertentu. Memeriksa dengan .isPrototypeOf masih berfungsi dalam kedua kasus. Kegunaannya bermacam-macam, namun tidak berlebihan:
var sparkie = Anjing.create("Sparkie", "Border Collie"); sparkie.nama; // "Sparkie" sparkie.berkembang biak; // "Border Collie" sparkie.bark(); // konsol: "ruff, ruff" sparkie.print(); // konsol: "Anjing Sparkie adalah Border Collie" Dog.isDog(sparkie); // true Metode 4: Object.create, pabrik tingkat atas, prototipe yang ditangguhkan Metode ini merupakan sedikit modifikasi dari metode 3, di mana kelas itu sendiri adalah pabrik, berbeda dengan kasus di mana kelas adalah objek dengan metode pabrik . Mirip dengan contoh konstruktor (metode 1), tetapi menggunakan metode pabrik dan Objek.buat.
function Animal(type)( var animal = Object.create(Animal.prototype); animal.type = type; return animal; ) Animal.isAnimal = function(obj, type)( if(!Animal.prototype.isPrototypeOf(obj) )( mengembalikan salah; ) mengembalikan tipe ? obj.type === tipe: true ); Hewan.prototipe =(); fungsi Anjing(nama, ras)( var proto = Object.assign(Animal("dog"), Dog.prototype); var dog = Object.create(proto); dog.name = nama; dog.breed = berkembang biak; kembali anjing; ) Anjing.isDog = function(obj)( return Animal.isAnimal(obj, "dog"); ); Anjing.prototipe = ( kulit())( console.log("ruff, ruff"); ), print())( console.log("Anjing " + nama ini + " adalah " + ras ini) ;
Cara ini menarik karena mirip dengan cara pertama, namun tidak memerlukan kata kunci baru dan bekerja dengan operator contoh. Cara penggunaannya sama seperti cara pertama, namun tanpa menggunakan kata kunci baru:
var sparkie = Anjing("Sparkie", "Border Collie"); sparkie.nama; // "Sparkie" sparkie.berkembang biak; // "Border Collie" sparkie.bark(); // konsol: "ruff, ruff" sparkie.print(); // konsol: "Anjing Sparkie adalah Border Collie" Dog.isDog(sparkie); // true Perbandingan Metode 1 vs Metode 4 Hanya ada sedikit alasan untuk menggunakan Metode 1 dibandingkan Metode 4. Metode 1 memerlukan penggunaan kata kunci baru, atau menambahkan tanda centang berikut di konstruktor:
if(!(ini instanceof Foo))( kembalikan Foo baru(a, b, c); )
Dalam hal ini lebih mudah digunakan Objek.buat dengan metode pabrik. Anda juga tidak dapat menggunakan fungsi Fungsi#panggilan atau Fungsi#berlaku dengan fungsi konstruktor karena mengesampingkan konteks kata kunci ini. Pemeriksaan di atas mungkin menyelesaikan masalah ini, tetapi jika Anda perlu bekerja dengan jumlah argumen yang tidak diketahui sebelumnya, Anda harus menggunakan metode pabrik. Metode 2 vs Metode 3 Alasan yang sama tentang konstruktor dan operator baru yang disebutkan di atas berlaku dalam kasus ini. Memeriksa dengan contoh diperlukan jika sintaks baru digunakan kelas tanpa menggunakan operator baru atau digunakan Fungsi#panggilan atau Fungsi#berlaku.Pendapat saya Seorang programmer harus mengupayakan kejelasan dalam kodenya. Sintaks Metode 3 memperjelas apa yang sebenarnya terjadi. Ini juga memudahkan penggunaan pewarisan berganda dan pewarisan tumpukan. Sejak operator baru melanggar prinsip terbuka/tertutup karena ketidakcocokan dengan menerapkan atau panggilan, itu harus dihindari. Kata kunci kelas menyembunyikan sifat prototipe warisan dalam JavaScript di balik topeng sistem kelas.
“Sederhana lebih baik daripada canggih,” dan menggunakan kelas karena dianggap lebih “canggih” hanya akan membuat pusing kepala teknis yang tidak perlu.
Penggunaan Objek.buat lebih ekspresif dan jelas dibandingkan menggunakan copula baru Dan ini. Selain itu, prototipe disimpan dalam objek yang berada di luar konteks pabrik itu sendiri, dan dengan demikian dapat lebih mudah dimodifikasi dan diperluas dengan menambahkan metode. Sama seperti kelas di ES6.
Kata kunci kelas, mungkin merupakan fitur JavaScript yang paling merugikan. Saya sangat menghormati orang-orang brilian dan pekerja keras yang terlibat dalam proses penulisan standar, namun bahkan orang-orang brilian pun terkadang melakukan hal yang salah. - Eric Elliott
Menambahkan sesuatu yang tidak perlu dan mungkin berbahaya, bertentangan dengan sifat bahasa, adalah tindakan yang tidak bijaksana dan salah.
Jika Anda memutuskan untuk menggunakan kelas, Saya sangat berharap saya tidak perlu lagi bekerja dengan kode Anda. Menurut pendapat saya, pengembang harus menghindari penggunaan konstruktor, kelas Dan baru, dan menggunakan metode yang lebih natural terhadap paradigma dan arsitektur bahasanya. Glosarium Objek.assign(a, b) menyalin semua properti enumerable suatu objek B untuk menolak A dan kemudian mengembalikan objek tersebut A
Objek.buat(proto) membuat objek baru dari prototipe yang ditentukan proto
Objek.setPrototypeOf(obj, proto) mengubah properti internal [] obyek keberatan pada proto

Tag: Tambahkan tag

WordPress menggunakan templat di mana saja dan Javascript tidak terkecuali. Dalam postingan ini, kita akan membahas tentang kemampuan bawaan WordPress untuk membuat template HTML, yang kemudian dapat digunakan di JS. Templat ini sangat mudah dibuat dan digunakan, sama seperti banyak hal lainnya di WordPress.

Ada banyak cara untuk membuat template dalam Javascript, bahkan ada spesifikasi tersendiri yang disebut Moustache. Ini diterapkan dalam banyak bahasa, termasuk Javascript. Misalnya, pustaka Handlebars menggunakan spesifikasi ini dan bahkan sedikit memperluasnya. Atau perpustakaan mini Underscore yang populer.

Sejak versi 3.5, WordPress sudah memiliki mesin template yang nyaman untuk JS pada intinya. Misalnya, digunakan di panel admin saat membuat blok untuk pemuat media. Berdasarkan pustaka Underscore yang disebutkan di atas, sintaksnya telah sedikit dimodifikasi agar lebih konsisten dengan spesifikasi Moustache.

Untuk membuat template di WordPress ada metode wp.template

wp.template(id)

Membuat objek template dari kode HTML. Untuk mendapatkan kode HTML siap pakai untuk digunakan di JS, Anda perlu meneruskan data untuk mengisi template ke objek yang dibuat.

Kembali

Fungsi. Fungsi untuk meneruskan data untuk interpolasi templat.

Menggunakan var template = wp.template(id); var HTML = templat(data); pengenal (garis)

ID elemen HTML yang berisi kode HTML template. Elemen HTML harus memiliki atribut id yang ditentukan di sini dengan awalan tmpl-.

Misalnya, jika Anda menentukan foo di sini, maka elemen HTML harus memiliki id id="tmpl-foo" .

Data (Sebuah Objek) Objek data JS yang akan digunakan untuk mengisi template. Misalnya: ( teks: "Halo") .

Pengisian Pola (Interpolasi)
  • (((data.unescaped))) - data yang tidak dibersihkan.
  • ((data.escaped)) - data dihapus.
  • - proses js (eval).
Awalan data.

data dalam templat adalah objek data sumber. Kunci data harus digunakan dalam templat.

Untuk mencocokkan struktur data yang dikembalikan oleh fungsi wp_send_json_success() dan wp_send_json_error(), wp.template membungkus semua data yang diterima dalam variabel data. Oleh karena itu, sebelum setiap parameter dalam template, Anda perlu menentukan data. , jika tidak, kita akan mendapatkan kesalahan: (properti) tidak ditentukan.

Benar (((data.nama)))

Salah (((nama)))

Contoh templat

Ini hanya akan menjadi keluaran.

Mari kita cetak nilai variabel escapeValue ((data.escapedValue)).

Jika data berisi markup, cetaklah tanpa keluar:

(((data.unescapedValue)))

Ketika Anda perlu melakukan beberapa logika.

Hanya akan dicetak jika data.trueValue = true.

Membuat dan membuat template Membuat template

Untuk memastikan bahwa templat tidak muncul dengan cara apa pun di pohon DOM, biasanya dibuat dalam tag skrip dengan indikasi tipe type="text/html" .

Halo (((data.nama)))

Atribut id harus dimulai dengan tmpl- , apa pun setelah awalan ini akan digunakan dalam fungsi wp.template("my-template") .

Membuat template dalam tag skrip adalah peretasan yang bagus untuk membuat elemen html yang tidak digunakan dengan cara apa pun oleh browser. Ketika jenis yang tidak dapat dipahami oleh browser ditentukan, itu hanya mengabaikan tag html, yang kita perlukan.

Templat juga dapat dibuat di elemen HTML lainnya (misalnya, di , yang kemudian dapat disembunyikan), satu-satunya hal yang perlu Anda lakukan adalah menentukan atribut id.

Ada juga tag HTML khusus untuk membuat template, namun tidak didukung di IE. Namun secara keseluruhan cukup relevan.

Pembuatan templat

wp.template() mengembalikan fungsi, jadi jangan mencoba meneruskan hasilnya ke elemen html atau mencetak hasilnya ke konsol. Biasanya, hasil wp.template() diteruskan ke sebuah variabel, dan kemudian variabel tersebut digunakan sebagai fungsi dan meneruskan data yang harus diisi template.

Contoh (templat yang ditunjukkan di atas)

// JS var template = wp.template("my-template"), data = ( nama: "Victor" ); jQuery(".elemen-saya").html(templat(data));

Hasilnya, kami mendapatkan dalam HTML:

Halo Victor

Contoh komentar AJAX menggunakan template

Buat templat dan sertakan skrip dalam file function.php tema:

  • (((data.gravatar))) ((data.comment_author))