最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript 中的 this 綁定機制深入解析

 更新時間:2025年11月28日 10:06:23   作者:77美式  
本文詳細介紹了JavaScript中this關(guān)鍵字的綁定機制,從核心原則出發(fā),按優(yōu)先級拆解了new綁定、顯式綁定、隱式綁定和默認綁定等規(guī)則,通過實際場景和案例,幫助讀者徹底理清this的指向邏輯,感興趣的朋友跟隨小編一起看看吧

深入理解 JavaScript 中的 this 綁定機制

在 JavaScript 學習路徑中,this 關(guān)鍵字絕對是繞不開的核心知識點,也是最容易讓人困惑的概念之一。很多開發(fā)者會被其“變幻莫測”的指向搞得暈頭轉(zhuǎn)向,甚至戲稱其為“JavaScript 中的薛定諤”。但實際上,this 的指向并非毫無規(guī)律,其核心原則只有一個:this 是函數(shù)執(zhí)行時的上下文對象,指向誰完全取決于函數(shù)的調(diào)用方式,而非定義位置。

本文將從核心原則出發(fā),按優(yōu)先級拆解 this 的綁定規(guī)則,結(jié)合實際場景與案例,幫你徹底理清 this 的指向邏輯。

一、核心認知:this 指向的本質(zhì)

在探討具體規(guī)則前,我們需要先建立一個關(guān)鍵認知:this 是動態(tài)綁定的,它的指向只在函數(shù)執(zhí)行的那一刻才最終確定。

舉個直觀的例子:

function sayHi() {
  console.log(this.name);
}
const person1 = { name: "張三", sayHi };
const person2 = { name: "李四", sayHi };
person1.sayHi(); // 張三
person2.sayHi(); // 李四

同一個 sayHi 函數(shù),只因調(diào)用者不同,this 就指向了不同的對象。這正是 this 的核心特性——執(zhí)行上下文決定指向。

而所有 this 綁定場景,都遵循一套明確的優(yōu)先級規(guī)則(從高到低):
new 綁定 > 顯式綁定(call/apply/bind)> 隱式綁定(對象調(diào)用)> 默認綁定(全局/嚴格模式)

二、分場景拆解 this 綁定規(guī)則

1. 默認綁定:函數(shù)獨立調(diào)用時

當函數(shù)沒有任何調(diào)用前綴(不是對象屬性、不是 new 調(diào)用、未使用 call/apply/bind),即為獨立調(diào)用,此時觸發(fā)默認綁定。

  • 非嚴格模式:this 指向全局對象(瀏覽器中是 window,Node.js 中是 global);
  • 嚴格模式('use strict'):this 指向 undefined(ES5 引入嚴格模式的核心目的之一,就是避免意外修改全局變量)。

代碼示例

// 非嚴格模式
function foo() {
  console.log(this); // window(瀏覽器環(huán)境)
}
foo(); // 獨立調(diào)用,觸發(fā)默認綁定
// 嚴格模式
function bar() {
  'use strict';
  console.log(this); // undefined
}
bar();
// 嵌套函數(shù)的默認綁定
const obj = {
  fn() {
    // 這里的 this 是 obj(隱式綁定)
    function inner() {
      console.log(this); // window(非嚴格模式,獨立調(diào)用觸發(fā)默認綁定)
    }
    inner(); // 無調(diào)用前綴,獨立執(zhí)行
  }
};
obj.fn();

注意:嵌套函數(shù)的 this 與外層函數(shù)的 this 無關(guān),只要是獨立調(diào)用,就遵循默認綁定。

2. 隱式綁定:函數(shù)作為對象屬性調(diào)用時

當函數(shù)作為某個對象的屬性,通過 對象.函數(shù)() 的形式調(diào)用時,this 會指向這個調(diào)用者對象(即 . 前面的對象)。這是日常開發(fā)中最常見的綁定場景之一。

代碼示例

const user = {
  name: "王五",
  age: 28,
  introduce() {
    console.log(`我是${this.name},今年${this.age}歲`);
  },
  address: {
    city: "北京",
    showLocation() {
      console.log(`我在${this.city}`); // this 指向 address 對象
    }
  }
};
user.introduce(); // 我是王五,今年28歲(this = user)
user.address.showLocation(); // 我在北京(this = address)

