Javascript中this關(guān)鍵字指向問(wèn)題的測(cè)試與詳解
前言
Javascript是一門基于對(duì)象的動(dòng)態(tài)語(yǔ)言,也就是說(shuō),所有東西都是對(duì)象,一個(gè)很典型的例子就是函數(shù)也被視為普通的對(duì)象。Javascript可以通過(guò)一定的設(shè)計(jì)模式來(lái)實(shí)現(xiàn)面向?qū)ο蟮木幊?,其中this “指針”就是實(shí)現(xiàn)面向?qū)ο蟮囊粋€(gè)很重要的特性。本文將給大家詳細(xì)介紹關(guān)于Javascript中this關(guān)鍵字指向的相關(guān)內(nèi)容,讓我們先做一個(gè)小測(cè)試,如果全部答對(duì)了,恭喜你不用往下看了。
測(cè)試題目
第一題
<script> var str = 'zhangsan'; function demo() { var str = 'lisi'; alert(this.str); } window.demo(); // ?? var obj = { str: "wangwu", say: function() { alert(this.str); } } obj.say(); // ?? var fun = obj.say; window.fun(); // ?? </script>
第二題
<script> var username = 'zhangsan'; (function() { var username = 'lisi'; alert(this.username); // ?? })() function demo() { var username = 'wangwu'; function test() { alert(this.username); } test(); // ?? } demo(); </script>
第三題
<script> function Person() { this.username = 'zhangsan'; this.say = function() { alert('我叫' + this.username); } } var p = new Person(); p.say(); // ?? var p1 = new Person(); p1.say(); // ?? </script>
第四題
<script> var username = 'zhangsan'; function demo() { alert(this.username) } var obj1 = { username: "lisi" }; var obj2 = { username: "wangwu" }; demo(); // ?? demo(obj1); // ?? demo(obj2); // ?? demo.call(obj1); // ?? demo.apply(obj2); // ?? </script>
答案
- 第一題:zhangsan wangwu zhangsan
- 第二題:zhangsan zhangsan
- 第三題:我叫zhangsan 我叫zhangsan
- 第四題:zhangsan zhangsan zhangsan lisi wangwu
(往下看,下面有詳細(xì)解析哦)
this
- 指向調(diào)用函數(shù)的對(duì)象
- 無(wú)對(duì)象調(diào)用函數(shù)/匿名函數(shù)自調(diào)用(this指向window)
- 通過(guò)new產(chǎn)生的對(duì)象
- apply/call調(diào)用
一、指向調(diào)用函數(shù)的對(duì)象
<script> // this:指向調(diào)用函數(shù)的對(duì)象 var str = 'zhangsan'; function demo() { var str = 'lisi'; //this->window console.log(this); alert(this.str); } window.demo(); // zhangsan var obj = { str: "wangwu", say: function() { // this->obj alert(this.str); } } obj.say(); // wangwu var fun = obj.say; window.fun(); // zhangsan </script>
- 全局函數(shù)(demo)屬于window對(duì)象的方法,window調(diào)用demo所以this就指向了window
- obj調(diào)用say方法,this就指向了obj
- fun()是全局函數(shù),而聲明的fun接收的是obj里面單純的一個(gè)函數(shù),并沒(méi)有調(diào)用(obj.say()才是調(diào)用了函數(shù)),此時(shí)的fun就是一個(gè)函數(shù)(function(){alert(this.str);}),那么當(dāng)fun()調(diào)用函數(shù)的時(shí)候,this指向的就是window
- 是誰(shuí)調(diào)用的函數(shù),那么this就指向誰(shuí)
二、無(wú)對(duì)象調(diào)用函數(shù)/匿名函數(shù)自調(diào)用->this指向window
<script> // 2.匿名函數(shù)自執(zhí)行|匿名函數(shù)|無(wú)主函數(shù) this->window var username = 'zhangsan'; // 匿名函數(shù)自執(zhí)行 this->window (function() { var username = 'lisi'; console.log(this); // window alert(this.username); // zhangsan })() function demo() { var username = 'wangwu'; // 無(wú)主函數(shù) this->window function test() { // this->window alert(this.username); } test(); // zhangsan } demo(); </script>
- 因?yàn)槟涿瘮?shù)沒(méi)有名字,所以就掛給window了
- test(),誰(shuí)調(diào)用test那么就指向誰(shuí)。當(dāng)然實(shí)驗(yàn)過(guò),它不是window調(diào)用的,也不是demo調(diào)用的,沒(méi)有人管它,那么它就指向window。它就相當(dāng)于一個(gè)沒(méi)有主人調(diào)用它,無(wú)主函數(shù)。
三、通過(guò)new產(chǎn)生的對(duì)象
<script> // 3.通過(guò)new的對(duì)象:this指向產(chǎn)生的對(duì)象 // 函數(shù) function Person() { // 屬性 this.username = 'zhangsan'; // 方法 this.say = function() { // this->p console.log(this); // Person對(duì)象 alert('我叫' + this.username); } } // 實(shí)例化出一個(gè)對(duì)象:p就具有了username屬性和say方法 var p = new Person(); console.log(p); // Person對(duì)象 console.log(p.username); // zhangsan p.say(); // 我叫zhangsan // this->p1 var p1 = new Person(); p1.say(); // Person對(duì)象 我叫zhangsan </script>
- 當(dāng)我們的函數(shù)Person里面運(yùn)用了this去寫屬性和方法這種格式,那么就要通過(guò)new來(lái)讓屬性和方法變得有價(jià)值,通過(guò)new去運(yùn)用函數(shù)里面的屬性和方法
四、apply/call調(diào)用
首先我們來(lái)了解下apply()/call()是個(gè)什么東西呢?
apply()/call():最終是調(diào)用function,只不過(guò)內(nèi)部的this指向了thisObj
function.call([thisObj[,arg1[, arg2[, [,.argN]]]]]) function.apply([thisObj[,argArray]])
注意:
1. 調(diào)用function函數(shù),但是函數(shù)內(nèi)的this指向thisObj(更改對(duì)象內(nèi)部指針)
2. 如果thisObj沒(méi)有傳參,則默認(rèn)為全局對(duì)象
3. call()/apply()聯(lián)系與區(qū)別
聯(lián)系:功能一樣,第一個(gè)參數(shù)都是thisObj
區(qū)別:傳遞的參數(shù)如果比較多
call()的實(shí)參就是一一列出
apply()的實(shí)參是全部放置在第二個(gè)數(shù)組參數(shù)中
一個(gè)理解apply()/call()的實(shí)例:
<script> // apply()/call() function demo() { console.log(123); } // 調(diào)用函數(shù)的時(shí)候,demo.call()/demo.apply()最終調(diào)用的還是demo() demo(); // 123 demo.call(); //123 demo.apply(); // 123 </script> <script> // call()/apply()的區(qū)別: // call()參數(shù)單獨(dú)再call中羅列 // apply()的參數(shù)通過(guò)數(shù)組表示 function demo(m, n, a, b) { alert(m + n + a + b); } demo(1, 5, 3, 4); // 13 demo.call(null, 1, 5, 3, 4); // 13 demo.apply(null, [1, 5, 3, 4]); // 13 </script>
this的第四個(gè)用法實(shí)例
<script> // this的第四個(gè)用法:call(obj)/apply(obj):強(qiáng)制性的將this指向了obj var username = 'zhangsan'; function demo() { alert(this.username) } var obj1 = { username: "lisi" }; var obj2 = { username: "wangwu" }; // call()/apply():打劫式的改變了this的指向 demo(); // zhangsan demo(obj1); //zhangsan demo(obj2); //zhangsan demo.call(obj1); // lisi demo.apply(obj2); // wangwu </script>
- 如果直接調(diào)用demo里面寫的不管是obj1還是obj2,那么demo還是屬于window調(diào)用的。
- 不管你用call還是apply最終調(diào)用的都是demo函數(shù),但它們會(huì)強(qiáng)制的this指向了obj1/obj2,強(qiáng)制的指向了它們的第一個(gè)參數(shù)對(duì)象。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
JavaScript實(shí)現(xiàn)頁(yè)面截圖3種解決方案
網(wǎng)頁(yè)截圖是指將網(wǎng)頁(yè)上的內(nèi)容截取下來(lái),并保存為圖片的過(guò)程,下面這篇文章主要給大家介紹了關(guān)于JavaScript實(shí)現(xiàn)頁(yè)面截圖的3種解決方案,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-06-06JS如何通過(guò)FileReader獲取.txt文件內(nèi)容
今天小編就為大家分享一篇JS如何通過(guò)FileReader獲取.txt文件內(nèi)容,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12ES6中的class是如何實(shí)現(xiàn)的(附Babel編譯的ES5代碼詳解)
這篇文章主要介紹了ES6中的class是如何實(shí)現(xiàn)的?(附Babel編譯的ES5代碼詳解),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05JavaScript Tips 使用DocumentFragment加快DOM渲染速度
大家在開(kāi)發(fā)JavaScript應(yīng)用的時(shí)候,如果遇到這種大量節(jié)點(diǎn)的情況,不妨將DocumentFragment作為一個(gè)備選的方案。2010-06-06JavaScript中eval和with語(yǔ)句如何影響作用域鏈的深度探索
這篇文章主要為大家介紹了JavaScript中eval和with語(yǔ)句如何影響作用域鏈的深度探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05JS Pro-深入面向?qū)ο蟮某绦蛟O(shè)計(jì)之繼承的詳解
一般的面向?qū)ο蟪绦蛘Z(yǔ)言,有兩種繼承方法——接口繼承(interface inheritance)和實(shí)現(xiàn)繼承(implementation inheritance)。接口繼承只繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。在JavaScript中,函數(shù)沒(méi)有簽名,所以在JavaScript只支持實(shí)現(xiàn)繼承,而且主要是依靠原型鏈(prototype chaining)來(lái)是實(shí)現(xiàn)的2013-05-05