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

JavaScript?this綁定規(guī)則具體實例(告別踩坑指南!)

 更新時間:2026年03月31日 08:57:25   作者:不甜情歌  
在JavaScript中this關(guān)鍵字是一個非常重要的概念,它用于在運行時確定某個函數(shù)調(diào)用的上下文,這篇文章主要介紹了JavaScript this綁定規(guī)則的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

前言

在JavaScript學(xué)習(xí)中,this絕對是“讓人又愛又恨”的存在——它看似簡單,用起來卻總讓人摸不著頭腦,一不小心就踩坑。有人說它是“動態(tài)代詞”,有人說它是“隱式傳遞的對象引用”,其實只要摸清它的綁定規(guī)則,就能輕松駕馭!今天就結(jié)合具體代碼實例,從“為什么有this”到“怎么用this”,一步步把this講透~

一、先搞懂:為什么要有this?

很多新手會疑惑,明明可以直接通過對象名訪問屬性,為什么還要用this?其實this的核心作用,是提供一種更優(yōu)雅的方式,隱式傳遞對象引用,讓代碼更簡潔、更易于復(fù)用。

我們來看兩組對比代碼,一眼就能明白this的優(yōu)勢:

// 沒有this的寫法,需要手動傳遞對象
function identify(context) {
  return context.name.toUpperCase()
}
function speek(context) {
  var greeting = 'hello, I am ' + identify(context)
  console.log(greeting); // 輸出:hello, I am TOM
}
var me = { name: 'Tom' }
speek(me) // 每次調(diào)用都要手動傳入me對象
// 有this的寫法,無需手動傳遞,更簡潔
function identify() {
  return this.name.toUpperCase() // this自動指向調(diào)用者
}
function speek() {
  var greeting = 'Hello, I am ' + identify.call(this)
  console.log(greeting); // 輸出:Hello, I am TOM
}
var me = { name: 'Tom' }
speek.call(me) // 用call綁定this,無需重復(fù)傳參

不難發(fā)現(xiàn),有了this,我們不用每次調(diào)用函數(shù)都手動傳遞對象,尤其在復(fù)雜項目中,能大大簡化代碼,提升可讀性和復(fù)用性

二、this用在哪?兩大核心場景

this不是固定不變的,它的指向完全取決于“調(diào)用方式”,而不是“定義位置”。它主要用在兩個場景中,記住這兩點,就能快速定位this的指向:

1. 全局作用域中的this

在全局作用域(不在任何函數(shù)內(nèi)部)中,this直接指向window對象(瀏覽器環(huán)境下)。哪怕是單獨的代碼塊,this依然指向window哦~

{
  let a = this
  console.log(a); // 輸出:Window 對象(瀏覽器環(huán)境)
}
// 全局作用域直接打印this
console.log(this === window); // 輸出:true 

2. 函數(shù)作用域中的this

這是this最常用的場景,也是最容易踩坑的地方。函數(shù)中的this,指向調(diào)用該函數(shù)的對象,不同的調(diào)用方式,this的指向完全不同。接下來我們重點講解函數(shù)中this的5種綁定規(guī)則,每一種都搭配你提供的代碼實例,逐句解析~

三、this的5種綁定規(guī)則

規(guī)則1:默認綁定 → 獨立調(diào)用的函數(shù),this指向window

當(dāng)函數(shù)被“獨立調(diào)用”(沒有任何上下文對象,直接調(diào)用)時,this默認綁定到window。哪怕函數(shù)嵌套在其他函數(shù)中,只要是獨立調(diào)用,this依然指向window。

