前置:重要事情說(shuō)三遍:執(zhí)行上下文和作用域不一樣!不一樣!不一樣!
1、執(zhí)行上下文和作用域之間最大的區(qū)別是:
執(zhí)行上下文在運(yùn)行時(shí)確定,隨時(shí)可能改變;作用域在定義時(shí)確定,永遠(yuǎn)不會(huì)改變。
2、每個(gè)執(zhí)行上下文都有三個(gè)重要的屬性,變量對(duì)象(Variable object,VO),作用域鏈(Scope chain)和this,當(dāng)然還有一些附加的屬性。
實(shí)例、
? ?var a=1;//全局作用域? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ?function fn1(){
? ?var a=2; //fn1作用域
? ? }
?this.a=1;//全局執(zhí)行上下文 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?function fn1(){
this.a=2; //fn1執(zhí)行上下文
}
var obj=new fn1();
一、執(zhí)行上下文
綜述:每次當(dāng)控制器轉(zhuǎn)到可執(zhí)行代碼的時(shí)候,就會(huì)進(jìn)入一個(gè)執(zhí)行上下文。執(zhí)行上下文可以理解為當(dāng)前代碼的執(zhí)行環(huán)境,它會(huì)形成一個(gè)作用域。JavaScript中的運(yùn)行環(huán)境大概包括三種情況。
1、全局環(huán)境:JavaScript代碼運(yùn)行起來(lái)會(huì)首先進(jìn)入該環(huán)境
2、函數(shù)環(huán)境:當(dāng)函數(shù)被調(diào)用執(zhí)行時(shí),會(huì)進(jìn)入當(dāng)前函數(shù)中執(zhí)行代碼
3、eval
在一個(gè)JavaScript程序中,必定會(huì)產(chǎn)生多個(gè)執(zhí)行上下文,JavaScript引擎會(huì)以堆棧的方式來(lái)處理它們。棧底永遠(yuǎn)都是全局上下文,而棧頂就是當(dāng)前正在執(zhí)行的上下文。
當(dāng)代碼在執(zhí)行過(guò)程中,遇到以上三種情況,都會(huì)生成一個(gè)執(zhí)行上下文,放入棧中,而處于棧頂?shù)纳舷挛膱?zhí)行完畢之后,就會(huì)自動(dòng)出棧。
(1)變量對(duì)象VO和活動(dòng)對(duì)象AO
變量對(duì)象VO是與執(zhí)行上下文相關(guān)的特殊對(duì)象,用來(lái)存儲(chǔ)上下文的函數(shù)聲明,函數(shù)形參和變量。在global全局上下文中,變量對(duì)象也是全局對(duì)象自身;在函數(shù)執(zhí)行上下文中,VO是不能直接訪問(wèn)的,此時(shí)由活動(dòng)對(duì)象(activation object,縮寫(xiě)為AO)扮演VO的角色。
變量對(duì)象VO存儲(chǔ)上下文中聲明的以下內(nèi)容
{
}
二、this
this代表了當(dāng)前對(duì)象的一個(gè)引用。
1、this指代全局
var name ="global this";
functionglobalTest() {
console.log(this.name);?
?}?
?globalTest();//global this
2、this指代構(gòu)造函數(shù)
var name ="global name";
function showName() {? ?//構(gòu)造函數(shù)
this.name ="showName function";?
?}
var obj =new showName();
console.log(obj.name);? //showName?
functionconsole.log(name);? //global name
3、指向某個(gè)對(duì)象
如果函數(shù)作為對(duì)象的方法調(diào)用,this指向的是這個(gè)上級(jí)對(duì)象,即調(diào)用方法的對(duì)象
function? showName() {? ?//普通函數(shù)
console.log(this.name);?
?}
var obj = {};?
?obj.name ="ooo";?
?obj.show = showName;?
?obj.show();? //ooo
4、apply/call調(diào)用時(shí)的this
apply和call都是為了改變函數(shù)體內(nèi)部的this指向。
call(thisObj,Object)? ?;apply(thisObj,[argArray])
var value ="Global value";
functionFunA() {
this.value ="AAA";?
?}
functionFunB()?{
console.log(this.value);
?}?
?FunB();? ? ? ? ?//Global value 因?yàn)槭窃谌种姓{(diào)用的FunB(),this.value指向全局的value FunB.call(window);? ? ? ? //Global value,this指向window對(duì)象,因此this.value指向全局的value FunB.call(new FunA());? ? ? ? ?//AAA, this指向參數(shù)new FunA(),即FunA對(duì)象 FunB.apply(window);? ? ? ? ? ?//Global value FunB.apply(new FunA());//AAA
三、作用域
首先,js只有函數(shù)作用域(function-based),沒(méi)有塊級(jí)作用域,也就是只有函數(shù)會(huì)有自己的作用域,其他都沒(méi)有。
接著,作用域分為全局作用域與局部作用域。
全局作用域中的對(duì)象可以在代碼的任何地方訪問(wèn),一般來(lái)說(shuō),下面情況的對(duì)象會(huì)在全局作用域中:
最外層函數(shù)和在最外層函數(shù)外面定義的變量
沒(méi)有通過(guò)關(guān)鍵字"var"聲明的變量
瀏覽器中,window對(duì)象的屬性
局部作用域又被稱(chēng)為函數(shù)作用域(Function scope),所有的變量和函數(shù)只能在作用域內(nèi)部使用。
參考:https://www.cnblogs.com/nanchen/p/6055016.html
? ? ? ? ? https://www.cnblogs.com/lsgxeva/p/7975669.html
? ? ? ? ? http://www.itdecent.cn/p/edb2be5866eb
? ? ? ? ?https://blog.csdn.net/github_34514750/article/details/52901781