- 說(shuō)明:該文屬于 大前端全棧架構(gòu)白寶書(shū)專欄,目前階段免費(fèi),如需要項(xiàng)目實(shí)戰(zhàn)或者是體系化資源,文末名片加V!
- 作者:哈哥撩編程,十余年工作經(jīng)驗(yàn), 從事過(guò)全棧研發(fā)、產(chǎn)品經(jīng)理等工作,目前在公司擔(dān)任研發(fā)部門(mén)CTO。
- 榮譽(yù):2022年度博客之星Top4、2023年度超級(jí)個(gè)體得主、谷歌與亞馬遜開(kāi)發(fā)者大會(huì)特約speaker、全棧領(lǐng)域優(yōu)質(zhì)創(chuàng)作者。
- ?? 白寶書(shū)系列
- ?? 啟示錄 - 攻城獅的自我修養(yǎng)
- ?? Python全棧白寶書(shū)
- ?? ChatGPT實(shí)踐指南白寶書(shū)
- ?? 產(chǎn)品思維訓(xùn)練白寶書(shū)
- ?? 全域運(yùn)營(yíng)實(shí)戰(zhàn)白寶書(shū)
- ?? 大前端全棧架構(gòu)白寶書(shū)

?認(rèn)識(shí)上下文
小時(shí)候?qū)W習(xí)做閱讀理解時(shí),老師經(jīng)常會(huì)強(qiáng)調(diào),注意上下文。比如有一個(gè)句子:這是一個(gè)好習(xí)慣,我們應(yīng)該堅(jiān)持。如果不結(jié)合上文的意思,根本不知道“這”指的是什么。如果結(jié)合上文,比如,隨手關(guān)燈,這是一個(gè)好習(xí)慣,我們應(yīng)該堅(jiān)持。我們就知道此時(shí)的“這”指的是“隨手關(guān)燈”,那么整個(gè)句子的語(yǔ)義就好理解了。
在函數(shù)中,也經(jīng)常需要結(jié)合上下文來(lái)編寫(xiě)和理解代碼。
函數(shù)中可以使用
this
,表示函數(shù)的上下文
與中文中的“這”類似,函數(shù)中的this具體指代什么必須
通過(guò)調(diào)用函數(shù)時(shí)的“前言后語(yǔ)”來(lái)判斷
下面看一個(gè)例子:
- 第一種調(diào)用方式:對(duì)象打點(diǎn)調(diào)用自己的方法:
var xiaomumu = {
name: '小沐沐',
age: 2,
sex: '男',
hobbies: ['秋千', '滑梯'],
sayHello: function () {
console.log('Hello, 我是' + this.name + ',我今年' + this.age + '歲了');
}
};
xiaomumu.sayHello(); // Hello, 我是小沐沐,我今年2歲了
- 第二種調(diào)用方式:對(duì)象的方法被賦值給一個(gè)全局變量,全局變量加圓括號(hào)調(diào)用:
var xiaomumu = {
name: '小沐沐',
age: 2,
sex: '男',
hobbies: ['秋千', '滑梯'],
sayHello: function () {
console.log('Hello, 我是' + this.name + '我今年' + this.age + '歲了');
}
};
var sayHello = xiaomumu.sayHello; // 將這個(gè)屬性存入了一個(gè)全局變量(變量的名稱可以和屬性名相同,方便理解)
sayHello(); //Hello, 我是undefined我今年undefined歲了
這兩種調(diào)用方式,this指代的對(duì)象分別是:
- 第一種,對(duì)象打點(diǎn)調(diào)用方式,函數(shù)中的this指代這個(gè)打點(diǎn)的對(duì)象
- 第二種,圓括號(hào)直接調(diào)用函數(shù),函數(shù)中的this指代window對(duì)象
其實(shí)可以這么理解,第二種中,因?yàn)槿肿兞慷际莣indow的屬性,相當(dāng)于用window.sayHello()的方式調(diào)用了這個(gè)函數(shù)。所以this指代的就是window對(duì)象。
所以我們一定要記?。?mark>只有函數(shù)被調(diào)用時(shí),我們才能知道this指代的是什么函數(shù)的上下文由函數(shù)的調(diào)用方式
決定,同一個(gè)函數(shù),用不同的形式調(diào)用它,則函數(shù)的上下文不同
?上下文規(guī)則
我們知道,不同的調(diào)用方式,函數(shù)的上下文就不同,那么我們?cè)趺慈ヅ袛嗪瘮?shù)的上下文呢?這就要學(xué)習(xí)各種不同的函數(shù)調(diào)用規(guī)則。
??上下文規(guī)則1
規(guī)則1:對(duì)象打點(diǎn)調(diào)用它的方法函數(shù),則函數(shù)的上下文是這個(gè)打點(diǎn)的對(duì)象
下面看幾個(gè)案例,練習(xí)一下:
題目一: 下面代碼的運(yùn)行結(jié)果是什么?
function fn() {
console.log(this.a + this.b);
}
var obj = {
a: 11,
b: 22,
fn: fn
};
obj.fn();
運(yùn)行結(jié)果:33
題目二: 下面代碼的運(yùn)行結(jié)果是什么?
var obj1 = {
a: 1,
b: 2,
fn: function () {
console.log(this.a + this.b);
}
};
var obj2 = {
a: 3,
b: 4,
fn: obj1.fn
};
obj2.fn();
運(yùn)行結(jié)果: 7
一定要記住,誰(shuí)打點(diǎn)調(diào)用函數(shù),函數(shù)中的this指代的就是誰(shuí)
題目三: 下面代碼的運(yùn)行結(jié)果是什么?
function outer() {
var a = 11;
var b = 22;
return {
a: 33,
b: 44,
fn: function () {
console.log(this.a + this.b);
}
};
}
outer().fn();
運(yùn)行結(jié)果:77
上面的代碼中,outer()返回了一個(gè)對(duì)象,相當(dāng)于還是一個(gè)對(duì)象打點(diǎn)調(diào)用了函數(shù),所以適用于對(duì)象打點(diǎn)調(diào)用函數(shù),函數(shù)的上下文就是這個(gè)對(duì)象的規(guī)則。
題目四: 下面代碼的運(yùn)行結(jié)果是什么?
function fun() {
console.log(this.a + this.b);
}
var obj = {
a: 1,
b: 2,
c: [{
a: 3,
b: 4,
c: fun
}]
};
var a = 5;
obj.c[0].c();
運(yùn)行結(jié)果:7
上面的代碼中,最終調(diào)用函數(shù)的是obj.c[0]
這個(gè)對(duì)象,所以函數(shù)中的this指代的就是obj.c[0]
??上下文規(guī)則2
規(guī)則2:圓括號(hào)直接調(diào)用函數(shù),則函數(shù)的上下文是window對(duì)象
題目一: 下面代碼的運(yùn)行結(jié)果是什么?
var obj1 = {
a: 1,
b: 2,
fn: function () {
console.log(this.a + this.b);
}
};
var a = 3;
var b = 4;
var fn = obj1.fn;
fn();
運(yùn)行結(jié)果:7
題目二: 下面代碼的運(yùn)行結(jié)果是什么?
function fun() {
return this.a + this.b;
}
var a = 1;
var b = 2;
var obj = {
a: 3,
b: fun(),
fun: fun
};
var result = obj.fun();
console.log(result);
運(yùn)行結(jié)果:6,題目分析如下:
這是一道非常正規(guī)的面試題,大家一定要學(xué)會(huì)分析其中的代碼邏輯
??上下文規(guī)則3
規(guī)則3:數(shù)組(類數(shù)組對(duì)象)枚舉出函數(shù)進(jìn)行調(diào)用,上下文是這個(gè)數(shù)組(類數(shù)組對(duì)象)
數(shù)組[下標(biāo)]()
類數(shù)組對(duì)象:所有鍵名為自然數(shù)序列(從0開(kāi)始),且有l(wèi)ength屬性的對(duì)象
arguments對(duì)象是最常見(jiàn)的類數(shù)組對(duì)象,它是函數(shù)的實(shí)參列表
題目一: 下面代碼的運(yùn)行結(jié)果是什么?
var arr = ['A', 'B', 'C', function () {
console.log(this[0]);
}];
arr[3]();
運(yùn)行結(jié)果: “A”
上面的代碼適用規(guī)則3,this指代的就是arr這個(gè)數(shù)組
題目二: 下面代碼的運(yùn)行結(jié)果是什么?
function fun() {
arguments[3]();
}
fun('A', 'B', 'C', function () {
console.log(this[1]);
});
運(yùn)行結(jié)果:“B”。我們可以打印一下arguments,可以看到arguments是一個(gè)類數(shù)組對(duì)象,里面其實(shí)就是fun()函數(shù)被調(diào)用時(shí),傳入的實(shí)參:
??上下文規(guī)則4
規(guī)則4:IIFE中的函數(shù),上下文是window對(duì)象。(IIFE在以前的文中提到過(guò),是立即可執(zhí)行函數(shù)。)
(function (){
? //立即可執(zhí)行函數(shù)
})()
題目一: 下面代碼的運(yùn)行結(jié)果是什么?
var a = 1;
var obj = {
a: 2,
fun: (function () {
var a = this.a;
return function () {
console.log(a + this.a);
}
})()
};
obj.fun();
運(yùn)行結(jié)果:3。這是一個(gè)大廠的面試題,題目分析如下:
??上下文規(guī)則5
規(guī)則5:定時(shí)器、延時(shí)器調(diào)用函數(shù),上下文是window對(duì)象
setInterval(函數(shù),時(shí)間);
setTimeout(函數(shù),時(shí)間);
題目一: 下面代碼的運(yùn)行結(jié)果是什么?
var obj = {
a: 1,
b: 2,
fun: function () {
console.log(this.a + this.b);
}
};
var a = 3;
var b = 4;
setTimeout(obj.fun, 2000);
運(yùn)行結(jié)果:7。因?yàn)橛醚訒r(shí)器調(diào)用的函數(shù),適用規(guī)則5,this指代的就是window對(duì)象,即this.a
和this.b
的值分別是3,4
題目二: 下面代碼的運(yùn)行結(jié)果是什么?
var obj = {
a: 1,
b: 2,
fun: function () {
console.log(this.a + this.b);
}
};
var a = 3;
var b = 4;
setTimeout(function () {
obj.fun(); //適用規(guī)則1
}, 2000);
運(yùn)行結(jié)果:3。這里要注意,延時(shí)器不是直接調(diào)用obj里的fun函數(shù),而是一個(gè)匿名函數(shù),這個(gè)匿名函數(shù)里又調(diào)用了obj.fun(),所以此時(shí)的this應(yīng)指代的是obj這個(gè)對(duì)象,即this.a
和this.b
的值分別是1,2
??上下文規(guī)則6
規(guī)則6:事件處理函數(shù)的上下文是綁定事件的DOM元素
DOM元素.onclick = function() {
};
題目一: 點(diǎn)擊哪個(gè)盒子,哪個(gè)盒子就變紅,要求使用同一個(gè)事件處理函數(shù)實(shí)現(xiàn)(不能用事件委托)
<html lang="en">
<head>
<style>
div {
width: 200px;
height: 200px;
float: left;
border: 1px solid #000;
margin-right: 10px;
}
</style>
</head>
<body>
<div id="box1"></div>
<div id="box2"></div>
<div id="box3"></div>
<script>
function setColorToRed(o) {
this.style.backgroundColor = 'red';
}
var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
var box3 = document.getElementById('box3');
box1.onclick = function () {
setColorToRed(box1);
}
box1.onclick = setColorToRed;
box2.onclick = setColorToRed;
box3.onclick = setColorToRed;
</script>
</body>
</html>
運(yùn)行結(jié)果:點(diǎn)擊哪個(gè)盒子,哪個(gè)盒子就變紅。這里的this指代的就是綁定事件的DOM元素;注意區(qū)分this和e.target的不同
題目二: 點(diǎn)擊哪個(gè)盒子,哪個(gè)盒子在2000毫秒后就變紅,要求使用同一個(gè)事件處理函數(shù)實(shí)現(xiàn)(不能用事件委托)
題目分析:
這個(gè)題目其實(shí)就是上個(gè)題目+一個(gè)延時(shí)器,但是需要注意的是加上延時(shí)器后,this指代的可能會(huì)不一樣,所以需要使用一個(gè)程序猿非常常用的技術(shù):備份上下文文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-755339.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>Document</title>
<style>
div {
width: 200px;
height: 200px;
float: left;
border: 1px solid #000;
margin-right: 10px;
}
</style>
</head>
<body>
<div id="box1"></div>
<div id="box2"></div>
<div id="box3"></div>
<script>
function setColorToRed(o) {
//備份上下文
var self = this; // 通常使用self來(lái)備份上下文,也有使用that或_this的,這個(gè)技術(shù)非常的常用!
setTimeout(() => {
self.style.backgroundColor = 'red';
}, 2000);
}
var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
var box3 = document.getElementById('box3');
box1.onclick = function () {
setColorToRed(box1);
}
box1.onclick = setColorToRed;
box2.onclick = setColorToRed;
box3.onclick = setColorToRed;
</script>
</body>
</html>
注意:程序員在書(shū)寫(xiě)this的時(shí)候通常會(huì)看一下這個(gè)this到底指代什么,需不需要備份文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-755339.html
到了這里,關(guān)于〖大前端 - 基礎(chǔ)入門(mén)三大核心之JS篇(51)〗- 面向?qū)ο笾J(rèn)識(shí)上下文與上下文規(guī)則的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!