一文詳解js中如何改變this指向
1.this指向
什么是this指向?
在 JavaScript中,this的指向取決于函數(shù)被調(diào)用的方式,而非定義的位置
1.1常見的this
- 獨(dú)立函數(shù)
函數(shù)獨(dú)立調(diào)用時(shí),this指向全局對(duì)象(瀏覽器中為 window,Node.js中為global)。
function show() {
console.log(this); // window(非嚴(yán)格模式)
}
show();
嚴(yán)格模式下為undefined
function show() {
"use strict"
console.log(this); // undefined
}
show(); // 如果window.show()那么此時(shí)的this指向的就是window
- 對(duì)象函數(shù)
函數(shù)作為對(duì)象方法調(diào)用時(shí),this 指向調(diào)用它的對(duì)象
const user = {
name: "Alice",
greet() {
console.log(`Hello, ${this.name}!`); // Hello, Alice!
}
};
user.greet();
方法被分離后調(diào)用會(huì)導(dǎo)致this丟失
const func = user.greet; func(); // ? 錯(cuò)誤:this 丟失(指向 window/undefined)
- 箭頭函數(shù)
箭頭函數(shù)的this定義:箭頭函數(shù)的this是在定義函數(shù)時(shí)綁定的,不是在執(zhí)行過程中綁定的。簡單的說,函數(shù)在定義時(shí),this就繼承了定義函數(shù)的對(duì)象。
箭頭函數(shù)內(nèi)的this就是箭頭函數(shù)外的那個(gè)this為什么?
注意:箭頭函數(shù)沒有自己的this
const obj = {
name: "Dave",
regularFunc: function() {
console.log(this.name); // Dave(隱式綁定)
},
arrowFunc: () => {
console.log(this.name); // 空(繼承外層 this)window上沒有name
}
};
obj.regularFunc();
obj.arrowFunc();
let name = "123";
let person = {
name: "456",
fn1: function() {
// 這邊的this和下面的setTimeout函數(shù)下的this相等
let that = this;
setTimeout(() => {
console.log(this.name, that === this); // '456' true
}, 0);
},
fn2: function() {
// 這邊的this和下面的setTimeout函數(shù)下的this不相等
let that = this;
setTimeout(function() {
console.log(this.name, that === this); // '123' false
}, 0);
},
};
person.fn1(); // '456' true
person.fn2(); // '123' false
- DOM節(jié)點(diǎn)
非嚴(yán)格模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>最編程 創(chuàng)未來</title>
</head>
<body>
<button>變色</button>
<script>
let elements = document.getElementsByTagName("button")[0];
elements.addEventListener(
"click",
function () {
this.style.backgroundColor = "#A5D9F3";
},
false
);
</script>
</body>
</html>

嚴(yán)格模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>最編程 創(chuàng)未來</title>
</head>
<body>
<button>變色</button>
<script>
'use strict'
var elements = document.getElementsByTagName("button")[0];
elements.addEventListener(
"click",
function () {
console.log(this)
this.style.backgroundColor = "#A5D9F3";
},
false
);
</script>
</body>
</html>

