Rumah > Artikel > hujung hadapan web > Penjelasan terperinci tentang prinsip kerja dan contoh kemahiran javascript prototaip inheritance_javascript
Pertama, saya akan berkongsi dengan anda contoh warisan prototaip JS untuk rujukan anda Kandungan khusus adalah seperti berikut
1. Warisan prototaip JS
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JS原型继承</title> </head> <body> <!--原型继承--> <script type="text/javascript"> //clone()函数用来创建新的类Person对象 var clone = function(obj) { var _f = function() {}; //这句是原型式继承最核心的地方,函数的原型对象为对象字面量 _f.prototype = obj; return new _f; } //先声明一个对象字面量 var Animal = { somthing: 'apple', eat: function() { console.log("eat " + this.somthing); } } //不需要定义一个Person的子类,只要执行一次克隆即可 var Cat = clone(Animal); //可以直接获得Person提供的默认值,也可以添加或者修改属性和方法 console.log(Cat.eat()); Cat.somthing = 'orange'; console.log(Cat.eat()); //声明子类,执行一次克隆即可 var Someone = clone(Cat); </script> </body> </html>
2. Cara pewarisan prototaip JavaScript berfungsi
Adalah diketahui bahawa JavaScript menggunakan warisan prototaip, tetapi kerana ia hanya menyediakan satu contoh pelaksanaan secara lalai, iaitu pengendali baharu, penjelasannya sentiasa mengelirukan. Apakah yang perlu saya jelaskan seterusnya ialah warisan prototaip dan cara penggunaannya ia dalam JavaScript.
Takrifan warisan prototaip
Apabila anda membaca penjelasan tentang warisan prototaip JS, anda akan sering melihat teks berikut:
Apabila mencari sifat objek, JavaScript merentasi rantaian prototaip sehingga ia menemui sifat dengan nama tertentu. ——Dari JavaScript Secret Garden
Kebanyakan pelaksanaan JavaScript menggunakan atribut __proto__ untuk mewakili rantai prototaip objek. Dalam artikel ini kita akan melihat apakah perbezaan antara __proto__ dan prototaip.
Nota: __proto__ ialah penggunaan tidak formal yang tidak sepatutnya muncul dalam kod anda. Ia hanya digunakan di sini untuk menerangkan cara warisan prototaip JavaScript berfungsi.
Kod berikut menunjukkan cara enjin JS mencari atribut:
function getProperty(obj, prop) { if (obj.hasOwnProperty(prop)) return obj[prop] else if (obj.__proto__ !== null) return getProperty(obj.__proto__, prop) else return undefined }
Mari kita ambil contoh biasa: titik dua dimensi, dengan koordinat dua dimensi x y , juga mempunyai kaedah cetakan.
Menggunakan takrif warisan prototaip yang kami nyatakan sebelum ini, kami mencipta objek Titik dengan tiga sifat: x, y dan cetakan. Untuk mencipta titik dua dimensi baharu, kita perlu mencipta objek baharu dan biarkan atribut __proto__nya menghala ke Titik:
var Point = { x: 0, y: 0, print: function () { console.log(this.x, this.y); } }; var p = {x: 10, y: 20, __proto__: Point}; p.print(); // 10 20
Warisan prototaip pelik JavaScript
Perkara yang mengelirukan ialah setiap orang yang mengajar warisan prototaip tidak akan memberikan sekeping kod sedemikian, tetapi akan memberikan kod berikut:
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { print: function () { console.log(this.x, this.y); } }; var p = new Point(10, 20); p.print(); // 10 20
Ini berbeza daripada apa yang dijanjikan di sini Point menjadi fungsi, dan kemudian terdapat sifat prototaip, dan terdapat pengendali baru. Apa yang berlaku dengan lelaki ini?
Cara pengendali baharu berfungsi
Pencipta Brendan Eich mahu JS serupa dengan bahasa pengaturcaraan berorientasikan objek tradisional, seperti Java dan C++. Dalam bahasa ini, kami menggunakan operator baharu untuk membuat instantiate objek baharu untuk kelas. Jadi dia menulis operator baru di JS.
C++ mempunyai konsep pembina yang digunakan untuk memulakan sifat contoh, jadi pengendali baharu mesti menyasarkan fungsi.
Kita perlu meletakkan kaedah objek di satu tempat, dan kerana kita menggunakan bahasa prototaip, kita meletakkannya dalam atribut prototaip fungsi tersebut.
Operator baharu menerima fungsi F dan hujahnya: F baharu(argumen...). Proses ini terbahagi kepada tiga langkah:
Buat contoh kelas. Langkah ini adalah untuk menetapkan atribut __proto__ objek kosong kepada F.prototype.
Mulakan contoh. Fungsi F dipanggil dengan hujah yang dihantar, dan kata kunci ini ditetapkan kepada contoh.
Kembalikan contoh.
Kini setelah kami tahu cara baharu berfungsi, kami boleh melaksanakannya dengan kod JS:
function New (f) { var n = { '__proto__': f.prototype }; /*第一步*/ return function () { f.apply(n, arguments); /*第二步*/ return n; /*第三步*/ }; }
Contoh kecil untuk melihat status kerjanya:
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { print: function () { console.log(this.x, this.y); } }; var p1 = new Point(10, 20); p1.print(); // 10 20 console.log(p1 instanceof Point); // true var p2 = New (Point)(10, 20); p2.print(); // 10 20 console.log(p2 instanceof Point); // true
Warisan prototaip sebenar dalam JavaScript
Spesifikasi ECMA JS hanya membenarkan kami menggunakan operator baharu untuk pewarisan prototaip. Tetapi tuan besar Douglas Crockford menemui cara untuk menggunakan baharu untuk mencapai warisan prototaip sebenar! Dia menulis fungsi Object.create seperti berikut:
Object.create = function (parent) { function F() {} F.prototype = parent; return new F(); };
Ini kelihatan pelik, tetapi agak kemas: ia mencipta objek baharu dan menetapkan prototaipnya kepada apa-apa nilai yang anda mahukan. Jika kita membenarkan penggunaan __proto__, maka kita juga boleh menulis:
Object.create = function (parent) { return { '__proto__': parent }; };
Kod berikut membolehkan Point kami menerima pakai warisan prototaip sebenar:
var Point = { x: 0, y: 0, print: function () { console.log(this.x, this.y); } }; var p = Object.create(Point); p.x = 10; p.y = 20; p.print(); // 10 20
Kesimpulan
Kami telah mempelajari apa itu warisan prototaip JS dan cara JS melaksanakannya dengan cara yang khusus. Walau bagaimanapun, menggunakan warisan prototaip benar (seperti Object.create dan __proto__) masih mempunyai kelemahan berikut:
Penyawaian yang lemah: __proto__ bukanlah penggunaan standard, malah penggunaan yang tidak digunakan lagi. Pada masa yang sama, Object.create asal dan versi asal yang ditulis oleh Dao Ye juga berbeza.
Pengoptimuman yang lemah: Sama ada ia asli atau tersuai Object.create, prestasinya jauh kurang dioptimumkan berbanding baharu dan yang pertama adalah sehingga 10 kali lebih perlahan daripada yang kedua.
Di atas adalah keseluruhan kandungan artikel ini, saya harap ia akan membantu kajian semua orang.