JS中this的值詳細講解以及面試指向練習

this?的值取決于它出現的上下文:函數、類或全局。

在函數內部,this?的值取決于函數如何被調用,this?是語言在函數體被執行時為你創建的綁定

對于典型的函數,this?的值是函數被訪問的對象。換句話說,如果函數調用的形式是?obj.f(),那么?this?就指向?obj,例如

function getThis() {return this;
}const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };obj1.getThis = getThis;
obj2.getThis = getThis;console.log(obj1.getThis()); // { name: 'obj1', getThis: [Function: getThis] }
console.log(obj2.getThis()); // { name: 'obj2', getThis: [Function: getThis] }

注意,雖然函數是相同的,但是根據其調用的方式,this?的值是不同的。這與函數參數的工作方式類似。

this到底指向誰

調用函數會創建新的屬于函數自身的執行上下文,執行上下文的調用創建階段會決定this的指向,結論:this的指向,是在調用函數時根據執行上下文所動態確定的,或者說this關鍵字指向函數(方法)運行時的所有者

1.規則:

  • 在函數體中,簡單調用該函數時(非顯式/隱式綁定下),嚴格模式下this綁定到undefined,否則綁定到全局對象window/global
  • 一般構造函數new調用,綁定到新創建的對象上
  • 一般由call/bind/apply方法顯式調用,綁定到指定參數的對象上
  • 一般由上下文對象調用,綁定在該對象上
  • 箭頭函數中,根據外層上下文綁定的this決定this的指向

2.實例分析練習

(1)全局環境下的this

