自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一勞永逸地搞懂 JavaScript中This

開發(fā) 前端
你是否曾覺得 JavaScript 似乎在戲弄你,尤其是當(dāng)它在你面前揮舞 This 關(guān)鍵字時(shí)?那種“好吧,JavaScript,今天我們玩什么游戲?”的感覺。特別是當(dāng)你試圖確定在某段代碼中 This 引用的是什么時(shí)。

引言:this 在 JS 中 —— 為什么它如此重要

你是否曾覺得 JavaScript 似乎在戲弄你,尤其是當(dāng)它在你面前揮舞 this 關(guān)鍵字時(shí)?那種“好吧,JavaScript,今天我們玩什么游戲?”的感覺。特別是當(dāng)你試圖確定在某段代碼中 this 引用的是什么時(shí)。

理解 this 就像在JavaScript廣闊的領(lǐng)域中握住指南針。這不僅僅是為了弄清楚一個(gè)關(guān)鍵字;它是為了打開通往高級編碼技巧和模式的大門。

為什么我們應(yīng)該關(guān)心“this”?

  • 普遍性:就像你無法逃避的流行曲調(diào), this 在JavaScript中隨處可見。從小腳本到龐大的Web應(yīng)用程序,它都會顯現(xiàn)出來。
  • 提高水平:解讀 this 意味著你正在走向像經(jīng)驗(yàn)豐富的專家那樣的編碼。這是更接近健壯且無錯(cuò)誤的腳本的一步。
  • 變色龍行為:this 在許多情境中的含義都會變化,這使它既有趣又時(shí)而令人困惑。

接下來會發(fā)生什么?

做好準(zhǔn)備,因?yàn)槲覀兗磳⒁粍谟酪莸亟议_this的神秘面紗。我們將探索其所有的細(xì)微差別,涵蓋你可能遇到的每一個(gè)場景。不再有猜測或撓頭的困惑!

準(zhǔn)備深入了解嗎?無論你是編寫腳本多年還是剛開始JavaScript之旅,讓我們攜手共進(jìn),一起解開this的神秘面紗!

“this”在全局上下文中:從基礎(chǔ)開始

當(dāng)你剛開始理解JavaScript中的 this 關(guān)鍵字時(shí),最好從頭開始 —— 也就是全局上下文。但是,我們說的全局上下文是什么意思呢?

簡單地說,全局上下文是默認(rèn)的、頂級的環(huán)境,當(dāng)你的代碼不在任何函數(shù)或?qū)ο髢?nèi)部時(shí),它就位于這個(gè)環(huán)境中。那么,在這里 this 是如何表現(xiàn)的呢?

在瀏覽器中:

如果你在瀏覽器中運(yùn)行你的 JavaScript 代碼(像我們大多數(shù)人經(jīng)常做的那樣),全局上下文中的this指的是window對象。這是因?yàn)?,在瀏覽器中,window 對象就是全局對象。

console.log(this === window); // true
var variable = “我是一個(gè)全局變量!”;
console.log(this.variable); // “我是一個(gè)全局變量!”

在這里,當(dāng)我們聲明變量時(shí),它被附加到 window 對象上。因此,在全局上下文中使用this.variable 會給我們那個(gè)變量的值。

在Node.js中:

如果你在Node.js環(huán)境中運(yùn)行你的代碼,情況會有所不同。在Node.js中,this 的頂級值是一個(gè)空對象,不等同于 global。

console.log(this); // {}
global.globalVar = “我在Node中的全局對象上!”;
console.log(global.globalVar); // “我在Node中的全局對象上!”

了解 this 在全局上下文中的行為可能會根據(jù)代碼的執(zhí)行位置而有所不同。

那么,為什么這很重要?

掌握全局上下文中的 this 為理解其在更復(fù)雜場景中的行為提供了基礎(chǔ)。當(dāng)你深入JavaScript時(shí),你會發(fā)現(xiàn)有些情況下,函數(shù)或方法是從全局上下文中調(diào)用的,理解這種行為變得至關(guān)重要。

通過掌握基礎(chǔ)知識,當(dāng)我們深入探討 this 的后續(xù)部分時(shí),你為自己奠定了成功的基礎(chǔ)。

“this”在常規(guī)函數(shù)中:上下文是關(guān)鍵

