Rumah > Artikel > hujung hadapan web > Pemahaman mendalam tentang konsep prototaip dalam pengaturcaraan JavaScript_Pengetahuan asas
Objek prototaip JavaScript sentiasa mengelirukan. Malah pakar JavaScript yang berpengalaman dan juga pengarangnya sering memberikan penjelasan yang sangat terhad tentang konsep ini. Saya percaya masalah itu datang daripada pemahaman terawal kami tentang prototaip. Prototaip sentiasa berkait rapat dengan sifat prototaip baharu, pembina dan yang mengelirukan. Malah, prototaip adalah konsep yang agak mudah. Untuk memahaminya dengan lebih baik, kita perlu melupakan arketaip pembinaan yang kita 'pelajari' dan, kemudian, kembali ke akar umbi.
Apakah prototaip?
Prototaip ialah objek yang mewarisi sifat daripada objek lain.
Bolehkah mana-mana objek menjadi prototaip?
Ya
Objek tersebut mempunyai prototaip?
Setiap objek mempunyai prototaip lalai. Prototaip itu sendiri adalah objek, dan setiap prototaip itu sendiri mempunyai prototaip. (Dengan satu pengecualian, prototaip objek lalai berada di bahagian atas setiap rantai prototaip, dan prototaip lain berada di penghujung rantai prototaip)
Mengambil langkah ke belakang, apakah objek?
Dalam JavaScript, objek ialah koleksi tidak tertib arbitrari yang disimpan sebagai pasangan nilai kunci Jika ia bukan kelas primitif (tidak ditentukan, null, boolean.nuber atau rentetan), ia ialah objek.
Anda boleh berfikir bahawa setiap objek mempunyai prototaip Tetapi apabila saya menulis ({}).prototaip, saya tidak pasti.
Lupakan semua yang anda ketahui tentang sifat prototaip - ini mungkin punca kekeliruan Prototaip sebenar objek ialah sifat dalaman [[Prototaip]] ECMA 5 memperkenalkan kaedah akses standard, Object.getPrototypeOf(object ). . Pelaksanaan terbaharu ini disokong oleh Firefox, Safari, Chrome dan IE9 Selain itu, kecuali IE, semua penyemak imbas menyokong kaedah akses bukan standard __proto__ Jika tidak, kita hanya boleh mengatakan bahawa pembina objek ialah Prototaip Properties.
var a = {}; //Opera 或 IE<=8下失败 Object.getPrototypeOf(a); //[object Object] //IE下失败 a.__proto__; //[object Object] //所有浏览器 //(but only if constructor.prototype has not been replaced and fails with Object.create) a.constructor.prototype; //[object Object]
Sangat bagus, false ialah jenis primitif, kenapa false.__proto__ mengembalikan nilai?
Apabila mengakses prototaip jenis primitif, ia akan dipaksa menjadi objek.
//(works in IE<=8 too, due to double-negative) false.__proto__ === Boolean(false).__proto__; //true
Saya ingin melaksanakan pewarisan menggunakan prototaip, apakah yang perlu saya lakukan sekarang?
Adalah hampir tidak bermakna untuk menambah sifat prototaip pada contoh Melainkan terdapat satu situasi, iaitu, adalah sangat cekap untuk menambah sifat secara langsung pada contoh itu sendiri . Fungsi Sebagai contoh Array, kita boleh melakukan ini
//fails in IE<=8 var a = {}; a.__proto_ = Array.prototype; a.length; //0
Tetapi kita dapat melihat bahawa kuasa sebenar prototaip terletak pada berbilang kejadian yang berkongsi prototaip yang sama. Sifat objek prototaip ditakrifkan sekali dan diwarisi oleh semua kejadian yang dirujuknya. Peningkatan prestasi dan kebolehselenggaraan program menggunakan prototaip adalah jelas. Jadi adakah ini sebab untuk pembina? Ya, pembina menyediakan mekanisme penyemak imbas yang mudah untuk tugasan prototaip biasa pada penciptaan contoh. .
Sebelum memberikan contoh, saya perlu tahu apa yang dilakukan oleh sifat constructor.prototype?
Nah, pertama sekali, JavaScript tidak membezakan antara pembina dan kaedah lain, jadi setiap kaedah mempunyai atribut prototaip. Sebaliknya, apa-apa yang bukan kaedah tidak mempunyai sifat sedemikian.
//永远不是构造函数的方法,无论如何都是有prototype属性的 Math.max.prototype; //[object Object] //构造函数也有prototype属性 var A = function(name) { this.name = name; } A.prototype; //[object Object] //Math不是一个方法,所以没有prototype属性 Math.prototype; //null
Kini anda boleh mentakrifkan: Atribut prototaip kaedah ialah objek prototaip yang diberikan kepada tika apabila kaedah ini digunakan sebagai pembina untuk mencipta tika.
Adalah sangat penting untuk memahami bahawa atribut prototaip sesuatu kaedah tiada kaitan dengan prototaip sebenar.
//(在IE中会失败) var A = function(name) { this.name = name; } A.prototype == A.__proto__; //false A.__proto__ == Function.prototype; //true - A的prototype是它的构造函数的prototype属性
Bolehkah anda memberi contoh?
Anda mungkin pernah melihat atau menggunakan kod berikut beratus kali, tetapi ini sekali lagi, tetapi mungkin ada sesuatu yang baharu.
//构造器. <em>this</em> 作为新对象返回并且它内部的[[prototype]]属性将被设置为构造器默认的prototype属性 var Circle = function(radius) { this.radius = radius; //next line is implicit, added for illustration only //this.__proto__ = Circle.prototype; } //扩充 Circle默认的prototype对象的属性因此扩充了每个由它新建实例的prototype对象的属性 Circle.prototype.area = function() { return Math.PI*this.radius*this.radius; } //创建Circle的两个示例,每个都会使用相同的prototype属性 var a = new Circle(3), b = new Circle(4); a.area().toFixed(2); //28.27 b.area().toFixed(2); //50.27
Ini bagus. Jika saya menukar sifat prototaip pembina, bolehkah objek contoh sedia ada segera mengakses versi prototaip baharu?
Hmm... tidak juga. Jika saya mengubah suai atribut prototaip sedia ada, maka ini memang berlaku, kerana a.__proto__ merujuk kepada objek yang ditakrifkan oleh A.prototype apabila objek itu dicipta.
var A = function(name) { this.name = name; } var a = new A('alpha'); a.name; //'alpha' A.prototype.x = 23; a.x; //23
Tetapi jika saya menggantikan atribut prototaip dengan objek baharu, a.__proto__ masih menunjuk ke objek asal.
var A = function(name) { this.name = name; } var a = new A('alpha'); a.name; //'alpha' A.prototype = {x:23}; a.x; //null
Apakah rupa prototaip lalai?
Objek dengan sifat pembina.
var A = function() {}; A.prototype.constructor == A; //true var a = new A(); a.constructor == A; //true (a 的constructor属性继承自它的原型)
Apakah hubungan antara instanceof dan prototaip?
Jika atribut prototaip A muncul dalam rantaian prototaip a, ungkapan a instanceof A akan kembali benar. Ini bermakna kita boleh menipu instanceof untuk gagal.
var A = function() {} var a = new A(); a.__proto__ == A.prototype; //true - so instanceof A will return true a instanceof A; //true; //mess around with a's prototype a.__proto__ = Function.prototype; //a's prototype no longer in same prototype chain as A's prototype property a instanceof A; //false
那么我还能利用原型干些其它的什么事儿?
记得我曾经说过每一个构造器都拥有一个prototype属性,利用该属性可以将原型赋值给所有由构造器产生的实例?其实这同样适用于本地构造器,例如Function和String。通过扩展(而不是替换)这个属性,我们可以更新每个指定类型对象的prototype。
String.prototype.times = function(count) { return count < 1 ? '' : new Array(count + 1).join(this); } "hello!".times(3); //"hello!hello!hello!"; "please...".times(6); //"please...please...please...please...please...please..."
告诉我更多关于继承与原型是怎么工作的。原型链又是什么东东?
因为每个对象和每个原型(本身)都有一个原型,我们可以想象, 一个接一个的对象连接在一起形成一个原型链。 原型链的终端总是默认对象(object)的原型。
a.__proto__ = b; b.__proto__ = c; c.__proto__ = {}; //默认对象 {}.__proto__.__proto__; //null
原型继承机制是内在且隐式实现的。当对象a要访问属性foo时,Javascript会遍历a的原型链(首先从a自身开始),检查原型链的每一个环节中存在的foo属性。如果找到了foo属性就会将其返回,否则返回undefined值。
直接赋值会咋样?
当直接为对象属性赋值时,原型继承机制就玩不转了。a.foo='bar'会直接赋值给a的foo属性。要想为原型对象的属性赋值,你需要直接定位原型对象的该属性。
关于javascript原型就讲全了。我觉得对于原型概念的理解,我把握的还是比较准确的,但是我的观点无论如何也不是最后的结果。请随便告之我的错误之处或提出和我不一致的观点。