// 實例1:直接調(diào)用函數(shù)
var a = 1
function foo() {
  console.log(this.a); // this指向window,window.a = 1
}
function bar () {
  var a = 2
  foo() // 獨立調(diào)用foo,this不指向bar,依然指向window
}
bar() // 輸出:1 ?
// 實例2:嵌套函數(shù)獨立調(diào)用
var a = 1
function bar () {
  var a = 2
  function foo() {
    console.log(this.a); // 獨立調(diào)用,this指向window
  }
  foo() // 獨立調(diào)用foo
bar() // 輸出:1 ?
// 實例3:無上下文調(diào)用函數(shù)
function foo() {
  var a = 1
  bar(this.a) // this指向window,window.a未定義,所以傳遞undefined
}
function bar(x) {
  console.log(x); // 輸出:undefined ?
}
foo() // 獨立調(diào)用foo,this指向window

規(guī)則2:隱式綁定 → 上下文對象調(diào)用,this指向該對象

當(dāng)函數(shù)被“上下文對象”調(diào)用時(比如:對象.函數(shù)()),this會隱式綁定到這個上下文對象上。簡單說:誰調(diào)用函數(shù),this就指向誰。

// 實例1:對象直接調(diào)用函數(shù)
function foo() {
  console.log(this.a); // this指向調(diào)用者obj
}
var obj = {
  a: 1,
  foo: foo // foo作為obj的屬性
}
obj.foo() // 調(diào)用者是obj,輸出:1 
// 實例2:多層對象調(diào)用(this指向最近的調(diào)用者)
function foo() {
  console.log(this.a);
}
var obj = {
  a: 1,
  foo: foo
}
var obj2 = {
  a: 2,
  foo: obj // obj2的foo屬性指向obj
}
obj2.foo.foo() // 最終調(diào)用foo的是obj,this指向obj,輸出:1 

規(guī)則3:隱式丟失 → 函數(shù)引用被賦值,this指向“意外對象”

隱式丟失是最容易踩坑的情況!當(dāng)函數(shù)的引用被賦值給另一個變量,或者作為參數(shù)傳遞時,原本的隱式綁定會失效,this會回歸默認綁定(指向window)。

// 實例:函數(shù)引用被賦值,隱式丟失
function foo() {
  console.log(this.a);
}
var obj = {
  a: 1,
  foo: foo
}
// 把obj.foo賦值給變量bar,此時bar是獨立函數(shù)引用
var bar = obj.foo
var a = 2 // window.a = 2
bar() // 獨立調(diào)用bar,this指向window,輸出:2 (原本以為指向obj,實際丟失綁定)

簡單總結(jié):只要函數(shù)不是被“對象.函數(shù)()”直接調(diào)用,而是被賦值后調(diào)用,大概率會發(fā)生隱式丟失哦~

規(guī)則4:顯式綁定 → 主動綁定this,精準控制指向

當(dāng)我們想主動控制this的指向時,就可以用顯式綁定——通過call、apply、bind三個方法,手動將this綁定到指定對象上。這三個方法的用法有細微區(qū)別,結(jié)合實例一次性搞懂:

// 共同前提
var obj = { a: 1 }
function foo(x, y) {
  console.log(this.a, x + y); // this指向我們手動綁定的obj
}
// 1. call方法:直接調(diào)用函數(shù),參數(shù)逐個傳遞
foo.call(obj, 1, 2) // 輸出:1 3 ?(call綁定this為obj,參數(shù)1、2逐個傳入)
// 2. apply方法:直接調(diào)用函數(shù),參數(shù)以數(shù)組形式傳遞
var arr = [1, 2]
foo.apply(obj, arr) // 輸出:1 3 ?(apply參數(shù)是數(shù)組,會自動解構(gòu))
// 3. bind方法:不直接調(diào)用函數(shù),返回一個“綁定了this”的新函數(shù)
const bar = foo.bind(obj, 2, 4) // 綁定this為obj,預(yù)設(shè)參數(shù)2、4
bar(3) // 調(diào)用新函數(shù),額外傳入?yún)?shù)3,最終x=2,y=4+3=7?不!注意:bind預(yù)設(shè)參數(shù)在前
// 正確解析:bind預(yù)設(shè)的2、4是前兩個參數(shù),bar(3)是第三個參數(shù)?不,foo只有x、y兩個參數(shù)
// 最終x=2,y=4,輸出:1 6 ?(bind綁定后,參數(shù)會固定,后續(xù)傳入的參數(shù)會忽略多余的)

小技巧:call和apply的區(qū)別只在參數(shù)傳遞方式,bind和前兩者的區(qū)別是“不立即調(diào)用”,適合需要延遲調(diào)用的場景(比如定時器、事件綁定)。

規(guī)則5:new綁定 → 構(gòu)造函數(shù)中,this指向?qū)嵗龑ο?/h3>