啊,常規(guī)函數(shù)。與它們的新型箭頭函數(shù)表親相比,它們可能看起來有點(diǎn)老派,但它們?nèi)匀皇荍avaScript的基礎(chǔ)部分。當(dāng)涉及到這些函數(shù)內(nèi)部“this”的行為時(shí),事情可能會變得有點(diǎn)棘手。

基本行為:

在其核心,常規(guī)函數(shù)內(nèi)部的 this 值是由如何調(diào)用該函數(shù)(其調(diào)用上下文)來確定的。讓我們分解一下:

直接調(diào)用函數(shù):

當(dāng)你在全局上下文中調(diào)用一個(gè)函數(shù)時(shí),this 將引用全局對象。

function showThis() {
console.log(this);
}
showThis(); // 在瀏覽器中是‘window’,在Node.js中是‘global’

作為對象內(nèi)的方法:

當(dāng)一個(gè)函數(shù)被定義為對象方法時(shí),this 將引用擁有該方法的對象。

const obj = {
name: “John”,
sayName: function() {
console.log(this.name);
}
};
obj.sayName(); // “John”

在這里,sayName 方法使用 obj 對象調(diào)用。因此,sayName 內(nèi)部的 this 指的是 obj。

特殊情況

使用call、apply和bind:

這些是允許你直接設(shè)置 this 應(yīng)該引用什么的方法,而不考慮函數(shù)如何或在哪里被調(diào)用。

call和apply立即用指定的上下文調(diào)用函數(shù)。

function greet(greeting) {
console.log(greeting + ‘, ‘ + this.name);
}
const person = { name: “Alice” };
greet.call(person, “Hello”); // “Hello, Alice”

bind返回一個(gè)帶有綁定上下文的新函數(shù),但不立即執(zhí)行它。

const boundGreet = greet.bind(person);
boundGreet(“Hi”); // “Hi, Alice”

為什么上下文很重要?

理解常規(guī)函數(shù)內(nèi)部this的行為都是關(guān)于上下文的。它是關(guān)于知道在調(diào)用時(shí)哪個(gè)對象“擁有”函數(shù)。這種洞察可以防止無數(shù)的錯(cuò)誤和挫敗感,尤其是當(dāng)你的JavaScript項(xiàng)目在復(fù)雜性上增長時(shí)。

請記住,在JavaScript的錯(cuò)綜復(fù)雜的迷宮中,this 關(guān)鍵字是你的光明之光。在常規(guī)函數(shù)的世界中,它是上下文,確保你總是在正確的軌道上。當(dāng)我們進(jìn)一步探索時(shí),觀察 this 和上下文之間的動態(tài)舞蹈,適應(yīng)語言的不同節(jié)奏。

箭頭函數(shù)和“this”:游戲規(guī)則改變者

好吧,讓我們談?wù)劶^函數(shù)。當(dāng)ES6出現(xiàn)時(shí),它帶來了這種寫函數(shù)的新方法,不僅看起來更簡潔,而且還改變了我們對 this 的看法。

這都是關(guān)于你來自哪里的

你知道在生活中,我們中的一些人根據(jù)我們所在的地方和我們與誰在一起會戴不同的帽子嗎?常規(guī)函數(shù)也做類似的事情與 this。他們可以是變色龍,根據(jù)他們?nèi)绾伪徽{(diào)用來改變 this 引用什么。

而箭頭函數(shù)呢?他們是直接的。他們從他們的周圍抓住 this 的值,并堅(jiān)持使用它。無論他們?nèi)ツ睦锘蛉绾伪皇褂谩?/p>

const person = {
  name: ‘Anna’,
  activities: [‘reading’, ‘hiking’],
  printActivities() {
    this.activities.forEach(activity => {
    console.log(${this.name} loves ${activity});
  });
 }
};
person.printActivities();
// 輸出:
// Anna loves reading
// Anna loves hiking

注意 forEach 中的箭頭函數(shù)嗎?它舒適地使用 printActivities 中的 this。沒有戲劇。

但有一個(gè)問題。

箭頭函數(shù)有點(diǎn)固執(zhí)。我們用來為常規(guī)函數(shù)設(shè)置 this 的方法,如 call、apply或bind?它們不適用于箭頭函數(shù)。