常見陷阱:隱式綁定丟失
隱式綁定的核心是“函數(shù)作為對象屬性被調(diào)用”,如果函數(shù)被抽離出來獨立執(zhí)行,或作為回調(diào)函數(shù)傳遞,就會丟失原對象綁定,退化為默認綁定。

典型場景

const user = {
  name: "趙六",
  sayHi() {
    console.log(this.name);
  }
};
// 陷阱1:函數(shù)賦值給獨立變量
const hi = user.sayHi; // 僅獲取函數(shù)引用,未執(zhí)行
hi(); // undefined(this = window,非嚴格模式)
// 陷阱2:作為回調(diào)函數(shù)傳遞
setTimeout(user.sayHi, 1000); // undefined(定時器回調(diào)獨立執(zhí)行)
[1,2,3].forEach(user.sayHi); // undefined(forEach 回調(diào)獨立執(zhí)行)

3. 顯式綁定:用 call/apply/bind 強制指定 this

當我們需要手動控制 this 指向時,可以使用函數(shù)原型上的 call、apply、bind 方法,這種方式稱為顯式綁定,優(yōu)先級高于隱式綁定。

三者的核心區(qū)別與用法如下表所示:

方法核心作用語法格式執(zhí)行時機
call強制綁定 this,傳遞參數(shù)fn.call(thisArg, arg1, arg2, ...)立即執(zhí)行
apply強制綁定 this,數(shù)組形式傳遞參數(shù)fn.apply(thisArg, [arg1, arg2, ...])立即執(zhí)行
bind強制綁定 this,返回新函數(shù)(不立即執(zhí)行)const newFn = fn.bind(thisArg, arg1, arg2, ...)后續(xù)手動執(zhí)行

代碼示例

function printInfo(job) {
  console.log(`${this.name},從事${job}工作`);
}
const personA = { name: "錢七" };
const personB = { name: "孫八" };
// call:立即執(zhí)行,參數(shù)逐個傳遞
printInfo.call(personA, "前端開發(fā)"); // 錢七,從事前端開發(fā)工作
// apply:立即執(zhí)行,參數(shù)以數(shù)組傳遞
printInfo.apply(personB, ["后端開發(fā)"]); // 孫八,從事后端開發(fā)工作
// bind:返回新函數(shù),this 永久綁定
const printTeacher = printInfo.bind(personA, "講師");
printTeacher(); // 錢七,從事講師工作
// 即使后續(xù)用 call 嘗試修改,也無效
printTeacher.call(personB, "產(chǎn)品經(jīng)理"); // 錢七,從事講師工作

特殊情況:如果給 call/apply/bind 傳遞的 thisArgnullundefined,則該參數(shù)會被忽略,this 遵循默認綁定:

printInfo.call(null, "設(shè)計師"); // undefined,從事設(shè)計師工作(非嚴格模式)

4. new 綁定:構(gòu)造函數(shù)調(diào)用時

當函數(shù)通過 new 關(guān)鍵字調(diào)用時(此時函數(shù)稱為“構(gòu)造函數(shù)”),this 會指向新創(chuàng)建的實例對象,這是優(yōu)先級最高的綁定規(guī)則。

new 關(guān)鍵字執(zhí)行時,會依次完成 4 件事:

  1. 創(chuàng)建一個空對象(const instance = {});
  2. 讓空對象的 __proto__ 指向構(gòu)造函數(shù)的 prototype(實現(xiàn)原型繼承);
  3. 構(gòu)造函數(shù)的 this 指向這個空對象;
  4. 若構(gòu)造函數(shù)沒有返回對象,則默認返回這個新對象。

代碼示例

function Person(name, age) {
  this.name = name;
  this.age = age;
  console.log(this); // Person { name: '周九', age: 30 }(this 指向新實例)
}
const person1 = new Person("周九", 30);
console.log(person1.name); // 周九(this 綁定到 person1)
// new 綁定優(yōu)先級高于顯式綁定
const person2 = { name: "吳十" };
const BoundPerson = Person.bind(person2); // 顯式綁定到 person2
const person3 = new BoundPerson("鄭十一", 25);
console.log(person3.name); // 鄭十一(this 指向新實例 person3,而非 person2)

