javascript
$.ligerdialog.open中确定按钮加事件_彻底搞懂JavaScript中的this指向问题
JavaScript中的this是讓很多開發者頭疼的地方,而this關鍵字又是一個非常重要的語法點。毫不夸張地說,不理解它的含義,大部分開發任務都無法完成。
想要理解this,你可以先記住以下兩點:
1:this永遠指向一個對象;
2:this的指向完全取決于函數調用的位置;
針對以上的第一點特別好理解,不管在什么地方使用this,它必然會指向某個對象;確定了第一點后,也引出了一個問題,就是this使用的地方到底在哪里,而第二點就解釋了這個問題,但關鍵是在JavaScript語言之中,一切皆對象,運行環境也是對象,所以函數都是在某個對象下運行,而this就是函數運行時所在的對象(環境)。這本來并不會讓我們糊涂,但是JavaScript支持運行環境動態切換,也就是說,this的指向是動態的,很難事先確定到底指向哪個對象,這才是最讓我們感到困惑的地方。
先看原理
function fun(){console.log(this.s); } ? var obj = {s:'1',f:fun } ? var s = '2'; ? obj.f(); //1 fun(); //2上述代碼中,fun函數被調用了兩次,顯而易見的是兩次的結果不一樣;
很多人都會這樣解釋,obj.f()的調用中,因為運行環境在obj對象內,因此函數中的this指向對象obj;
而在全局作用域下調用 fun() ,函數中的 this 就會指向全局作用域對象window;
但是大部分人不會告訴你,this的指向為什么會發生改變,this指向的改變到底是什么時候發生的;而搞懂了這些,this的使用才不會出現意外;
首先我們應該知道,在JS中,數組、函數、對象都是引用類型,在參數傳遞時也就是引用傳遞;
上面的代碼中,obj 對象有兩個屬性,但是屬性的值類型是不同的,在內存中的表現形式也是不同的;
調用時就成了這個樣子:
因為函數在js中既可以當做值傳遞和返回,也可當做對象和構造函數,所有函數在運行時需要確定其當前的運行環境,this就出生了,所以,this會根據運行環境的改變而改變,同時,函數中的this也只能在運行時才能最終確定運行環境;
再來看下面的代碼,你可能會更加理解this對于運行環境的動態切換規則:
var A = {name: '張三',f: function () {console.log('姓名:' + this.name);} }; ? var B = {name: '李四' }; ? B.f = A.f; B.f() // 姓名:李四 A.f() // 姓名:張三上面代碼中,A.f屬性被賦給B.f,也就是A對象將匿名函數的 地址 賦值給B對象;
那么在調用時,函數分別根據運行環境的不同,指向對象A和B
function foo() {console.log(this.a); } var obj2 = {a: 2,fn: foo }; var obj1 = {a: 1,o1: obj2 }; obj1.o1.fn(); // 2obj1對象的o1屬性值是obj2對象的地址,而obj2對象的fn屬性的值是函數foo的地址;
函數foo的調用環境是在obj2中的,因此this指向對象obj2;
那么接下來,我們對this使用最頻繁的幾種情況做一個總結,最常見的基本就是以下5種:
對象中的方法,事件綁定 ,構造函數 ,定時器,函數對象的call()、apply() 方法;
上面在講解this原理是,我們使用對象的方法中的this來說明的,在此就不重復講解了,不懂的同學們,請返回去重新閱讀;
事件綁定中的this
事件綁定共有三種方式:行內綁定、動態綁定、事件監聽;
行內綁定的兩種情況:
<input type="button" value="按鈕" onclick="clickFun()"> <script>function clickFun(){this // 此函數的運行環境在全局window對象下,因此this指向window;} </script> ? <input type="button" value="按鈕" onclick="this"> <!-- 運行環境在節點對象中,因此this指向本節點對象 -->行內綁定事件的語法是在html節點內,以節點屬性的方式綁定,屬性名是事件名稱前面加'on',屬性的值則是一段可執行的 JS 代碼段;而屬性值最常見的就是一個函數調用;
當事件觸發時,屬性值就會作為JS代碼被執行,當前運行環境下沒有clickFun函數,因此瀏覽器就需要跳出當前運行環境,在整個環境中尋找一個叫clickFun的函數并執行這個函數,所以函數內部的this就指向了全局對象window;如果不是一個函數調用,直接在當前節點對象環境下使用this,那么顯然this就會指向當前節點對象;
動態綁定與事件監聽:
<input type="button" value="按鈕" id="btn"> <script>var btn = document.getElementById('btn');btn.onclick = function(){this ; // this指向本節點對象} </script>因為動態綁定的事件本就是為節點對象的屬性(事件名稱前面加'on')重新賦值為一個匿名函數,因此函數在執行時就是在節點對象的環境下,this自然就指向了本節點對象;
事件監聽中this指向的原理與動態綁定基本一致,所以不再闡述;
構造函數中的this
function Pro(){this.x = '1';this.y = function(){}; } var p = new Pro();對于接觸過 JS 面向對象編程的同學來說,上面的代碼和圖示基本都能看懂,new 一個構造函數并執行函數內部代碼的過程就是這個五個步驟,當 JS 引擎指向到第3步的時候,會強制的將this指向新創建出來的這個對象;基本不需要理解,因為這本就是 JS 中的語法規則,記住就可以了;
window定時器中的this
var obj = {fun:function(){this ;} } ? setInterval(obj.fun,1000); // this指向window對象 setInterval('obj.fun()',1000); // this指向obj對象setInterval() 是window對象下內置的一個方法,接受兩個參數,第一個參數允許是一個函數或者是一段可執行的 JS 代碼,第二個參數則是執行前面函數或者代碼的時間間隔;
在上面的代碼中,setInterval(obj.fun,1000) 的第一個參數是obj對象的fun ,因為 JS 中函數可以被當做值來做引用傳遞,實際就是將這個函數的地址當做參數傳遞給了 setInterval 方法,換句話說就是 setInterval 的第一參數接受了一個函數,那么此時1000毫秒后,函數的運行就已經是在window對象下了,也就是函數的調用者已經變成了window對象,所以其中的this則指向的全局window對象;
而在 setInterval('obj.fun()',1000) 中的第一個參數,實際則是傳入的一段可執行的 JS 代碼;1000毫秒后當 JS 引擎來執行這段代碼時,則是通過 obj 對象來找到 fun 函數并調用執行,那么函數的運行環境依然在 對象 obj 內,所以函數內部的this也就指向了 obj 對象;
函數對象的call()、apply() 方法
函數作為對象提供了call(),apply() 方法,他們也可以用來調用函數,這兩個方法都接受一個對象作為參數,用來指定本次調用時函數中this的指向;
call()方法
call方法使用的語法規則函數名稱.call(obj,arg1,arg2...argN);
參數說明:
obj:函數內this要指向的對象,
arg1,arg2...argN :參數列表,參數與參數之間使用一個逗號隔開var lisi = {names:'lisi'}; var zs = {names:'zhangsan'}; function f(age){console.log(this.names);console.log(age);} f(23);//undefined ? //將f函數中的this指向固定到對象zs上; f.call(zs,32);//zhangsan
apply()方法
函數名稱.apply(obj,[arg1,arg2...,argN])參數說明:
obj :this要指向的對象
[arg1,arg2...argN] : 參數列表,要求格式為數組var lisi = {name:'lisi'}; var zs = {name:'zhangsan'}; function f(age,sex){console.log(this.name+age+sex); } //將f函數中的this指向固定到對象zs上; f.apply(zs,[23,'nan']);
注意:call和apply的作用一致,區別僅僅在函數實參參數傳遞的方式上;
這個兩個方法的最大作用基本就是用來強制指定函數調用時this的指向;
總結
以上是生活随笔為你收集整理的$.ligerdialog.open中确定按钮加事件_彻底搞懂JavaScript中的this指向问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python计算一元一次方程的根_5-2
- 下一篇: 车仪表台上的装饰_仪表台放这个东西,相当