const obj = {
value: ‘hello’,
  print: () => {
    console.log(this.value);
  }
};
const anotherObj = { value: ‘world’ };
obj.print.call(anotherObj); // 輸出:undefined

我們試圖用 call 偷偷摸摸,但 print 中的箭頭函數(shù)就像,“我知道我是誰!”并堅(jiān)持使用它的原始 this。

所以,箭頭還是不箭頭?

箭頭函數(shù)就像你擁有的那個(gè)最喜歡的工具 —— 超級有用,但不適合每一項(xiàng)工作。當(dāng)你想保持 this不變時(shí),尤其是在回調(diào)中,它們是非常有價(jià)值的。但是當(dāng)你需要一些靈活性時(shí)?經(jīng)典函數(shù)可能是你的朋友。

在IIFEs中:this 的獨(dú)特角色

在我們深入了解IIFE中的 this 之前,讓我們澄清一下什么是IIFE。想象一下:你剛寫了一個(gè)函數(shù),而在你有機(jī)會坐下來欣賞你的作品之前,它已經(jīng)開始工作了。那就是IIFE!

IIFE(立即調(diào)用的函數(shù)表達(dá)式)就像那個(gè)朋友,一做完計(jì)劃就立刻行動。一旦定義,砰 —— 它就運(yùn)行了。而且,僅僅因?yàn)樗俣瓤觳⒉灰馕吨皇嵌嗖哦嗨嚨?。你可以用?biāo)準(zhǔn)函數(shù)、箭頭函數(shù),甚至加入一些 async-await 魔法來制作它。它們是這樣的:

// 經(jīng)典的方式
(function () {
  console.log(“這是一個(gè)IIFE!”);
})();

// 現(xiàn)代的、箭頭函數(shù)的變種
(() => {
  console.log(“箭頭函數(shù)IIFE正在行動!”);
})();

// 對于那些異步的冒險(xiǎn)
(async () => {
  await console.log(“Async-await與IIFE結(jié)合?是的!”);
})();

現(xiàn)在,進(jìn)入IIFEs中的 this及其獨(dú)特的舞蹈。當(dāng)你在IIFE內(nèi)部,你看著 this,你基本上在看全局對象。在瀏覽器世界中,那是我們的可靠朋友,window。

(function () {
    console.log(this);  // Outputs: Window {...} in browsers
})();

但這里有一個(gè)轉(zhuǎn)折:用神秘的 use strict 聲明開始你的IIFE,這就會有一個(gè)身份危機(jī)。而不是指向全局對象,它只會坐在那里,直到你用像 call 或 apply 這樣的方法給它一些目的。

(function () {
    'use strict';
    console.log(this);  // Outputs: undefined
})();

this 在事件處理程序中:與DOM交互

讓我們描繪一個(gè)畫面。你在一個(gè)網(wǎng)頁上,你最喜歡的歌正在播放,有一個(gè)按鈕在那里誘惑你點(diǎn)擊它。在你知道之前,JavaScript的魔法就活了起來,事情開始發(fā)生。但你有沒有想過內(nèi)部工作,使這些DOM元素跳舞的隱藏的木偶線?在這個(gè)魔法的核心是我們的好朋友:this。

主要吸引力:事件監(jiān)聽器

當(dāng)你將一個(gè)事件監(jiān)聽器綁定到一個(gè)DOM元素時(shí),你基本上是在耳語指示,告訴它,“嘿,當(dāng)有人與你互動時(shí),做這件事?!碑?dāng)那個(gè)“事情”涉及到使用 this 時(shí),它通常指的是事件被調(diào)用的元素。