當(dāng)用new關(guān)鍵字調(diào)用構(gòu)造函數(shù)時,this會綁定到“新創(chuàng)建的實例對象”上。這也是構(gòu)造函數(shù)能創(chuàng)建多個實例的核心原因,我們結(jié)合你提供的代碼,解析new的底層邏輯和特殊情況:

// 實例1:正常new調(diào)用,this指向?qū)嵗?
function Animal() {
  this.name = '米奇' // this指向new創(chuàng)建的實例p
}
let a = new Animal()
let a2 = new Animal()
console.log(a.name); // 輸出:米奇 ?(a是實例,this指向a)
console.log(a2.name); // 輸出:米奇 ?(a2是另一個實例,this指向a2)
// 實例2:特殊情況——構(gòu)造函數(shù)return引用類型,new綁定失效(如果renturn 原始對象,對new的綁定不影響)
function Animal() {
  this.name = '米奇'
  return 123 // return的是原始類型
}
let a = new Animal()
console.log(a); // 輸出:Animal { name: '米奇' } ?
console.log(a.name); // 輸出:米奇 ?
function Animal() {
  this.name = '米奇'
  return {b: 1} // return的是引用類型(對象)
}
let a2 = new Animal()
console.log(a2); // 輸出:{b: 1} ?(new綁定失效,返回return的對象)
console.log(a2.name); // 輸出:undefined ?(a2不再是Animal實例,沒有name屬性)

補充new的底層原理(對應(yīng)你代碼中的注釋),幫你徹底理解:

  1. 創(chuàng)建一個空對象(var obj = {});

  2. 將構(gòu)造函數(shù)的this綁定到這個空對象(Animal.call(obj));

  3. 給空對象添加屬性(obj.name = '米奇');

  4. 將空對象的原型指向構(gòu)造函數(shù)的原型(obj.__proto__ = Animal.prototype);

  5. 如果構(gòu)造函數(shù)沒有return,或者return的是基本類型,就返回這個空對象(實例);如果return的是引用類型,就返回這個引用類型。

四、特殊情況:箭頭函數(shù)中的this

箭頭函數(shù)是ES6新增的語法,它和普通函數(shù)最大的區(qū)別的是:箭頭函數(shù)沒有自己的this!箭頭函數(shù)中的this,永遠指向它“外層最近的非箭頭函數(shù)”的this,而且一旦綁定,就無法修改(call、apply、bind也沒用)。

function foo() {
  var bar = () => {
    this.a = 2 // 箭頭函數(shù)沒有this,指向外層非箭頭函數(shù)foo的this
  }
  bar()
}
var obj = {
  a: 1,
  baz: foo
}
obj.baz() // 調(diào)用foo,foo的this指向obj(隱式綁定)
console.log(obj); // 輸出:{a: 2, baz: ?} ?(箭頭函數(shù)的this指向obj,修改了obj.a)
// 驗證:箭頭函數(shù)this無法修改
var obj2 = {a: 3}
bar.call(obj2) // 試圖用call修改this,無效
console.log(obj.a); // 依然是2 ?
console.log(obj2.a); // 還是3 ?

小提醒:箭頭函數(shù)適合用在回調(diào)函數(shù)中(比如定時器、數(shù)組方法),可以避免this指向混亂;但不適合用在構(gòu)造函數(shù)中,因為它沒有自己的this,無法創(chuàng)建實例哦~

五、總結(jié):this指向判斷口訣