5. 內(nèi)聯(lián)事件函數(shù)
當(dāng)代碼被內(nèi)聯(lián)處理函數(shù)調(diào)用時(shí),它的this指向監(jiān)聽器所在的DOM元素,不區(qū)分嚴(yán)格或非嚴(yán)格模式
<button onclick="console.log(this)">點(diǎn)擊測(cè)試</button> <!-- <button onclick="console.log(this)">點(diǎn)擊測(cè)試</button> -->
當(dāng)代碼被包括在函數(shù)內(nèi)部執(zhí)行時(shí),其this指向等同于函數(shù)直接調(diào)用的情況,即在非嚴(yán)格模式指向全局對(duì)象window
<button onclick="(function() { console.log(this) })()">點(diǎn)擊測(cè)試</button> <!-- Window {window: Window, self: Window, document: document, name: '最編程', location: Location, …} -->
當(dāng)代碼被包括在函數(shù)內(nèi)部執(zhí)行時(shí),其this指向等同于函數(shù)直接調(diào)用的情況,在嚴(yán)格模式指向undefined
<button onclick="(function() {'use strict'; console.log(this) })()">點(diǎn)擊測(cè)試</button> <!-- undefined -->
- 構(gòu)造函數(shù)
構(gòu)造函數(shù)中,this 指向新創(chuàng)建的實(shí)例對(duì)象Person{}
function Person(name) {
this.name = name;
}
const charlie = new Person("金小子");
console.log(charlie.name); // 金小子
// 偽代碼展示 new 的操作流程
const charlie = new Person("金小子");
// 實(shí)際發(fā)生的步驟:
// 1. 創(chuàng)建新對(duì)象
const tempObj = {};
// 2. 設(shè)置原型鏈
tempObj.__proto__ = Person.prototype;
// 3. 將 this 綁定到新對(duì)象并執(zhí)行構(gòu)造函數(shù)
Person.call(tempObj, "金小子"); // 此時(shí)構(gòu)造函數(shù)內(nèi)的 this = tempObj
// 4. 返回新對(duì)象
const charlie = tempObj;
以上就是常見的this指向,那么接下來來看改變this指向的方式。
2. call、apply、bind
JavaScript 的 call、apply 和 bind 都是用于顯式綁定函數(shù)執(zhí)行時(shí)的 this 指向。
三者核心區(qū)別:
● call:立即執(zhí)行函數(shù),逐個(gè)傳遞參數(shù)
● apply:立即執(zhí)行函數(shù),數(shù)組形式傳遞參數(shù)
● bind:不立即執(zhí)行,返回新函數(shù)(永久綁定 this 和部分參數(shù))
2.1 call
call
語法
func.call(thisArg, arg1, arg2, ...)
例子
function greet(message) {
console.log(`${message}, ${this.name}!`);
}
const person = { name: "Alice" };
// 將 greet 的 this 指向 person,并傳遞參數(shù)
greet.call(person, "Hello"); // 輸出: "Hello, Alice!"
● greet 中的 this 原本指向全局(如 window),但通過 call 將 this 綁定到 person 對(duì)象
● “Hello” 作為參數(shù)逐個(gè)傳遞
2.2 apply
語法
func.apply(thisArg, [argsArray])
示例
function introduce(age, job) {
console.log(`${this.name} is ${age} years old and works as a ${job}.`);
}
const person = { name: "Bob" };
// 將 introduce 的 this 指向 person,參數(shù)通過數(shù)組傳遞
introduce.apply(person, [30, "developer"]); // 輸出: "Bob is 30 years old and works as a developer."
● 參數(shù)以數(shù)組 [30, “developer”] 形式傳遞(適合動(dòng)態(tài)參數(shù)場(chǎng)景)
● 等同于 introduce.call(person, 30, “developer”)
2.3 bind
語法
const newFunc = func.bind(thisArg, arg1, arg2, ...) newFunc()
示例
function logHobby(hobby1, hobby2) {
console.log(`${this.name} likes ${hobby1} and ${hobby2}.`);
}
const person = { name: "Charlie" };
// 創(chuàng)建新函數(shù),永久綁定 this 和部分參數(shù)
const boundFunc = logHobby.bind(person, "hiking");
// 調(diào)用新函數(shù)時(shí)只需傳入剩余參數(shù)
boundFunc("reading"); // 輸出: "Charlie likes hiking and reading."
● bind 返回一個(gè)新函數(shù) boundFunc,其 this 永久綁定為 person
● “hiking” 被預(yù)設(shè)為第一個(gè)參數(shù),調(diào)用時(shí)只需傳遞剩余參數(shù)
總結(jié)
| 方法 | 執(zhí)行時(shí)機(jī) | 參數(shù)形式 | 是否返回新函數(shù) |
|---|---|---|---|
| call | 立即執(zhí)行 | 逐個(gè)參數(shù) (arg1, arg2) | ? |
| apply | 立即執(zhí)行 | 數(shù)組 ([args]) | ? |
| bind | 延遲執(zhí)行 | 逐個(gè)參數(shù)(可部分預(yù)設(shè)) | ? |
?? 核心總結(jié)
this 指向是 JavaScript 中核心且易混淆的知識(shí)點(diǎn),其本質(zhì)遵循「調(diào)用決定指向」的原則(箭頭函數(shù)除外):
普通函數(shù):this 指向調(diào)用它的對(duì)象,獨(dú)立調(diào)用時(shí)指向全局(嚴(yán)格模式為 undefined);
箭頭函數(shù):無自有 this,繼承定義時(shí)外層作用域的 this;
構(gòu)造函數(shù) / 事件處理:this 分別指向?qū)嵗龑?duì)象、觸發(fā)事件的 DOM 元素;
顯式綁定:call/apply/bind 可強(qiáng)制修改 this 指向,三者僅在「執(zhí)行時(shí)機(jī)、參數(shù)形式」上有差異(call/apply 立即執(zhí)行,bind 返回新函數(shù))。
?? 實(shí)踐建議
日常開發(fā)中,優(yōu)先通過「對(duì)象方法調(diào)用」「箭頭函數(shù)」「bind 綁定」明確 this 指向,避免全局 this 污染;
處理動(dòng)態(tài)參數(shù)時(shí)用 apply,需預(yù)設(shè)參數(shù) / 延遲執(zhí)行時(shí)用 bind,簡單傳參優(yōu)先 call;
嚴(yán)格模式下需格外注意獨(dú)立函數(shù)的 this 指向(變?yōu)?undefined),避免意外報(bào)錯(cuò)。
?? 記憶口訣
this 指向:「誰調(diào)用,指向誰;箭頭函數(shù),找外層;構(gòu)造 /new,指實(shí)例;顯式綁定,聽 call/apply/bind」;
綁定三兄弟:「call 逐個(gè)傳,apply 數(shù)組傳,bind 綁完等調(diào)用」。
到此這篇關(guān)于js中如何改變this指向的文章就介紹到這了,更多相關(guān)js改變this指向內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript實(shí)現(xiàn)簡單飛機(jī)大戰(zhàn)小游戲
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)簡單飛機(jī)大戰(zhàn)小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
詳解微信小程序scroll-view橫向滾動(dòng)的實(shí)踐踩坑及隱藏其滾動(dòng)條的實(shí)現(xiàn)
這篇文章主要介紹了詳解微信小程序scroll-view橫向滾動(dòng)的實(shí)踐踩坑及隱藏其滾動(dòng)條的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03
JS的遞增/遞減運(yùn)算符和帶操作的賦值運(yùn)算符的等價(jià)式
JS的遞增/遞減運(yùn)算符和帶操作的賦值運(yùn)算符的等價(jià)式...2007-12-12
JavaScript通過字典進(jìn)行字符串翻譯轉(zhuǎn)換的方法
這篇文章主要介紹了JavaScript通過字典進(jìn)行字符串翻譯轉(zhuǎn)換的方法,涉及javascript字符串轉(zhuǎn)換的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
微信小程序的運(yùn)行機(jī)制與安全機(jī)制解決方案詳解
這篇文章主要介紹了微信小程序的運(yùn)行機(jī)制與安全機(jī)制解決方案,接觸小程序有一段時(shí)間了,總得來說小程序開發(fā)門檻比較低,但其中基本的運(yùn)行機(jī)制和原理還是要懂的2023-02-02
微信小程序scroll-view的滾動(dòng)條設(shè)置實(shí)現(xiàn)
這篇文章主要介紹了微信小程序scroll-view的滾動(dòng)條設(shè)置實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03