const button = document.querySelector(‘#myButton’);
  button.addEventListener(‘click’, function() {
  console.log(this.innerHTML); // 輸出:#myButton內(nèi)的任何文本
});

在這種情況下,this 直接指向按鈕。就像按鈕說,“是的,我是被點(diǎn)擊的那個(gè)!”

情節(jié)轉(zhuǎn)折:箭頭函數(shù)

現(xiàn)在,如果你想在事件監(jiān)聽器中使用箭頭函數(shù),要小心。記住我們之前討論過箭頭函數(shù)從它們的周圍繼承 this 嗎?好吧,這意味著它們不像常規(guī)函數(shù)那樣綁定自己的 this。

button.addEventListener(‘click’, () => {
  console.log(this.innerHTML); // 哎呀!這不會按預(yù)期工作。
});

在這個(gè)設(shè)置中,this 不指向我們的按鈕。它可能指向窗口或另一個(gè)外部范圍,導(dǎo)致出現(xiàn)意外的結(jié)果。

動態(tài)事件:手動設(shè)置 this

有時(shí),你需要更多的控制,你可能想要指定 this 引用什么。對于這樣的情況,我們有 bind 來拯救!

function displayText() {
  console.log(this.innerHTML);
}
const boundFunction = displayText.bind(button);
button.addEventListener(‘click’, boundFunction);

在這里,無論 displayText 從哪里調(diào)用,使用 bind,我們都堅(jiān)定地告訴它考慮按鈕作為它的this。

“this”在構(gòu)造函數(shù)中:帶有上下文的建筑

想象一下你是一名建筑師。你手里有藍(lán)圖,材料準(zhǔn)備好了,每次你開始一個(gè)新項(xiàng)目,你都會建造結(jié)構(gòu),雖然基于類似的設(shè)計(jì),但都有自己獨(dú)特的性格和身份。在JavaScript中,當(dāng)我們談?wù)摌?gòu)造函數(shù)時(shí),我們實(shí)際上是在討論這些主要的藍(lán)圖,它們產(chǎn)生了獨(dú)特的對象。正如你可能猜到的,this 在個(gè)性化這些創(chuàng)作中起到了關(guān)鍵的作用。

基礎(chǔ):構(gòu)造函數(shù)

在其核心,構(gòu)造函數(shù)只是一個(gè)函數(shù)。但它是一個(gè)有抱負(fù)的函數(shù)。它夢想著創(chuàng)建多個(gè)對象,每個(gè)對象都是根據(jù)其框架塑造的,但持有自己的一套值。

function Car(make, model) {
  this.make = make;
  this.model = model;
}
const myCar = new Car(‘Toyota’, ‘Corolla’);
console.log(myCar.make); // 輸出:Toyota

注意我們?nèi)绾卧跇?gòu)造函數(shù)中使用 this?這是我們說的,“對于每一輛新車,將給定的制造和模型分配給這個(gè)特定的實(shí)例?!?/p>

旋轉(zhuǎn):原型方法

使用構(gòu)造函數(shù)的一個(gè)好處是能夠?qū)⒎椒ǜ郊拥剿鼈兊脑蜕?。這些方法可以通過 this 訪問實(shí)例特定的數(shù)據(jù),使它們相當(dāng)動態(tài)。

Car.prototype.displayInfo = function() {
  console.log(這輛車是一個(gè)${this.make} ${this.model}。);
};

myCar.displayInfo(); // 輸出:這輛車是一個(gè)Toyota Corolla。

在這里,displayInfo 方法使用 this 來訪問個(gè)別汽車的制造和模型,盡管該方法在實(shí)例之間是共享的。

小心:箭頭函數(shù)陷阱

快速提醒!記得我們之前關(guān)于箭頭函數(shù)的聊天嗎?即使在這里,它們與 this 的行為也是一致的。所以,如果你試圖用一個(gè)箭頭函數(shù)來制作一個(gè)構(gòu)造函數(shù)...好吧,期望一些怪癖。

const Gadget = (name) => {
this.name = name;
}
// const newGadget = new Gadget(‘Phone’); // 這會拋出一個(gè)錯(cuò)誤!

在上面的例子中,箭頭函數(shù)不創(chuàng)建自己的 this。相反,它從其封閉的范圍繼承它,當(dāng)用作構(gòu)造函數(shù)時(shí),可能會導(dǎo)致意外的結(jié)果。

與“this”有關(guān)的常見失誤:要注意什么

我們認(rèn)為我們已經(jīng)掌握了它的時(shí)候,它給了我們一個(gè)曲線球。這就像試圖抓住一個(gè)滑溜的魚;一旦你失去焦點(diǎn),它就消失了。但不要擔(dān)心,我們在這里幫助你避免一些常見的陷阱。

忘記“new”:當(dāng)你使用構(gòu)造函數(shù)創(chuàng)建一個(gè)新對象時(shí),確保使用new關(guān)鍵字。否則,this將指向全局對象,可能會導(dǎo)致意外的結(jié)果。

