Dalam JavaScript, array dapat dibuat menggunakan konstruktor array, atau dibuat dengan cepat menggunakan [], yang juga merupakan metode yang disukai. Array adalah prototipe yang diwarisi dari objek, dan tidak memiliki nilai pengembalian khusus untuk TypeOf, itu hanya mengembalikan 'objek'.
Di JS, dapat dikatakan bahwa semuanya adalah objek, dan array juga merupakan array.
Banyak objek memiliki banyak metode yang nyaman seperti dorongan, concat, irisan, dll. Dari array, tetapi jika beberapa objek tidak mengimplementasikan metode ini, kami masih ingin menggunakan fungsi -fungsi ini. Jadi apa yang harus saya lakukan?
1. Banyak metode memberikan implementasi yang sangat efisien, dan kami dapat mensimulasikan implementasinya.
Misalnya, browser di bawah IE8 tidak mendukung metode indeks array. Untuk membuat indeks dukungan array, kita dapat menulis metode sendiri untuk mengimplementasikan metode indeks dari:
(Tekan F12 untuk men -debug dengan IE Browser untuk memilih versi browser ke IE5.)
var arr = [,,,]; if (array.prototype.indexof) {alert ("browser Anda mendukung metode indeks dari metode.");} else {alert ("browser Anda tidak mendukung metode indeks dari metode ini. {if (this [i] == item) {return i;}} return -;}} alert (arr.indexof ()); waspada (arr.indexof ());Tentu saja metode ini sangat sampah. Saya tidak akan jelek dalam implementasi spesifik di sini, dan memberikan versi salinan di Baidu:
Jika Anda tertarik, Anda dapat melihat bagaimana mesin V8 diimplementasikan: https://github.com/v8/v8/blob/master/src/js/array.js
if (! array.prototype.indexof) {array.prototype.indexof = function (elt /*, dari* /) {var len = this.length >>>; var from = number (argumen []) || ; dari = (dari <)? Math.ceil (dari): Math.floor (dari); if (from <) from+= len; for (; from <len; from ++) {if (from in this && this [from] === elt) kembali dari;} return -;};}2. Panggilan warisan dan terapkan metode
Jika kita memiliki objek, bukankah sangat merepotkan untuk menulis setiap objek untuk mengimplementasikannya sendiri?
Dalam bahasa tingkat tinggi, kita dapat menggunakan warisan untuk menyelesaikan masalah, seperti kode Java berikut:
MyList kelas publik <e> memperluas arraylist <e> {public void myAdd (e e) {super.add (e); system.out.println ("add:"+e);}}Tetapi tidak ada konsep warisan dalam JS. Kami dapat menggunakan panggilan dan melamar untuk menyelesaikan masalah tersebut.
Kode di atas dapat ditulis ulang sebagai:
var myobject = function () {} myobject.prototype.add = function () {array.prototype.push.call (ini, argumen); // argumen output untuk (var i =; i <argumen.Di sini kita dapat melihat: Meskipun metode MyAdd diimplementasikan dalam metode warisan bahasa tingkat tinggi, metode MyADD hanya dapat melewati satu parameter sekarang. Jika Anda ingin melewati beberapa parameter, Anda perlu menulis metode public myAdd (E [] e) lainnya, atau bahkan metode public void myADD (daftar <E> e). JS dapat dilakukan dengan satu metode, menggunakan objek argumen untuk mewakili semua input parameter, yang sulit dilakukan bahasa tingkat tinggi.
(PS, pada kenyataannya, Anda dapat menulis public void myadd (e ... e) di java. Ini adalah parameter yang tidak pasti. Penggunaan myadd public void (e [] e) adalah sama)
Metode panggilan dan terapkan digunakan untuk mengubah pointer pointer ini di fungsi. Panggilan hanya memiliki dua parameter, dan berlaku biasanya digunakan setelah mengetahui jumlah parameter. Berikut ini adalah contoh:
var obj = function (name) {this.name = name;} obj.prototype.getName = function () {return this.name;} var obj1 = new obj ("zou"); var obj2 = {name: 'andy'}; name = obj1.getName.call (obj2);Rujukannya adalah:
berlaku (objek, arg1, arg2, ...)
Panggilan (objek, [arg1, arg2, ......])
Hanya satu "array" yang dapat diikuti oleh panggilan, termasuk semua parameter. Oleskan adalah gula sintaksis. Jika Anda tahu jumlah parameter, akan sangat nyaman untuk digunakan Apply.
Objek di atas juga bisa nol atau tidak terdefinisi, sehingga objek ini adalah objek global (jendela). Misalnya, contoh di atas akan diikuti:
var name = 'goo'; waspada (obj1.getname.call (null)); (Dalam mode yang ketat, karena objek global adalah nol, pengecualian akan dilemparkan: TipeError yang tidak tertulis: tidak dapat membaca 'nama' properti dari nol)
3. Object.Defineproperty
(Catatan: Jangan gunakan fitur jenis ini di bawah IE8)
Microsoft: Tambahkan properti ke objek, atau modifikasi properti properti yang ada.
getters, setter,
Bahkan, ada juga fungsi getters dan setter untuk properti objek di JS, tetapi saya pribadi berpikir getter dan setter di JS lebih seperti C#.
Misalnya, kode berikut mendefinisikan Getter/Setter:
function myobj () {} object.defineproperty (myobj.prototype, 'length', {get: function () {return this.length_; // ini tidak bisa panjang.}, set: function (value) {return this.length_ = value;}});Tempat yang dikomentari tidak bisa panjang, jika tidak, itu akan menjadi rekursif tanpa batas.
Anda juga dapat menghapus set dan membuat variabel panjang hanya baca.
Object.defineproperty (myobj.prototype, 'length', {get: function () {return this.length_; // ini tidak bisa panjang.}, /*Set: function (value) {return this.length_ = value;}* /}); myobj.length = 3;Kode ini akan melempar pengecualian: TipeError yang Tak Terbang: tidak dapat mengatur panjang properti #<myobj> yang hanya memiliki pengambil.
Untuk membuat properti objek hanya dibaca, Anda juga dapat menggunakan writable: false.
Object.defineproperty (myobj.prototype, 'length', {writable: false});Tulisan: Salah tidak dapat hidup berdampingan dengan set get, jika tidak kesalahan jenis akan dilemparkan.
Dapat dikonfigurasi: Bisakah itu dihapus dengan pernyataan hapus, tetapi properti yang dapat dikonfigurasi tampaknya valid dalam mode ketat. Kode semacam itu masih dapat dieksekusi dalam mode non-ketat: (melaporkan kesalahan dalam mode ketat)
Object.defineproperty (myobj.prototype, 'length', {dapat dikonfigurasi: false}); var obj = myobj baru (); hapus obj.length;Nilai: Menentukan nilai tetap dari objek. Nilai: 10, menunjukkan bahwa nilai awal objek ini adalah 10.
Dalam mode non-ketat, kode semacam itu tidak akan melaporkan kesalahan, dan dalam mode yang ketat, itu akan melaporkan kesalahan:
Object.defineproperty (myobj.prototype, 'length', {writable: false, value: '10 '}); var obj = myobj baru (); obj.length = 100;Anda dapat menggunakan GetOwnPropertyDescriptor untuk mendapatkan dan memodifikasi nilai -nilai ini. Misalnya, sekarang properti panjang saya hanya baca.
Menjalankan kode seperti itu, tetapi terjadi kesalahan:
Object.defineproperty (myobj.prototype, 'length', {value:, writable: false,}); var descriptor = object.getOwnPropertyDescriptor (myobj.prototype, "length"); descriptor.writing = true; object.defineproperty (myobj.protyproty), true; object.defineproperty (myobj.protyproty; TipeError Tanpa Diantak: Tidak Dapat Didefinisikan Motor Properti: PanjangIni karena nilai default yang dapat dikonfigurasi salah. Setelah memanggil DefinEproperty, dapat dikonfigurasi memiliki properti palsu, sehingga tidak dapat dibalik. Itu tidak dapat diubah di masa depan.
Oleh karena itu, Anda harus menggunakan yang dapat dikonfigurasi: Benar, dan properti objek ini dapat dimodifikasi. Kode lengkapnya adalah sebagai berikut:
Object.defineproperty (myobj.prototype, 'length', {value:, writable: false, dapat dikonfigurasi: true}); var descriptor = object.getOwnPropertyDescriptor (myobj.prototype, "length"); descriptor.writable = true; object.defineproperty (myobj.prototype, 'length', descriptor); myobj.prototype.length =; var obj = myobj baru (); peringatan (obj.length);Anda dapat menambahkan deskriptor kalimat. Konfigurasi = false;
Itu berarti bahwa saya telah memodifikasi properti ini, dan Anda tidak dapat memodifikasinya di masa depan
Fitur ini juga berguna dalam banyak kasus. Jika Anda menggunakan metode panggilan dan menerapkan, panjang objek diperlukan untuk menjadi variabel. Jika atribut panjang objek hanya baca, pengecualian akan dilemparkan saat panggilan panggilan dan berlaku.
Misalnya, panjang objek DomTokenList tidak dapat diubah. Saya mendapat Dom Object Domtokenlist,
Tetapi yang dapat dikonfigurasi benar, kami dapat memodifikasinya sehingga properti panjangnya dapat diubah:
Lihat, ini dapat dikonfigurasi benar, dan setter tidak ditentukan. Mari kita tulis metode yang ditetapkan untuk itu, bukankah tidak masalah?
var descriptor = object.getOwnPropertyDescriptor (domtokenlist.prototype, 'length'); descriptor.set = function (value) {this.length = value;} object.defineproperty (domtokenlist.prototype, 'length', descriptor);Lalu jalankan,
Pengecualian lainnya dilemparkan, RangeError yang tidak tertulis: ukuran tumpukan panggilan maksimum terlampaui (...)
Ini karena ketika kita mengatur ini. Panjangnya, itu akan berulang -ulang dalam metode set yang kita tulis.
Oleh karena itu, kita perlu menggunakan hapus untuk menghilangkan pengaruh atribut panjang, yaitu:
var descriptor = object.getOwnPropertyDescriptor (domtokenList.prototype, 'length'); descriptor.set = function (value) {delete domtokenlist.prototype.length; this.length = value;} object.defineproperty (domtokenlist.prototype, 'length', descriptor);Dengan cara ini, DomTokenList juga mendukung operasi Push, Pop dan lainnya.
Array.prototype.push.call (document.body.classlist, 'ABC')
Lalu merangkum
Domtokenlist.prototype.push = function () {array.prototype.push.call (document.body.classlist, array.prototype.slice.call (argumen));}Metode array.prototype.slice.call (argumen) digunakan untuk mengubah objek argumen menjadi array.