摘要:是什么這個(gè)單詞是一個(gè)代詞,所以應(yīng)該是指代某些東西搞清楚的關(guān)鍵之處,就是要搞清楚指代了什么那么到底指代了什么呢就像你平時(shí)指著一個(gè)蘋果說指著一個(gè)香蕉說同樣,也會(huì)因?yàn)榍闆r的不同而不同在中按照常規(guī)理解,的值是什么取決于函數(shù)如何被調(diào)用然而,的值是什么
1. this是什么
this這個(gè)單詞是一個(gè)代詞,所以this應(yīng)該是 指代某些東西
搞清楚this的關(guān)鍵之處,就是要搞清楚this指代了什么
那么this到底指代了什么呢?
就像你平時(shí)
指著一個(gè)蘋果說 this is an apple
指著一個(gè)香蕉說 this is a banana
同樣,this也會(huì)因?yàn)榍闆r的不同而不同
在JavaScript中
按照常規(guī)理解,this的值是什么取決于函數(shù)如何被調(diào)用
然而,this的值是什么完全取決于對(duì)應(yīng)函數(shù)被call時(shí)傳入的第一個(gè)參數(shù),而這一般是由js提前就預(yù)置好的
注意:這種方法可以判斷一般情況下的this是什么
判斷this值就看函數(shù)是怎么被調(diào)用的[函數(shù)有全局調(diào)用和方法調(diào)用]
this指向調(diào)用它的距離最近的那一個(gè)
// 例子 function fn() { console.log(this) } let obj = { a: "", fn: fn } // 場(chǎng)景一 fn() // window[瀏覽器] or global[node] // 場(chǎng)景二 obj.fn() // obj // 場(chǎng)景一:全局調(diào)用 // 場(chǎng)景二:方法調(diào)用
function VS method
function xx(){...} 是function
method某個(gè)對(duì)象下面的方法 如 obj = {fn:function(){...}} obj.fn() 叫做方法[method]
更詳細(xì)的說明請(qǐng)看深入淺出面向?qū)ο蠛驮汀靖拍钇?】
// test1 function fn() { console.log(this) } let obj1 = { wrapper: { a: "a", fn: fn } } obj1.wrapper.fn() // ? // fn()是被當(dāng)做wrapper的方法被調(diào)用的,所以this是wrapper // this指向調(diào)用它的距離最近的那一個(gè) // test2 function executeCallback(cb) { cb() } executeCallback(obj1.wrapper.fn) // this是全局變量 // 因?yàn)閑xecuteCallback函數(shù)是把cb當(dāng)成全局函數(shù)進(jìn)行調(diào)用的 // 不像是obj.cb(),若是obj.cb()就是方法調(diào)用了
按照常規(guī)理解已經(jīng)可以解決大部分的面試、筆試題了,但如果想究this之根本,還需要通過call2.2 用call理解
注意:通過對(duì)call的初步理解,你可以知道this的值為什么是這樣的,但這種思維不方便你猜this
首先,我們要清楚this在函數(shù)中的位置
function fn1([this], parameter) { // this就是隱藏的第一個(gè)參數(shù),而且永遠(yuǎn)是第一個(gè)參數(shù) console.log(this) }
其次,我們要知道call的語法
fun.call(thisArg, arg1, arg2, ...)
OK,現(xiàn)在我們要知道你在使用call的時(shí)候
call傳入的第一個(gè)參數(shù)可以指定(改變)fn1的第一個(gè)參數(shù),也就是隱藏的this
所以,為什么直接全局調(diào)用fn1時(shí),打印出來的是window呢?
因?yàn)閖s已經(jīng)幫你call了
// 你寫的代碼 fn1() // 在你寫上面代碼的時(shí)候,js幫你寫了一行你看不到的代碼 fn1().call(undefined) // 你可能回問:這樣打出來的值應(yīng)該是undefined呀 // 但瀏覽器有個(gè)機(jī)制 // 如果你傳的 thisArg 就 null 或者 undefined,那么 window 對(duì)象就是默認(rèn)的 context(嚴(yán)格模式下默認(rèn) context 是 undefined)
我們重新來看待一下全局調(diào)用和方法調(diào)用,以及js是如何用call指定this的
// 例子 function fn() { console.log(this) } let obj = { a: "", fn: fn } // 場(chǎng)景一 fn() // window[瀏覽器] or global[node] // js幫你寫的代碼 fn().call(undefined) // 場(chǎng)景二 obj.fn() // obj // js幫你寫的代碼 obj.fn().call(obj)
小測(cè)試(小陷阱)
let module = { x: 42, getX: function () { return this.x; } } let retrieveX = module.getX; console.log(retrieveX()); // undefined console.log(module.getX()) // 422.3 嚴(yán)格模式下的this
嚴(yán)格模式下只需要注意一點(diǎn)就行,其它情況下與非嚴(yán)格模式相同
全局作用域里函數(shù)中的this是undefined
function test() { "use strict" console.log(this) } test() // undefined
所以,在使用構(gòu)造函數(shù)時(shí),如果忘了加new,this不再指向全局對(duì)象,而是報(bào)錯(cuò),因?yàn)檫@就是函數(shù)的全局調(diào)用
let People = function (name) { "use strict" this.name = name } People() // Cannot set property "name" of undefined3.幾種復(fù)雜情況中的this 3.1 數(shù)組中的this
function fn() { console.log(this) } arr[fn, fn2, fn3] arr[0]() // ?? // answer:arr // 解析 // 數(shù)組也是對(duì)象的一種 // arr[0]() 可以看做 arr.0().call(arr)3.2 嵌套函數(shù)中的this
// 例子一 function fn0() { function fn() { console.log(this); } fn(); } fn0(); // fn中this是全局變量 // 例子二 let a = { b: function () { console.log(this) // {b:fn} function xx() { console.log(this) // window } xx() } } a.b()3.3 setTimeout、setInterval中的this
document.addEventListener("click", function (e) { console.log(this); setTimeout(function () { console.log(this); // 這里的this是全局變量 }, 200); }, false);3.4 事件中的this
document.querySelector("div").addEventListener("click",function (e) { console.log(this) // }) // 事件里的this指向的是觸發(fā)事件的DOM節(jié)點(diǎn)3.5 使用new時(shí)的this
請(qǐng)看深入淺出面向?qū)ο蠛驮汀痉馄匦抡J(rèn)識(shí)new】
4.總結(jié)如果幾種復(fù)雜情況下的this你看完了,你應(yīng)該會(huì)有疑惑
為啥我明白了全局調(diào)用和方法調(diào)用,但this的值仍然和我推斷的不一樣呢?
我說過了,this的值是call的第一個(gè)參數(shù),js已經(jīng)給很多this進(jìn)行call了
所以,總結(jié)一下
this的值是什么,你別猜,很可能會(huì)和你想的不一樣
console出來或者去看文檔、看源碼才是最穩(wěn)妥的選擇
如果你非要猜,就套用一下我這篇博客寫到的這幾種情況
如果你怕猜錯(cuò),又要用到this,很簡(jiǎn)單,直接用bind去強(qiáng)制指定this
關(guān)于call/apply/bind 請(qǐng)看this總結(jié)【2】—— call/apply和bind5.參考
this 的值到底是什么?一次說清楚
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92865.html
摘要:和概覽我們要將歸為一類,單獨(dú)歸為一類三者的共同點(diǎn)是都可以指定和都是綁定在的原型上的,所以的實(shí)例都可以調(diào)用這三個(gè)方法至于為什么,看完這篇文章你就懂了如果你不懂什么是實(shí)例的話,請(qǐng)移步深入淺出面向?qū)ο蠛驮透拍钇钊霚\出面向?qū)ο蠛驮透拍钇谝粋€(gè) 1.call/apply和bind概覽 我們要將call/apply歸為一類,bind單獨(dú)歸為一類 三者的共同點(diǎn)是都可以指定this call/...
摘要:目前采用動(dòng)態(tài)加載異步組件的方式來實(shí)現(xiàn)小組件之間的通信。內(nèi)容使用過的都應(yīng)該知道的動(dòng)態(tài)加載組件通過來綁定需要加載的組件??偨Y(jié)本篇主要借助的動(dòng)態(tài)組件和打包單文件來實(shí)現(xiàn)動(dòng)態(tài)加載異步組件,通過的事件總線掛載在上來實(shí)現(xiàn)平級(jí)組件之間的通信。 背景: 目前我們項(xiàng)目都是按組件劃分的,然后各個(gè)組件之間封裝成產(chǎn)品。目前都是采用iframe直接嵌套頁面。項(xiàng)目中我們還是會(huì)碰到一些通用的組件跟業(yè)務(wù)之間有通信,這種...
摘要:說明的視頻片段分發(fā)現(xiàn)在沒做出什么成果作者還提了一句,協(xié)議有望成為直播內(nèi)容的傳播協(xié)議。仿佛也沒能掩飾住不知道怎么分發(fā)視頻片段的尷尬說了這么多,看了代碼發(fā)現(xiàn)視頻片段還是通過分發(fā)總結(jié)最終將建立一個(gè)可擴(kuò)展的,即用即付的直播網(wǎng)絡(luò) Background Livepeer旨在構(gòu)建帶有激勵(lì)機(jī)制的視頻直播分布式網(wǎng)絡(luò) Blockchain 以太坊 智能合約和交易基于Ethereum以太坊網(wǎng)絡(luò) DP...
摘要:箭頭函數(shù)基本語法函數(shù)語法具名函數(shù)匿名函數(shù)三句話第一句話聲明第二句話聲明匿名函數(shù)第三句話把匿名函數(shù)賦值給箭頭函數(shù)語法特點(diǎn)只能做賦值,不能做聲明第一種寫法完全寫法不省略參數(shù)個(gè)數(shù),不省略函數(shù)體花括號(hào)參數(shù)個(gè)數(shù)函數(shù)體內(nèi)語句個(gè)數(shù)第二種寫法省略參數(shù)括號(hào)參 1.箭頭函數(shù)基本語法 1.1 ES3 函數(shù)語法 // 具名函數(shù) function xxx(arg1, arg2) { console.lo...
閱讀 1884·2021-09-22 15:29
閱讀 3361·2019-08-30 15:44
閱讀 3570·2019-08-30 15:43
閱讀 1769·2019-08-30 13:48
閱讀 1497·2019-08-29 13:56
閱讀 2483·2019-08-29 12:12
閱讀 977·2019-08-26 11:35
閱讀 1059·2019-08-26 10:25