function Dog(name) {
this.name = name;
}
const myDog = Dog(‘Buddy’); // Oops! 我們忘記了‘new’
console.log(window.name); // 輸出:Buddy

事件監(jiān)聽器和回調(diào):當(dāng)你在事件監(jiān)聽器或回調(diào)函數(shù)中使用this時(shí),確保你知道它引用的是什么。如果需要,使用bind或箭頭函數(shù)來確保正確的上下文。

構(gòu)造函數(shù)和箭頭函數(shù):如前所述,箭頭函數(shù)不綁定自己的 this。嘗試使用它們作為構(gòu)造函數(shù)可能會導(dǎo)致錯(cuò)誤。

  1. 方法和對象字面量:當(dāng)你在對象字面量中定義方法時(shí),如果你使用箭頭函數(shù),this將不會指向該對象。確保使用常規(guī)函數(shù)語法。
const person = {
  name: ‘Ella’,
  greet: () => {
    console.log(‘Hello, ‘ + this.name); // Oops! 這不會按預(yù)期工作。
  }
};
person.greet(); // 輸出:Hello, undefined

動態(tài)方法:當(dāng)你動態(tài)地添加方法到一個(gè)對象時(shí),確保你知道this引用的是什么。如果需要,使用bind來確保正確的上下文。

const cat = {
  name: ‘Whiskers’
};
function purr() {
  console.log(this.name + ‘ is purring...’);
}
cat.purr = purr;
cat.purr(); // 輸出:Whiskers is purring...

但如果我們這樣做:

const purring = cat.purr;
purring(); // Oops! 這不會按預(yù)期工作。

總結(jié):“this”之旅的終點(diǎn)

我們已經(jīng)走過了一段漫長的旅程,探索了JavaScript中 this 關(guān)鍵字的各個(gè)方面。從全局上下文到構(gòu)造函數(shù),從事件處理程序到常規(guī)函數(shù),我們已經(jīng)涵蓋了你可能遇到的每一個(gè)場景。

現(xiàn)在,你已經(jīng)武裝了自己,準(zhǔn)備好在你的代碼中恰當(dāng)?shù)厥褂?nbsp;this。無論你是在創(chuàng)建一個(gè)小型腳本還是一個(gè)龐大的Web應(yīng)用程序,你都知道如何導(dǎo)航 this 的變化多端的行為。

但請記住,學(xué)習(xí)是一個(gè)持續(xù)的過程。隨著你繼續(xù)編寫更多的JavaScript代碼,你可能會遇到新的挑戰(zhàn)和情境。但現(xiàn)在,你已經(jīng)有了一個(gè)堅(jiān)實(shí)的基礎(chǔ),可以幫助你在遇到困難時(shí)找到正確的方向。

責(zé)任編輯:姜華 來源: 大遷世界
相關(guān)推薦

2009-12-03 09:00:18

PHP分頁函數(shù)

2018-04-08 09:07:58

2009-10-12 14:06:05

U盤中毒

2022-01-17 09:58:29

自動化訪問權(quán)限CIO

2021-03-07 08:30:17

Github報(bào)錯(cuò)下載資源庫

2011-08-11 13:11:24

準(zhǔn)入控制

2023-10-18 10:42:44

WOT大會架構(gòu)架構(gòu)演進(jìn)

2023-10-25 14:47:08

架構(gòu)設(shè)計(jì)人工智能

2021-12-07 07:58:33

個(gè)人圖床工具

2016-10-18 13:58:15

2017-08-14 15:27:23

安卓單元測試代碼測試

2023-11-13 10:55:09

MySQL數(shù)據(jù)庫

2022-01-05 15:05:21

互聯(lián)網(wǎng)跳槽大廠

2023-08-08 10:15:18

2021-12-03 12:15:01

QT中文亂碼Windows

2022-04-15 08:07:21

ReactDiff算法

2023-02-24 12:52:11

智慧城市LoRaWAN

2019-12-30 15:42:07

光標(biāo)Windows 10黑屏

2009-09-18 16:23:35

CCIE認(rèn)證

2022-04-12 07:48:57

云技術(shù)SDN網(wǎng)絡(luò)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號