1. Panggilan fungsi
Fungsi sememangnya perkara yang paling penting dalam JavaScript. Dalam JavaScript, Function menganggap fungsi prosedur, kaedah, pembina dan juga kelas dan modul.
Dalam pengaturcaraan berorientasikan objek, fungsi, kaedah dan pembina kelas selalunya tiga perkara berbeza, dilaksanakan oleh sintaks yang berbeza. Tetapi dalam JavaScript, ketiga-tiga konsep ini dilaksanakan oleh fungsi, melalui tiga mod yang berbeza.
Mod penggunaan paling mudah ialah panggilan fungsi:
function hello(username) { return "hello, " + username; } hello("Keyser Söze"); // "hello, Keyser Söze"
2. Kaedah memanggil
Konsep kaedah dalam JavaScript ialah atribut objek ialah fungsi: ia adalah fungsi yang sama, tetapi ia berbeza selepas memberikannya kepada ahli objek. Selepas memberikan fungsi kepada ahli objek, ia tidak lagi dipanggil fungsi, tetapi kaedah.
var obj = { hello: function() { return "hello, " + this.username; }, username: "Hans Gruber" }; obj.hello(); // "hello, Hans Gruber"
Tingkah laku sebenar ialah panggilan itu sendiri menentukan objek mana yang akan diikat, iaitu:
obj1.hello() akan mengikat ini kepada obj1, dan obj2.hello() akan mengikat ini kepada obj2. Ingat satu ayat, siapa yang call, ini akan tunjuk kepada siapa
Disebabkan peraturan mengikat ini, penggunaan berikut juga boleh dilaksanakan:
function hello() { return "hello, " + this.username; } var obj1 = { hello: hello, username: "Gordon Gekko" }; obj1.hello(); // "hello, Gordon Gekko" var obj2 = { hello: hello, username: "Biff Tannen" };_ obj2.hello(); // "hello, Biff Tannen"
Namun, dalam fungsi biasa, seperti fungsi helo di atas, menggunakan kata kunci ini bukanlah cara yang baik Apabila ia dipanggil secara langsung, penunjuk ini menjadi masalah. Dalam kes ini, ini sering ditujukan kepada objek global (GlobalObject), yang biasanya merupakan objek tetingkap pada pelayar.
Dan tingkah laku ini tidak pasti dan tidak bermakna.
Jadi dalam standard ES5, jika mod ketat digunakan, ini akan ditetapkan kepada tidak ditentukan:
function hello() { "use strict"; return "hello, " + this.username; } hello(); // error: cannot read property "username" of undefined
Pendekatan di atas adalah untuk mendedahkan kemungkinan ralat dengan lebih cepat dan mengelakkan salah operasi dan pepijat yang sukar ditemui.
Perbezaan antara panggilan fungsi biasa dan panggilan kaedah akan jelas dengan melihat contoh ini.
var func = function() { alert(this); }; var o = {}; o.fn = func; // 比较 alert(o.fn === func);//true // 调用 func();//[object Window] o.fn();//[object Object]
Hasil larian di sini ialah kedua-dua fungsi adalah sama, jadi hasil cetakan adalah benar. Walau bagaimanapun, oleh kerana panggilan kedua-dua fungsi adalah berbeza, panggilan func mencetak [Tetingkap objek], manakala hasil cetakan o.fn ialah [objek Objek].
Berikut ialah perbezaan antara panggilan fungsi dan panggilan kaedah Dalam panggilan fungsi, ini merujuk secara khusus kepada tetingkap objek global, manakala dalam kaedah ini merujuk secara khusus kepada objek semasa, iaitu, ini dalam o.fn merujuk kepada objek. o.
3. Memanggil pembina
Mod penggunaan fungsi ketiga ialah menggunakannya sebagai pembina:
ini
dalam pembinaKita perlu menganalisis proses mencipta objek untuk mengetahui maksud ini seperti yang ditunjukkan dalam kod berikut:
var Person = function() { this.name = "小平果"; }; var p = new Person();
Fungsi Orang pertama kali ditakrifkan di sini. Mari analisa keseluruhan pelaksanaan:
Selepas menganalisis pelaksanaan pembina, kita boleh mendapatkan bahawa ini dalam pembina ialah objek semasa.
pulangan dalam pembina
Maksud pengembalian dalam pembina telah berubah Pertama, jika dalam pembina, jika objek dikembalikan, maka makna asal dikekalkan Jika pemulangan bukan objek, seperti nombor, Boolean, dan rentetan, maka pulangannya adalah ini, jika tiada pernyataan pulangan, maka ini juga dikembalikan Lihat kod berikut:
// 返回一个对象的 return var ctr = function() { this.name = "赵晓虎"; return { name:"牛亮亮" }; }; // 创建对象 var p = new ctr(); // 访问name属性 alert(p.name); //执行代码,这里打印的结果是"牛亮亮". 因为构造方法中返回的是一个对象,那么保留return的意义,返回内容为return后面的对象. 再看下面代码: // 定义返回非对象数据的构造器 var ctr = function() { this.name = "赵晓虎"; return "牛亮亮"; }; // 创建对象 var p = new ctr(); // 使用 alert(p); alert(p.name);
Hasil menjalankan kod ialah tetingkap timbul mula-mula mencetak [objek Objek], dan kemudian mencetak "Zhao Xiaohu" Kerana pemulangan di sini ialah rentetan, yang tergolong dalam jenis asas, kemudian penyataan pulangan di sini adalah tidak sah dan objek ini dikembalikan. Oleh itu, yang pertama mencetak [objek Objek] tetapi yang kedua tidak mencetak tanpa definisi.
function User(name, passwordHash) { this.name = name; this.passwordHash = passwordHash; } var u = new User("sfalken", "0ef33ae791068ec64b502d6cb0191387"); u.name; // "sfalken"
Gunakan kekunci baharu untuk memanggil fungsi sebagai pembina. Tidak seperti panggilan fungsi dan kaedah, pembina akan memasukkan objek baru dan mengikatnya dengan ini, dan kemudian mengembalikan objek sebagai nilai pulangan pembina. Fungsi fungsi pembina itu sendiri adalah untuk memulakan objek.
Kesilapan biasa dalam panggilan pembina
Saya dengan senang hati mentakrifkan pembina berikut:
var Coder = function( nick ){ this.nick = nick; };
Apa yang berlaku selepas menentukan pembina? Betul, buat seketika:
var coder = Coder( 'casper' );
Siapa nama abang coder ni? Cetaknya dengan cepat:
console.log( coder.nick ); //undefined = =b 竟然是undefined!!再回过头看看实例化的那个语句,不难发现问题出在哪里:少了个new var coder = Coder( 'casper' ); //当作普通的函数来调用,故内部的this指针其实指向window对象 console.log( window.nick); //输出:casper var coder = new Coder( 'casper' ); //加上new,一切皆不同,this正确地指向了当前创建的实例 console.log( coder.nick ); //输出:casper
这样的错误貌似挺低级的,但出现的概率挺高的,肿么去避免或减少这种情况的发生呢?
可以在内部实现里面动下手脚:
var Coder = function( nick ){ if( !(this instanceof Coder) ){ return new Coder( nick ); } this.nick = nick; };
其实很简单,实例化的时候,内部判断下,当前this指向的对象的类型即可,如果非当前构造函数的类型,强制重新调用一遍构造函数。
突然觉得Coder这名字不够洋气?想用Hacker,好吧,我改。。。数了下,一共有三处要改,这不科学,有没有办法只把构造函数的名字改了就行?
当然有:
var Coder = function( nick ){ if( !(this instanceof arguments.callee) ){ return new arguments.callee( nick ); } this.nick = nick; };
tips:据说在ES 5的严格模式下面arguments.callee会被禁用,不过仅当ES 5普及同时你指定了要使用严格模式,否则还是可以用的发散下思维。
以上就是本文的全部内容,希望对大家学习函数调用、方法调用和构造函数调用有所帮助。