Artikel ini hanya membincangkan isu ini Selepas membaca artikel ini, jika pembaca dapat menjawab soalan Apa ini dalam JavaScript dengan betul, sebagai pengarang, saya akan merasakan bahawa ia berbaloi untuk menghabiskan banyak usaha untuk menulis artikel sedemikian.
Kita perlu ingat satu ayat: ini sentiasa menunjuk ke objek di mana fungsi sedang berjalan! bukannya objek di mana fungsi itu dicipta. Iaitu: sesiapa yang memanggil menunjuk kepada siapa. Ingat…
Artikel ini akan menganalisis di mana objek ini berada dalam tiga situasi.
1. ini
dalam fungsi biasa
Tidak kira di mana ini, keutamaan pertama adalah untuk mencari lokasi apabila fungsi sedang berjalan.
var name="全局"; function getName(){ var name="局部"; return this.name; }; alert(getName());
Apabila ini muncul dalam fungsi getName persekitaran global, lokasi masa jalan bagi fungsi getName ialah
alert(getName());
Jelas sekali, objek di mana fungsi getName terletak ialah objek global, iaitu tetingkap, jadi rumah ini mesti berada dalam tetingkap. Pada masa ini, ini menunjuk ke objek tetingkap, jadi this.name yang dikembalikan oleh getName sebenarnya ialah window.name, jadi amaran keluar sebagai "global"!
Jadi, apabila ini tidak muncul dalam fungsi persekitaran global, tetapi muncul dalam fungsi persekitaran tempatan, di manakah ia akan jatuh?
var name="全局"; var xpg={ name:"局部", getName:function(){ return this.name; } }; alert(xpg.getName());
Fungsi getName di mana ini terletak bukan dalam persekitaran global, tetapi dalam persekitaran xpg. Tidak kira di mana ini, anda mesti mencari lokasi apabila fungsi sedang berjalan. Kedudukan fungsi getName semasa ia berjalan pada masa ini
alert(xpg.getName());
Jelas sekali, objek di mana fungsi getName terletak ialah xpg, jadi rumah ini mestilah dalam xpg, iaitu, ia menunjuk ke objek xpg Kemudian this.name yang dikembalikan oleh getName sebenarnya adalah xpg.name, jadi amaran keluar sebagai "separa"!
Berikan contoh untuk disatukan:
var someone = { name: "Bob", showName: function(){ alert(this.name); } }; var other = { name: "Tom", showName: someone.showName } other.showName(); //Tom
Walaupun kata kunci ini diisytiharkan dalam seseorang.showName, ia adalah lain.showName apabila dijalankan, jadi ini menunjuk ke objek semasa fungsi lain.showName, yang lain, jadi makluman terakhir ialah other.name.
2 ini sebagai penutup
Penutupan juga merupakan pengacau Artikel ini tidak akan menerangkan secara terperinci mengenainya buat sementara waktu: yang dipanggil penutupan adalah untuk mencipta fungsi lain di dalam fungsi dan fungsi dalaman mengakses pembolehubah luaran.
Anak yang hilang bercampur dengan penutupan bajingan, yang menunjukkan bahawa tidak akan pernah ada kedamaian!
var name="全局"; var xpg={ name:"局部", getName:function(){ return function(){ return this.name; }; } }; alert(xpg.getName()());
Pada masa ini, ini jelas dalam masalah Ia sebenarnya dalam fungsi tanpa nama dalam fungsi getName, dan fungsi tanpa nama memanggil nama pembolehubah, dengan itu membentuk penutupan, iaitu, ini dalam penutupan.
Tidak kira di mana ini, anda mesti mencari lokasi apabila fungsi sedang berjalan. Pada masa ini, ia tidak boleh dinilai berdasarkan kedudukan masa jalan fungsi getName, tetapi berdasarkan kedudukan masa jalan fungsi tanpa nama.
function (){ return this.name; };
Jelas sekali, objek di mana fungsi tanpa nama terletak ialah tetingkap, jadi rumah ini mesti berada dalam tetingkap, maka this.name yang dikembalikan oleh fungsi tanpa nama sebenarnya ialah window.name, jadi apa yang keluar dari makluman ialah "global"!
Jadi, bagaimana untuk membuat ini dalam xpg dalam penutupan? —Cache ini
var name="全局"; var xpg={ name:"局部", getName:function(){ var that=this; return function(){ return that.name; }; } }; alert(xpg.getName()());
Tentukan bahawa=ini dalam fungsi getName Pada masa ini, fungsi getName sedang berjalan di
alert(xpg.getName());
Kemudian ini menunjuk ke objek xpg, jadi itu juga menunjuk ke objek xpg. Jika that.name dikembalikan dalam fungsi tanpa nama bagi penutupan, that.name yang dikembalikan pada masa ini sebenarnya adalah xpg.name, jadi "tempatan" boleh dimaklumkan!
3. Kata kunci baharu mencipta objek baharu
Ini dalam pembina selepas kata kunci baharu menunjuk ke objek baharu yang dibina dengan pembina:
function Person(__name){ this.name = __name; //这个this指向用该构造函数构造的新对象,这个例子是Bob对象 } Person.prototype.show = function(){ alert(this.name); //this 指向Person,this.name = Person.name; } var Bob = new Person("Bob"); Bob.show(); //Bob
4 ini dalam panggilan dan mohon
Satu-satunya yang boleh mengurus ini dalam JavaScript ialah memanggil dan memohon.
panggilan dan memohon adalah seperti ibu bapa ini, mereka akan tinggal di mana sahaja mereka membiarkan ini hidup, dan mereka perlu patuh! Apabila tiada parameter, objek semasa ialah tetingkap
var name="全局"; var xpg={ name:"局部" }; function getName(){ alert(this.name); } getName(xpg); getName.call(xpg); getName.call();
Di mana ini terdapat dalam fungsi getName. Tidak kira di mana ini, anda mesti mencari lokasi apabila fungsi sedang berjalan. Kedudukan fungsi getName semasa ia berjalan pada masa ini
getName(xpg);
Jelas sekali, objek di mana fungsi getName terletak ialah tetingkap, jadi rumah ini mesti berada dalam tetingkap, iaitu, menunjuk ke objek tetingkap Kemudian this.name yang dikembalikan oleh getName sebenarnya window.name, jadi amaran itu keluar sebagai "global"!
Kemudian, sudah tiba masanya untuk menelefon dan memohon, kerana ini mesti mendengar arahan mereka!
getName.call(xpg);
Antaranya, panggilan menentukan bahawa rumah ini adalah objek xpg, kerana ini dipaksa untuk menyelesaikan hanya dalam xpg, maka ini menunjukkan kepada objek xpg pada masa ini, this.name sebenarnya xpg.name, jadi amaran keluar. sebagai "tempatan"!
5 ini dalam eval
Untuk fungsi eval, nampaknya objek semasa tidak ditentukan apabila ia dilaksanakan, tetapi sebenarnya ini tidak menunjuk ke tetingkap, kerana skop apabila fungsi itu dilaksanakan adalah skop semasa, yang bersamaan untuk mengisi kod di dalam baris itu. Contoh berikut menggambarkan masalah ini:
var name = "window"; var Bob = { name: "Bob", showName: function(){ eval("alert(this.name)"); } }; Bob.showName(); //Bob
6、没有明确的当前对象时的this
当没有明确的执行时的当前对象时,this指向全局对象window。
例如对于全局变量引用的函数上我们有:
var name = "Tom"; var Bob = { name: "Bob", show: function(){ alert(this.name); } } var show = Bob.show; show(); //Tom
你可能也能理解成show是window对象下的方法,所以执行时的当前对象时window。但局部变量引用的函数上,却无法这么解释:
var name = "window"; var Bob = { name: "Bob", showName: function(){ alert(this.name); } }; var Tom = { name: "Tom", showName: function(){ var fun = Bob.showName; fun(); } }; Tom.showName(); //window
在浏览器中setTimeout、setInterval和匿名函数执行时的当前对象是全局对象window,这条我们可以看成是上一条的一个特殊情况。
var name = "Bob"; var nameObj ={ name : "Tom", showName : function(){ alert(this.name); }, waitShowName : function(){ setTimeout(this.showName, 1000); } }; nameObj.waitShowName();
所以在运行this.showName的时候,this指向了window,所以最后显示了window.name。
7、dom事件中的this
(1)你可以直接在dom元素中使用
<input id="btnTest" type="button" value="提交" onclick="alert(this.value))" />
分析:对于dom元素的一个onclick(或其他如onblur等)属性,它为所属的html元素所拥有,直接在它触发的函数里写this,this应该指向该html元素。
(2)给dom元素注册js函数
a、不正确的方式
<script type="text/javascript"> function thisTest(){ alert(this.value); // 弹出undefined, this在这里指向?? } </script> <input id="btnTest" type="button" value="提交" onclick="thisTest()" />
分析:onclick事件直接调用thisTest函数,程序就会弹出undefined。因为thisTest函数是在window对象中定义的,
所以thisTest的拥有者(作用域)是window,thisTest的this也是window。而window是没有value属性的,所以就报错了。
b、正确的方式
<input id="btnTest" type="button" value="提交" /> <script type="text/javascript"> function thisTest(){ alert(this.value); } document.getElementById("btnTest").onclick=thisTest; //给button的onclick事件注册一个函数 </script>
分析:在前面的示例中,thisTest函数定义在全局作用域(这里就是window对象),所以this指代的是当前的window对象。而通过document.getElementById(“btnTest”).onclick=thisTest;这样的形式,其实是将btnTest的onclick属性设置为thisTest函数的一个副本,在btnTest的onclick属性的函数作用域内,this归btnTest所有,this也就指向了btnTest。其实如果有多个dom元素要注册该事件,我们可以利用不同的dom元素id,用下面的方式实现:
document.getElementById("domID").onclick=thisTest; //给button的onclick事件注册一个函数。
因为多个不同的HTML元素虽然创建了不同的函数副本,但每个副本的拥有者都是相对应的HTML元素,各自的this也都指向它们的拥有者,不会造成混乱。
为了验证上述说法,我们改进一下代码,让button直接弹出它们对应的触发函数:
<input id="btnTest1" type="button" value="提交1" onclick="thisTest()" /> <input id="btnTest2" type="button" value="提交2" /> <script type="text/javascript"> function thisTest(){ this.value="提交中"; } var btn=document.getElementById("btnTest1"); alert(btn.onclick); //第一个按钮函数 var btnOther=document.getElementById("btnTest2"); btnOther.onclick=thisTest; alert(btnOther.onclick); //第二个按钮函数 </script> 其弹出的结果是: //第一个按钮 function onclick(){ thisTest() } //第二个按钮 function thisTest(){ this.value="提交中"; }
从上面的结果你一定理解的更透彻了。
By the way,每新建一个函数的副本,程序就会为这个函数副本分配一定的内存。而实际应用中,大多数函数并不一定会被调用,于是这部分内存就被白白浪费了。所以我们通常都这么写:
<input id="btnTest1" type="button" value="提交1" onclick="thisTest(this)" /> <input id="btnTest2" type="button" value="提交2" onclick="thisTest(this)" /> <input id="btnTest3" type="button" value="提交3" onclick="thisTest(this)" /> <input id="btnTest4" type="button" value="提交4" onclick="thisTest(this)" /> <script type="text/javascript"> function thisTest(obj){ alert(obj.value); } </script>
这是因为我们使用了函数引用的方式,程序就只会给函数的本体分配内存,而引用只分配指针。这样写一个函数,调用的地方给它分配一个(指针)引用,这样效率就高很多。当然,如果你觉得这样注册事件不能兼容多种浏览器,可以写下面的注册事件的通用脚本:
//js事件 添加 EventUtil.addEvent(dom元素,事件名称,事件触发的函数名) 移除EventUtil.removeEvent(dom元素,事件名称,事件触发的函数名) var EventUtil = new eventManager(); //js事件通用管理器 dom元素 添加或者移除事件 function eventManager() { //添加事件 //oDomElement:dom元素,如按钮,文本,document等; ****** oEventType:事件名称(如:click,如果是ie浏览器,自动将click转换为onclick);****** oFunc:事件触发的函数名 this.addEvent = function(oDomElement, oEventType, oFunc) { //ie if (oDomElement.attachEvent) { oDomElement.attachEvent("on" + oEventType, oFunc); } //ff,opera,safari等 else if (oDomElement.addEventListener) { oDomElement.addEventListener(oEventType, oFunc, false); } //其他 else { oDomElement["on" + oEventType] = oFunc; } } this.removeEvent = function(oDomElement, oEventType, oFunc) { //ie if (oDomElement.detachEvent) { oDomElement.detachEvent("on" + oEventType, oFunc); } //ff,opera,safari等 else if (oDomElement.removeEventListener) { oDomElement.removeEventListener(oEventType, oFunc, false); } //其他 else { oDomElement["on" + oEventType] = null; } } }
正像注释写的那样,要注册dom元素事件,用EventUtil.addEvent(dom元素,事件名称,事件触发的函数名)即可, 移除时可以这样写:EventUtil.removeEvent(dom元素,事件名称,事件触发的函数名),这是题外话,不说了。
以上就是本文的全部内容,希望通过这篇文章大家更加了解javascript的this关键字,大家共同进步。