Kata Pengantar
Ini, pembina dan prototaip dalam JavaScript adalah semua isu biasa, dan adalah penting untuk memahami maksudnya secara mendalam. Di sini, mari kita semak semula, semak masa lalu dan pelajari perkara baharu!
ini
Ini mewakili objek semasa Jika ini digunakan dalam skop global, ia merujuk kepada tetingkap objek halaman semasa jika ini digunakan dalam fungsi, perkara ini merujuk kepada objek yang dipanggil fungsi ini pada masa larian. Kami juga boleh menggunakan dua kaedah global memohon dan memanggil untuk menukar penunjuk khusus ini dalam fungsi.
Mari kita lihat contoh penggunaan ini dalam skop global:
console.log(this === window); // true console.log(window.alert === this.alert); // true console.log(this.parseInt("021", 10)); // 10
Ini dalam fungsi ditentukan pada masa jalan, bukan apabila fungsi ditakrifkan, seperti berikut:
// 定义一个全局函数 function foo() { console.log(this.fruit); } // 定义一个全局变量,等价于window.fruit = "apple"; var fruit = "apple"; // 此时函数foo中this指向window对象 // 这种调用方式和window.foo();是完全等价的 foo(); // "apple" // 自定义一个对象,并将此对象的属性foo指向全局函数foo var pack = { fruit: "orange", foo: foo }; // 此时函数foo中this指向window.pack对象 pack.foo(); // "orange"
Fungsi global digunakan dan panggilan boleh digunakan untuk menukar penunjuk ini dalam fungsi, seperti berikut:
// 定义一个全局函数 function foo() { console.log(this.fruit); } // 定义一个全局变量 var fruit = "apple"; // 自定义一个对象 var pack = { fruit: "orange" }; // 等价于window.foo(); foo.apply(window); // "apple" // 此时foo中的this === pack foo.apply(pack); // "orange"
Nota: Fungsi guna dan panggil mempunyai fungsi yang sama Satu-satunya perbezaan ialah takrifan parameter kedua-dua fungsi adalah berbeza.
Oleh kerana fungsi juga merupakan objek dalam JavaScript, kita dapat melihat contoh menarik berikut:
// 定义一个全局函数 function foo() { if (this === window) { console.log("this is window."); } } // 函数foo也是对象,所以可以定义foo的属性boo为一个函数 foo.boo = function() { if (this === foo) { console.log("this is foo."); } else if (this === window) { console.log("this is window."); } }; // 等价于window.foo(); foo(); // this is window. // 可以看到函数中this的指向调用函数的对象 foo.boo(); // this is foo. // 使用apply改变函数中this的指向 foo.boo.apply(window); // this is window.
prototaip
Prototaip pada asasnya ialah objek JavaScript.
Dan setiap fungsi mempunyai atribut prototaip lalai. Jika fungsi ini digunakan dalam konteks mencipta objek tersuai, kami memanggil fungsi ini sebagai pembina. Contohnya, adegan mudah berikut:
// 构造函数 function Person(name) { this.name = name; } // 定义Person的原型,原型中的属性可以被自定义对象引用 Person.prototype = { getName: function() { return this.name; } } var hao= new Person("haorooms"); console.log(hao.getName()); // "haorooms"
Sebagai analogi, mari pertimbangkan jenis data dalam JavaScript - Rentetan, Nombor, Tatasusunan, Objek, Tarikh, dsb.
Kami mempunyai sebab untuk mempercayai bahawa jenis ini dilaksanakan sebagai pembina dalam JavaScript, seperti:
// 定义数组的构造函数,作为JavaScript的一种预定义类型 function Array() { // ... } // 初始化数组的实例 var arr1 = new Array(1, 56, 34, 12); // 但是,我们更倾向于如下的语法定义: var arr2 = [1, 56, 34, 12];
Pada masa yang sama, banyak kaedah pengendalian pada tatasusunan (seperti concat, join, push) juga harus ditakrifkan dalam atribut prototaip. Sebenarnya, semua jenis data intrinsik JavaScript mempunyai atribut prototaip baca sahaja (ini boleh difahami: jika anda mengubah suai atribut prototaip jenis ini, kaedah yang dipratentukan hilang), tetapi kami boleh menambahnya kaedah sambungan sendiri.
// 向JavaScript固有类型Array扩展一个获取最小值的方法 Array.prototype.min = function() { var min = this[0]; for (var i = 1; i < this.length; i++) { if (this[i] < min) { min = this[i]; } } return min; }; // 在任意Array的实例上调用min方法 console.log([1, 56, 34, 12].min()); // 1
Nota: Terdapat perangkap di sini Selepas menambah kaedah sambungan pada prototaip Array, kaedah sambungan ini juga akan digelung keluar apabila menggunakan for-in untuk menggelung tatasusunan. Kod berikut menggambarkan ini (dengan mengandaikan bahawa kaedah min telah dilanjutkan kepada prototaip Array):
var arr = [1, 56, 34, 12]; var total = 0; for (var i in arr) { total += parseInt(arr[i], 10); } console.log(total); // NaN
Penyelesaian juga sangat mudah:
var arr = [1, 56, 34, 12]; var total = 0; for (var i in arr) { if (arr.hasOwnProperty(i)) { total += parseInt(arr[i], 10); } } console.log(total); // 103
pembina
pembina sentiasa menunjuk kepada pembina yang mencipta objek semasa. Contohnya, contoh berikut:
// 等价于 var foo = new Array(1, 56, 34, 12); var arr = [1, 56, 34, 12]; console.log(arr.constructor === Array); // true // 等价于 var foo = new Function(); var Foo = function() { }; console.log(Foo.constructor === Function); // true // 由构造函数实例化一个obj对象 var obj = new Foo(); console.log(obj.constructor === Foo); // true // 将上面两段代码合起来,就得到下面的结论 console.log(obj.constructor.constructor === Function); // true
Tetapi apabila pembina menemui prototaip, sesuatu yang menarik berlaku. Kita tahu bahawa setiap fungsi mempunyai prototaip atribut lalai, dan pembina prototaip ini menunjukkan fungsi ini secara lalai. Seperti yang ditunjukkan dalam contoh berikut:
function Person(name) { this.name = name; }; Person.prototype.getName = function() { return this.name; }; var p = new Person("haorooms"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true // 将上两行代码合并就得到如下结果 console.log(p.constructor.prototype.constructor === Person); // true
Apabila kami mentakrifkan semula prototaip fungsi (nota: perbezaan daripada contoh di atas, ini bukan pengubahsuaian tetapi menimpa), tingkah laku pembina agak pelik, seperti yang ditunjukkan dalam contoh berikut:
function Person(name) { this.name = name; }; Person.prototype = { getName: function() { return this.name; } }; var p = new Person("haorooms"); console.log(p.constructor === Person); // false console.log(Person.prototype.constructor === Person); // false console.log(p.constructor.prototype.constructor === Person); // false
Kenapa? Ternyata apabila mengatasi Person.prototype, ia adalah setara dengan melaksanakan operasi kod berikut:
Person.prototype = new Object({ getName: function() { return this.name; } });
Pembina sentiasa menunjuk kepada pembina yang mencipta dirinya, jadi pada masa ini Person.prototype.constructor === Objek, iaitu:
function Person(name) { this.name = name; }; Person.prototype = { getName: function() { return this.name; } }; var p = new Person("haorooms"); console.log(p.constructor === Object); // true console.log(Person.prototype.constructor === Object); // true console.log(p.constructor.prototype.constructor === Object); // true
Bagaimana untuk menyelesaikan masalah ini? Kaedah ini juga sangat mudah, cuma ganti Person.prototype.constructor:
function Person(name) { this.name = name; }; Person.prototype = { getName: function() { return this.name; } }; Person.prototype.constructor = Person; var p = new Person("haorooms"); console.log(p.constructor === Person); // true console.log(Person.prototype.constructor === Person); // true console.log(p.constructor.prototype.constructor === Person); // true
juga boleh ditulis seperti ini:
function Person(name) { this.name = name; }; Person.prototype = { constructor:Person,//指定constructor getName: function() { return this.name; } };
Analisis komprehensif di atas mengenai klise js ini, pembina dan prototaip adalah semua kandungan yang dikongsi oleh editor, saya harap ia dapat memberi rujukan kepada anda, dan saya juga berharap semua orang akan menyokong Script Home.