function f1(){console.log(this);
}function f2() {'use strict'console.log(this);
}f1()  //Window對象
f2()  //undefined
const foo = {bar: 10,fn: function () {console.log(this);  //Windowconsole.log(this.bar);  //undefined}
}var fn1=foo.fn
fn1()

上題中this指向的是window,雖然fn函數在foo對象中作為方法被引用,但是在賦值給fn1后,fn1的執行仍然是在window的全局環境中

const foo = {bar: 10,fn: function () {console.log(this);  //{bar:10,fn:f}console.log(this.bar);  //10}
}foo.fn()

上題中this指向的是最后調用他的對象,在foo.fn()語句中this指向foo對象

注意:在執行函數時,如果函數中的this是被上一級的對象所調用,那么this指向的就是上一級的對象;否則指向全局環境

?(2)上下文對象調用中的this

const student={name:'hist',fn:function(){return this}
}console.log(student.fn()===student); //true
const person = {name: 'hist',brother: {name: 'comp',fn: function () {return this.name}}
}console.log(person.brother.fn());  //comp

上題在這種嵌套關系中,this指向最后調用它的對象

const o1 = {text: 'o1',fn: function () {return this.text}
}const o2 = {text: 'o2',fn: function () {return o1.fn()}
}const o3 = {text: 'o3',fn: function () {var fn= o1.fnreturn fn()}
}console.log(o1.fn()); //o1
console.log(o2.fn()); //o1
console.log(o3.fn()); //undefined

第二個相當于最后調用時還是用o1調用的fn()

第三個將o1.fn()賦值給fn后,直接調用fn(),沒有用對象點調用,所以這里this指向window

如果想讓第二個輸出o2怎么做?

const o2 = {text: 'o2',fn: o1.fn()
}

此時我們將賦值操作提前,相當于先把o1.fn()變為this.text,此時我們用o2調用fn()指向的就是o2對象

??(3)bind/call/apply改變this指向

補充:bind/call/apply使用方法

const target={}fn.call(target, 'arg1', 'arg2')
fn.apply(target,['arg1','arg2'])
fn.bind(target, 'arg1', 'arg2')()

示例一

function greet() {console.log(`Hello, ${this.name}`);
}const person = { name: 'Alice' };// 使用 call 明確指定 this
greet.call(person);  // 輸出:Hello, Alice

示例二

function greet(city, country) {console.log(`Hello, ${this.name} from ${city}, ${country}`);
}const person = { name: 'Bob' };// 使用 apply,參數是數組
greet.apply(person, ['New York', 'USA']);  // 輸出:Hello, Bob from New York, USA

示例三

function greet() {console.log(`Hello, ${this.name}`);
}const person = { name: 'Charlie' };// 使用 bind 創建一個新的函數
const boundGreet = greet.bind(person)();// 輸出:Hello, Charlie

??(4)構造函數和this

function Foo(){this.bar='hist'
}const instance=new Foo()
console.log(instance.bar);//hist

new操作符調用構造函數做了什么?

  • 創建一個新的對象
  • 將構造函數的this指向這個新對象
  • 為這個對象添加屬性、方法等
  • 最終返回新對象

下面是構造函數中出現顯示return的情況,分為兩種場景:

function Foo() {this.user = 'hist'const o = {}return o
}const instance = new Foo()
console.log(instance.user);//undefined

?將會輸出 undefined,此時 instance 是返回的空對象 o。

function Foo() {this.user = 'hist';return 1;
}const instance = new Foo();
console.log(instance.user);//hist

?將會輸出 hist,也就是說此時 instance 是返回的目標對象實例 this。

結論:如果在構造函數中顯式返回一個值,且返回的是一個對象,那么 this 就指向這個返回的對象;如果返回的不是一個對象,那么 this 仍然指向實例。

???(5)箭頭函數中的this指向

箭頭函數和普通函數有一個重要的區別:箭頭函數不會有自己的 this,它會繼承外部上下文的 this。

const foo = {fn: function () {setTimeout(function () {console.log(this);});},
};
foo.fn();//window

this 出現在 setTimeout() 中的匿名函數里,因此 this 指向 window 對象

const foo = {fn: function () {setTimeout(() => {console.log(this);});},
};foo.fn();//{fn: ?}
  • 在?foo.fn()?調用時,this?在?fn?方法內指向?foo?對象。
  • setTimeout?中的箭頭函數繼承了外部的?this,也就是?foo?對象。

(6)this優先級

通過 call、apply、bind、new 對 this 綁定的情況稱為顯式綁定

根據調用關系確定的 this 指向稱為隱式綁定

function foo(a) {console.log(this.a);
}const obj1 = {a: 1,foo: foo,
};const obj2 = {a: 2,foo: foo,
};obj1.foo.call(obj2); //2
obj2.foo.call(obj1); //1

call、apply 的顯式綁定一般來說優先級更高

function foo(a) {this.a = a;
}const obj1 = {};
var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a);

上述代碼通過 bind,將 bar 函數中的 this 綁定為 obj1 對象。執行 bar(2) 后,obj1.a 值為 2。即經過 bar(2) 執行后,obj1 對象為:{a: 2}。

當再使用 bar 作為構造函數時:

var baz = new bar(3)
console.log(baz.a)//3

將會輸出 3。我們看 bar 函數本身是通過 bind 方法構造的函數,其內部已經將 this 綁定為 obj1,它再作為構造函數,通過 new 調用時,返回的實例已經與 obj1 解綁。 也就是說:new 綁定修改了 bind 綁定中的 this,因此 new 綁定的優先級比顯式 bind 綁定更高。

function foo() {return (a) => {console.log(this.a);};
}const obj1 = {a: 1,
};const obj2 = {a: 2,
};const bar = foo.call(obj1);
bar.call(obj2);//1

由于 foo() 的 this 綁定到 obj1,bar(引用箭頭函數)的 this 也會綁定到 obj1,箭頭函數的綁定無法被修改。

var a = 123;const foo = () => (a) => {console.log(this.a);};const obj1 = {a: 2,};const obj2 = {a: 3,};const bar = foo.call(obj1);console.log(bar.call(obj2));//123

箭頭函數的綁定無法被修改,foo的執行上下文是window

如果將第一處的var a = 123;改為const?a = 123;

答案將會輸出為 undefined,原因是因為使用 const 聲明的變量不會掛載到 window 全局對象當中

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/62863.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/62863.shtml
英文地址,請注明出處:http://en.pswp.cn/web/62863.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2024年河南省高等職業教育技能大賽 大數據分析與應用賽項競賽方案

2024年河南省高等職業教育技能大賽 大數據分析與應用賽項競賽方案 一、賽項名稱 賽項名稱:大數據分析與應用 賽項編號:HN033 賽項組別:專業核心基本技能賽項 專業大類:電子與信息等 競賽形式:學生組(團體賽…

vue繞過rules自定義編寫動態校驗

今天犯了個低級錯誤,雖然走了很多彎路,但這個過程還是值得記錄一下 例子如下,有兩個輸入框: 第一個是套餐選擇下拉框,可以下拉選擇三個內容 第二個要根據上面的套餐選擇三個選項來決定怎么顯示,使用v-if&…

數字化招聘系統如何幫助企業實現招聘效率翻倍提升?

眾所周知,傳統的招聘方式已經難以滿足現代企業對人才的需求,而數字化招聘系統的出現,為企業提供了全新的解決方案。通過數字化招聘系統,企業可以自動化處理繁瑣的招聘流程,快速篩選合適的候選人,從而大幅提…

短視頻矩陣源碼開發部署全流程解析

在當今的數字化時代,短視頻已成為人們娛樂、學習和社交的重要方式。短視頻矩陣系統的開發與部署,對于希望在這一領域脫穎而出的企業和個人而言,至關重要。本文將詳細闡述短視頻矩陣源碼的開發與部署流程,并附上部分源代碼示例&…

華為云云原生中間件DCS DMS 通過中國信通院與全球IPv6測試中心雙重能力檢測

近日,中國信息通信研究院(以下簡稱“中國信通院”)與全球IPv6測試中心相繼宣布,華為云的分布式緩存服務(Distributed Cache Service,簡稱DCS)和分布式消息服務(Distributed Message …

關閉WPS在線功能資源和功能推薦

Kingsoft\WPS Office\12.1.0.18912\office6 選擇 【高級】 點擊 【確定】

Polars數據聚合與旋轉實戰教程

在這篇博文中,我們的目標是解決數據愛好者提出的一個常見問題:如何有效地從Polars DataFrame中創建匯總視圖,以便在不同時間段或類別之間輕松進行比較。我們將使用一個實際的數據集示例來探索實現這一目標的各種方法。 Polars簡介 Polars 是…

2024154讀書筆記|《帶著詩歌上街去》——我不長葉子,不開花,也不必要什么結果

2024154讀書筆記|《帶著詩歌上街去》——我不長葉子🌿,不開花🌼,也不必要什么結果 《帶著詩歌上街去》作者隔花人,作者很有巧思,在拍攝的照片上做詩,詩不是很有感覺,但是在墻上、風景…

建立基于TCP的客戶端和服務端

函數介紹: 1.socket() 作用:創建套接字 domain: AF_INET:IPv4 Internet 協議族。AF_INET6:IPv6 Internet 協議族。AF_UNIX:Unix 域協議族,用于在同一臺主機上的進程間通信。 type: SOCK_STREAM&#xff1a…

CNCF云原生生態版圖-分類指南(三)- 運行時

CNCF云原生生態版圖-分類指南(三)- 運行時 CNCF云原生生態版圖-分類指南三、運行時(Runtime)(一)云原生存儲(Cloud Native Storage)1. 是什么?2. 解決什么問題&#xff1…

機器學習經典算法

機器學習經典算法學習和分享。 k近鄰算法 線性回歸 梯度下降法 PCA主成分分析法 多項式回歸 邏輯回歸 支撐向量機SVM 決策樹 隨機森林 評價分類指標

MVC基礎——市場管理系統(三)Clean Architecture

文章目錄 項目地址五、Clean Architecture5.1 user cage driven5.1.1創建CoreBusiness 5.2 創建UseCases5.2.1 創建CategoriesUseCases1. 創建VeiwCategoriesUseCase獲取所有Cagegory 5.2.2. 實現ICategoryRepository接口3. 實現獲取所有Category的方法4. 實現獲取一個Cagegory…

手機上和電腦上都能觀看的翻頁電子書是如何制作的?

想知道手機上和電腦上都能觀看的翻頁電子書是都是如何制作的? 想知道這樣的電子書是怎樣呈現出來的? 那收藏這篇文章,我來跟大家說說該如何實現。 操作方法 一、登錄FLBOOK 二、開始制作,有多種創建方式,分別是&…

ABAP時間戳與日期時間轉換及時區處理

一、時間戳轉換為日期時間 1. 基本轉換 CONVERT TIME STAMP <fs_back>-lastchangedatetime TIME ZONE sy-zonloINTO DATE DATA(lv_date)TIME DATA(lv_time).2. 解決8小時時差問題的方案 方案1&#xff1a;直接使用UTC時區&#xff08;推薦&#xff09; CONVERT TIME …

Java 實現給pdf文件指定位置蓋章功能

Java 實現給pdf文件指定位置蓋章功能 開發中遇到一個需求, 需要給用戶上傳的的pdf文件, 指定位置上蓋公章的功能, 經過調研和對比, 最終確定實現思路. 這里是使用pdf文件中的關鍵字進行章子的定位, 之所以這樣考慮是因為如果直接寫死坐標的話, 可能會出現因pdf大小, 縮放, 蓋章…

ASP.NET Core API + MySql

環境 數據庫&#xff1a; mysql8.0 后端&#xff1a; vs2022 ASP.NET Core API .net 8 前端&#xff1a; Hbuilderx bootstrap 5.3.0 jquery v3.7.1 bootstrap-table 1.23.5 創建項目 添加資源包 AutoMapper Microsoft.EntityFrameworkCore.Tools 8.0.0 Pomelo.EntityFramew…

RFDiffusion 計算鍵角函數get_ang解讀

get_ang 函數&#xff08;kinematics.py包中&#xff09;計算三組原子 a,b,c 所形成的平面角&#xff08;planar angle&#xff09;&#xff0c;即 b 為頂點&#xff0c; a,b,c 所確定的角度。 源代碼&#xff1a; def get_ang(a, b, c):"""calculate planar …

Bananna Pi開源社區聯合矽昌通信打造開源的低成本Wifi5路由器

香蕉派 BPI-Wifi5 路由器采用矽昌SF19A2890S2芯片方案設計。它是一款高性能無線路由器&#xff0c;適用于小微企業、家庭和其他網絡環境。Banana Pi開源社區提供整體解決方案。所有代碼開源&#xff0c;用戶可以在上面自由開發自己的應用。 Banana Pi wifi5 路由器github代碼: …

圖像融合算法筆記2024 CDTNet

目錄 ControlCom-Image-Composition CDTNet-High-Resolution-Image-Harmonization 依賴項: trilinear 推理代碼ok: ControlCom-Image-Composition diffusesion https://github.com/bcmi/ControlCom-Image-Composition CDTNet-High-Resolution-Image-Harmonization

item2 for macos

安裝Item2 brew install iterm2 查看終端類型 cat /etc/shells Mac OS X 10.15 已經將默認的shell從Bash換成了zsh&#xff0c;所以不用安裝&#xff0c;10.15以前的可以使用下面的命令進行安裝 brew install zsh 安裝Oh My ZSH # curl sh -c "$(curl -fsSL https://ra…