一文詳解js中如何改變this指向
1.this指向
什么是this指向?
在 JavaScript中,this的指向取決于函數被調用的方式,而非定義的位置
1.1常見的this
- 獨立函數
函數獨立調用時,this指向全局對象(瀏覽器中為 window,Node.js中為global)。
function show() {
console.log(this); // window(非嚴格模式)
}
show();
嚴格模式下為undefined
function show() {
"use strict"
console.log(this); // undefined
}
show(); // 如果window.show()那么此時的this指向的就是window
- 對象函數
函數作為對象方法調用時,this 指向調用它的對象
const user = {
name: "Alice",
greet() {
console.log(`Hello, ${this.name}!`); // Hello, Alice!
}
};
user.greet();
方法被分離后調用會導致this丟失
const func = user.greet; func(); // ? 錯誤:this 丟失(指向 window/undefined)
- 箭頭函數
箭頭函數的this定義:箭頭函數的this是在定義函數時綁定的,不是在執(zhí)行過程中綁定的。簡單的說,函數在定義時,this就繼承了定義函數的對象。
箭頭函數內的this就是箭頭函數外的那個this為什么?
注意:箭頭函數沒有自己的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函數下的this相等
let that = this;
setTimeout(() => {
console.log(this.name, that === this); // '456' true
}, 0);
},
fn2: function() {
// 這邊的this和下面的setTimeout函數下的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é)點
非嚴格模式
<!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>

嚴格模式
<!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. 內聯事件函數
當代碼被內聯處理函數調用時,它的this指向監(jiān)聽器所在的DOM元素,不區(qū)分嚴格或非嚴格模式
<button onclick="console.log(this)">點擊測試</button> <!-- <button onclick="console.log(this)">點擊測試</button> -->
當代碼被包括在函數內部執(zhí)行時,其this指向等同于函數直接調用的情況,即在非嚴格模式指向全局對象window
<button onclick="(function() { console.log(this) })()">點擊測試</button> <!-- Window {window: Window, self: Window, document: document, name: '最編程', location: Location, …} -->
當代碼被包括在函數內部執(zhí)行時,其this指向等同于函數直接調用的情況,在嚴格模式指向undefined
<button onclick="(function() {'use strict'; console.log(this) })()">點擊測試</button> <!-- undefined -->
- 構造函數
構造函數中,this 指向新創(chuàng)建的實例對象Person{}
function Person(name) {
this.name = name;
}
const charlie = new Person("金小子");
console.log(charlie.name); // 金小子
// 偽代碼展示 new 的操作流程
const charlie = new Person("金小子");
// 實際發(fā)生的步驟:
// 1. 創(chuàng)建新對象
const tempObj = {};
// 2. 設置原型鏈
tempObj.__proto__ = Person.prototype;
// 3. 將 this 綁定到新對象并執(zhí)行構造函數
Person.call(tempObj, "金小子"); // 此時構造函數內的 this = tempObj
// 4. 返回新對象
const charlie = tempObj;
以上就是常見的this指向,那么接下來來看改變this指向的方式。
2. call、apply、bind
JavaScript 的 call、apply 和 bind 都是用于顯式綁定函數執(zhí)行時的 this 指向。
三者核心區(qū)別:
● call:立即執(zhí)行函數,逐個傳遞參數
● apply:立即執(zhí)行函數,數組形式傳遞參數
● bind:不立即執(zhí)行,返回新函數(永久綁定 this 和部分參數)
2.1 call
call
語法
func.call(thisArg, arg1, arg2, ...)
例子
function greet(message) {
console.log(`${message}, ${this.name}!`);
}
const person = { name: "Alice" };
// 將 greet 的 this 指向 person,并傳遞參數
greet.call(person, "Hello"); // 輸出: "Hello, Alice!"
● greet 中的 this 原本指向全局(如 window),但通過 call 將 this 綁定到 person 對象
● “Hello” 作為參數逐個傳遞
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,參數通過數組傳遞
introduce.apply(person, [30, "developer"]); // 輸出: "Bob is 30 years old and works as a developer."
● 參數以數組 [30, “developer”] 形式傳遞(適合動態(tài)參數場景)
● 等同于 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)建新函數,永久綁定 this 和部分參數
const boundFunc = logHobby.bind(person, "hiking");
// 調用新函數時只需傳入剩余參數
boundFunc("reading"); // 輸出: "Charlie likes hiking and reading."
● bind 返回一個新函數 boundFunc,其 this 永久綁定為 person
● “hiking” 被預設為第一個參數,調用時只需傳遞剩余參數
總結
| 方法 | 執(zhí)行時機 | 參數形式 | 是否返回新函數 |
|---|---|---|---|
| call | 立即執(zhí)行 | 逐個參數 (arg1, arg2) | ? |
| apply | 立即執(zhí)行 | 數組 ([args]) | ? |
| bind | 延遲執(zhí)行 | 逐個參數(可部分預設) | ? |
?? 核心總結
this 指向是 JavaScript 中核心且易混淆的知識點,其本質遵循「調用決定指向」的原則(箭頭函數除外):
普通函數:this 指向調用它的對象,獨立調用時指向全局(嚴格模式為 undefined);
箭頭函數:無自有 this,繼承定義時外層作用域的 this;
構造函數 / 事件處理:this 分別指向實例對象、觸發(fā)事件的 DOM 元素;
顯式綁定:call/apply/bind 可強制修改 this 指向,三者僅在「執(zhí)行時機、參數形式」上有差異(call/apply 立即執(zhí)行,bind 返回新函數)。
?? 實踐建議
日常開發(fā)中,優(yōu)先通過「對象方法調用」「箭頭函數」「bind 綁定」明確 this 指向,避免全局 this 污染;
處理動態(tài)參數時用 apply,需預設參數 / 延遲執(zhí)行時用 bind,簡單傳參優(yōu)先 call;
嚴格模式下需格外注意獨立函數的 this 指向(變?yōu)?undefined),避免意外報錯。
?? 記憶口訣
this 指向:「誰調用,指向誰;箭頭函數,找外層;構造 /new,指實例;顯式綁定,聽 call/apply/bind」;
綁定三兄弟:「call 逐個傳,apply 數組傳,bind 綁完等調用」。
到此這篇關于js中如何改變this指向的文章就介紹到這了,更多相關js改變this指向內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解微信小程序scroll-view橫向滾動的實踐踩坑及隱藏其滾動條的實現
這篇文章主要介紹了詳解微信小程序scroll-view橫向滾動的實踐踩坑及隱藏其滾動條的實現,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03