5. 特殊場景:箭頭函數(shù)的 this

ES6 引入的箭頭函數(shù)(() => {})是一個特例——箭頭函數(shù)沒有自己的 this。它的 this 是定義時所在的外層作用域的 this,且一旦綁定就永久固定,無法通過 call/apply/bind/new 修改。

箭頭函數(shù)的設(shè)計初衷,就是為了解決“嵌套函數(shù) this 丟失”的問題。

代碼示例

const obj = {
  name: "王十二",
  asyncTask() {
    // 普通函數(shù)作為回調(diào):this 指向 window(默認綁定)
    setTimeout(function() {
      console.log(this.name); // undefined
    }, 500);
    // 箭頭函數(shù)作為回調(diào):this 繼承外層 asyncTask 的 this(即 obj)
    setTimeout(() => {
      console.log(this.name); // 王十二
    }, 1000);
  }
};
obj.asyncTask();
// 箭頭函數(shù)無法用 new 調(diào)用(會報錯)
const ArrowFn = () => {};
new ArrowFn(); // TypeError: ArrowFn is not a constructor
// 箭頭函數(shù)的 this 無法通過 call 修改
const test = () => console.log(this.name);
test.call({ name: "李十三" }); // undefined(this 仍為外層作用域的 this)

適用場景:箭頭函數(shù)適合作為回調(diào)函數(shù)(如定時器、數(shù)組方法、Promise 回調(diào)),避免 this 指向混亂;不適合作為構(gòu)造函數(shù)或?qū)ο蠓椒ǎ〞?dǎo)致 this 指向不符合預(yù)期)。

三、this 指向判斷流程圖(優(yōu)先級從高到低)

掌握以下流程圖,可快速判斷任意場景下 this 的指向:

  1. 函數(shù)是用 new 調(diào)用的嗎?→ this = 新創(chuàng)建的實例;
  2. 函數(shù)是用 call/apply/bind 調(diào)用的嗎?→ this = 手動指定的對象;
  3. 函數(shù)是作為對象的屬性調(diào)用的嗎?→ this = 調(diào)用者對象;
  4. 函數(shù)是獨立調(diào)用的嗎?→ 非嚴格模式 this = 全局對象,嚴格模式 this = undefined;
  5. 若是箭頭函數(shù)?→ this = 定義時外層作用域的 this

四、經(jīng)典面試題解析(鞏固理解)

題1:隱式綁定丟失與箭頭函數(shù)對比

const user = {
  name: "小明",
  fn1() {
    setTimeout(function() {
      console.log(this.name); // 答案:undefined(默認綁定 window)
    }, 0);
  },
  fn2() {
    setTimeout(() => {
      console.log(this.name); // 答案:小明(繼承 fn2 的 this = user)
    }, 0);
  }
};
user.fn1();
user.fn2();

題2:new 與 bind 優(yōu)先級

function Foo() {
  this.value = 100;
}
const obj = { value: 200 };
const BoundFoo = Foo.bind(obj); // 顯式綁定到 obj
const instance = new BoundFoo();
console.log(instance.value); // 答案:100(new 優(yōu)先級高于 bind,this 指向?qū)嵗?

題3:嵌套對象的隱式綁定

const company = {
  name: "字節(jié)跳動",
  department: {
    name: "前端研發(fā)部",
    getDepartmentName() {
      console.log(this.name);
    }
  }
};
const getDeptName = company.department.getDepartmentName;
getDeptName(); // 答案:undefined(獨立調(diào)用,默認綁定 window)
company.department.getDepartmentName(); // 答案:前端研發(fā)部(this 指向 department)

五、總結(jié)