看完上面的規(guī)則,可能會覺得有點多,教大家一個簡單的判斷口訣,遇到this就按這個順序來,永遠不會錯:

  1. 看函數(shù)是不是用new調(diào)用?是 → this指向?qū)嵗?/p>

  2. 看函數(shù)是不是用call、apply、bind調(diào)用?是 → this指向綁定的對象;

  3. 看函數(shù)是不是被上下文對象調(diào)用(對象.函數(shù)())?是 → this指向該對象;

  4. 看函數(shù)是不是箭頭函數(shù)?是 → this指向外層最近的非箭頭函數(shù)的this;

  5. 以上都不是 → 默認綁定,this指向window(嚴格模式下是undefined)。

其實this并沒有那么難,核心就是“誰調(diào)用,指向誰”,再記住箭頭函數(shù)和new的特殊情況,多練幾個實例,就能輕松掌握。希望這篇文章能幫你吃透this,從此告別this踩坑煩惱,在JavaScript的路上越走越順哦~

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

相關(guān)文章

  • 如何將JS的變量值傳遞給ASP變量

    如何將JS的變量值傳遞給ASP變量

    asp作為主頁面,外接一個js的,我想知道一下能否在js里面調(diào)用asp的變量值,如果能這些值是怎么傳遞過去的呢?本文將提供解決方法,需要的朋友可以參考下
    2012-12-12
  • JS+HTML5實現(xiàn)獲取手機驗證碼倒計時按鈕

    JS+HTML5實現(xiàn)獲取手機驗證碼倒計時按鈕

    這篇文章主要介紹了基于JS+HTML5實現(xiàn)獲取手機驗證碼倒計時按鈕,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-08-08
  • Postman無法正常返回結(jié)果問題解決

    Postman無法正常返回結(jié)果問題解決

    這篇文章主要介紹了Postman無法正常返回結(jié)果問題解決,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • 微信小程序?qū)崿F(xiàn)星級評價

    微信小程序?qū)崿F(xiàn)星級評價

    這篇文章主要為大家詳細介紹了微信小程序?qū)崿F(xiàn)星級評價,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • WebSocket的簡單介紹及應(yīng)用

    WebSocket的簡單介紹及應(yīng)用

    因此,如果讓服務(wù)器端也可以主動發(fā)送信息到客戶端,就可以很大程度改進這些不足。WebSocket就是一個實現(xiàn)這種雙向通信的新協(xié)議。下面小編來簡單介紹下它
    2019-05-05
  • javascript css float屬性的特殊寫法

    javascript css float屬性的特殊寫法

    使用js操作css屬性的寫法是有一定的規(guī)律的
    2008-11-11
  • JS構(gòu)造函數(shù)與原型prototype的區(qū)別介紹

    JS構(gòu)造函數(shù)與原型prototype的區(qū)別介紹

    下面小編就為大家?guī)硪黄狫S構(gòu)造函數(shù)與原型prototype的區(qū)別介紹。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • javascript 播放器 控制

    javascript 播放器 控制

    javascript 播放器 控制...
    2007-01-01
  • 微信小程序如何自定義table組件

    微信小程序如何自定義table組件

    這篇文章主要介紹了微信小程序如何自定義table組件,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-06-06
  • 微信小程序自定義彈窗wcPop插件

    微信小程序自定義彈窗wcPop插件

    平時在開發(fā)小程序的時候,彈窗應(yīng)用場景還是蠻廣泛的,但是微信官方提供的彈窗比較有局限性,不能自定義修改。下面通過本文給大家?guī)砹宋⑿判〕绦蜃远x彈窗wcPop插件,感興趣的朋友跟隨小編一起看看吧
    2018-11-11

最新評論

上栗县| 鄄城县| 平原县| 安乡县| 陇川县| 榆中县| 隆化县| 雷山县| 东光县| 宽甸| 怀宁县| 稷山县| 长兴县| 肃南| 内黄县| 孝昌县| 延长县| 郸城县| 南宁市| 原阳县| 丽江市| 巴里| 商河县| 类乌齐县| 彰化市| 旬邑县| 奉贤区| 福泉市| 黄陵县| 依兰县| 津市市| 凤冈县| 两当县| 当雄县| 白河县| 宿州市| 息烽县| 丰原市| 乌兰察布市| 盐城市| 利川市|