JavaScript 中的 this 并非“玄學”,而是遵循明確的綁定規(guī)則:

  1. 核心原則:this 指向由函數(shù)調(diào)用方式決定,而非定義位置;
  2. 優(yōu)先級順序:new 綁定 > 顯式綁定 > 隱式綁定 > 默認綁定;
  3. 特殊情況:箭頭函數(shù)無自身 this,繼承外層作用域的 this,適合解決回調(diào)函數(shù) this 丟失問題;
  4. 常見陷阱:隱式綁定丟失(函數(shù)賦值給獨立變量、作為回調(diào)傳遞),需通過 bind 或箭頭函數(shù)規(guī)避。

掌握以上規(guī)則后,無論遇到多么復(fù)雜的 this 場景,都能按優(yōu)先級逐步拆解,精準判斷其指向。

到此這篇關(guān)于深入理解 JavaScript 中的 this 綁定機制的文章就介紹到這了,更多相關(guān)js this綁定機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • js Array.slice的8種不同用法示例

    js Array.slice的8種不同用法示例

    這篇文章主要給大家介紹了關(guān)于js Array.slice的8種不同用法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用js 具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-07-07
  • 微信小程序?qū)崿F(xiàn)計算器(含歷史記錄)

    微信小程序?qū)崿F(xiàn)計算器(含歷史記錄)

    這篇文章主要為大家詳細介紹了微信小程序?qū)崿F(xiàn)計算器,含歷史記錄,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • JavaScript實現(xiàn)返回頂部按鈕案例

    JavaScript實現(xiàn)返回頂部按鈕案例

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)返回頂部按鈕案例,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • JS在IE和FF下attachEvent,addEventListener學習筆記

    JS在IE和FF下attachEvent,addEventListener學習筆記

    今天小弄了一下JS事件,主要說一下FF和IE兼容的問題
    2009-11-11
  • javascript代碼編寫需要注意的7個小細節(jié)小結(jié)

    javascript代碼編寫需要注意的7個小細節(jié)小結(jié)

    每種語言都有它特別的地方,對于JavaScript來說,使用var就可以聲明任意類型的變量,這門腳本語言看起來很簡單,然而想要寫出優(yōu)雅的代碼卻是需要不斷積累經(jīng)驗的。本文利列舉了JavaScript初學者應(yīng)該注意的七個細節(jié),與大家分享。
    2011-09-09
  • JavaScript獲得表單target屬性的方法

    JavaScript獲得表單target屬性的方法

    這篇文章主要介紹了JavaScript獲得表單target屬性的方法,涉及javascript操作表單屬性的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-04-04
  • JavaScript中Math對象相關(guān)知識全解

    JavaScript中Math對象相關(guān)知識全解

    Math對象中的方法很常用,來跟我一起看看吧,下面這篇文章主要給大家介紹了關(guān)于JavaScript中Math對象相關(guān)知識全解的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • 基于node.js的快速開發(fā)透明代理

    基于node.js的快速開發(fā)透明代理

    服務(wù)器端js(Server-Side Javascrpt)很早也就有了,JAVA中也有javascript 的script引擎。
    2010-12-12
  • weebox彈出窗口不居中顯示的解決方法

    weebox彈出窗口不居中顯示的解決方法

    這篇文章主要為大家詳細介紹了weebox彈出窗口不居中顯示的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • easyUI實現(xiàn)(alert)提示框自動關(guān)閉的實例代碼

    easyUI實現(xiàn)(alert)提示框自動關(guān)閉的實例代碼

    下面小編就為大家?guī)硪黄猠asyUI實現(xiàn)(alert)提示框自動關(guān)閉的實例代碼。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11

最新評論

望都县| 松潘县| 吴川市| 长丰县| 璧山县| 枣强县| 根河市| 阆中市| 古丈县| 克什克腾旗| 吉木萨尔县| 屯门区| 临洮县| 新巴尔虎右旗| 五华县| 乌兰察布市| 陵水| 静宁县| 夏河县| 永福县| 寻乌县| 梁山县| 京山县| 壶关县| 闽清县| 泾源县| 南陵县| 武隆县| 泾阳县| 根河市| 泗水县| 邵阳县| 伊通| 成都市| 龙陵县| 墨竹工卡县| 方山县| 鄂托克旗| 扬中市| 岳阳市| 高台县|