當前位置:首頁 » 網頁前端 » web調用堆棧
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

web調用堆棧

發布時間: 2022-09-12 21:45:37

㈠ Web前端工程師這些JavaScript的問題你會嗎

今天小編要跟大家分享的文章是關於Web前端工程師這些JavaScript的問題你會嗎。JavaScript是一種有趣的語言,我們都喜歡它,因為它的性質。瀏覽器是JavaScript的主要運行的地方,兩者在我們的服務中協同工作。JS有一些概念,人們往往會對它掉以輕心,有時可能會忽略不計。原型、閉包和事件循環等概念仍然是大多數JS開發人員繞道而行的晦澀領域之一。正如我們所知,無知是一件危險的事情,它可能會導致錯誤。


接下來,來看看幾個問題,你也可以試試想想,然後作答。


問題1:瀏覽器控制台上會列印什麼?vara=10;

functionfoo(){

console.log(a);//??

vara=20;

}

foo();

問題2:如果我們使用let或const代替var,輸出是否相同vara=10;

functionfoo(){

console.log(a);//??

leta=20;

}

foo();

問題3:"newArray"中有哪些元素?vararray=[];

for(vari=0;i<3;i++){

array.push(()=>i);

}

varnewArray=array.map(el=>el());

console.log(newArray);//??

問題4:如果我們在瀏覽器控制台中運行'foo'函數,是否會導致堆棧溢出錯誤?functionfoo(){

setTimeout(foo,0);//是否存在堆棧溢出錯誤?

};

問題5:如果在控制台中運行以下函數,頁面(選項卡)的UI是否仍然響應functionfoo(){

returnPromise.resolve().then(foo);

};

問題6:我們能否以某種方式為下面的語句使用展開運算而不導致類型錯誤varobj={x:1,y:2,z:3};

[...obj];//TypeError

問題7:運行以下代碼片段時,控制台上會列印什麼?

varobj={a:1,b:2};

Object.setPrototypeOf(obj,{c:3});

Object.defineProperty(obj,'d',{value:4,enumerable:false});

//-inloop?

for(letpropinobj){

console.log(prop);

}

問題8:xGetter()會列印什麼值?

varx=10;

varfoo={

x:90,

getX:function(){

returnthis.x;

}

};

foo.getX();//prints90

varxGetter=foo.getX;

xGetter();//prints??

答案


現在,讓我們從頭到尾回答每個問題。我將給您一個簡短的解釋,同時試圖揭開這些行為的神秘面紗,並提供一些參考資料。


問題1:undefined


解析:


使用var關鍵字聲明的變數在JavaScript中會被提升,並在內存中分配值undefined。但初始化恰發生在你給變數賦值的地方。另外,var聲明的變數是函數作用域的,而let和const是塊作用域的。所以,這就是這個過程的樣子:


vara=10;//全局使用域


functionfoo(){


//vara的聲明將被提升到到函數的頂部。


//比如:vara


console.log(a);//列印undefined


//實際初始化值20隻發生在這里


vara=20;//localscope


}


問題2:ReferenceError:aundefined


解析:


let和const聲明可以讓變數在其作用域上受限於它所使用的塊、語句或表達式。與var不同的是,這些變數沒有被提升,並且有一個所謂的暫時死區(TDZ)。試圖訪問TDZ中的這些變數將引發ReferenceError,因為只有在執行到達聲明時才能訪問它們。


vara=10;//全局使用域


functionfoo(){//TDZ開始


//創建了未初始化的'a'


console.log(a);//ReferenceError


//TDZ結束,'a'僅在此處初始化,值為20


leta=20;


}


下表概述了與JavaScript中使用的不同關鍵字聲明的變數對應的提升行為和使用域:

問題3:[3,3,3]


解析:


在for循環的頭部聲明帶有var關鍵字的變數會為該變數創建單個綁定(存儲空間)。閱讀更多關於閉包的信息。讓我們再看一次for循環。


//誤解作用域:認為存在塊級作用域


vararray=[];


for(vari=0;i<3;i++){


//三個箭頭函數體中的每個`'i'`都指向相同的綁定,


//這就是為什麼它們在循環結束時返回相同的值Ɖ'。


array.push(()=>i);


}


varnewArray=array.map(el=>el());


console.log(newArray);//[3,3,3]


如果使用let聲明一個具有塊級作用域的變數,則為每個循環迭代創建一個新的綁定。


//使用ES6塊級作用域


vararray=[];


for(leti=0;i<3;i++){


//這一次,每個'i'指的是一個新的的綁定,並保留當前的值。


//因此,每個箭頭函數返回一個不同的值。


array.push(()=>i);


}


varnewArray=array.map(el=>el());


console.log(newArray);//[0,1,2]


解決這個問題的另一種方法是使用閉包。


letarray=[];


for(vari=0;i<3;i++){


array[i]=(function(x){


returnfunction(){


returnx;


};


})(i);


}


constnewArray=array.map(el=>el());


console.log(newArray);//[0,1,2]


問題4:不會溢出


解析:


JavaScript並發模型基於「事件循環」。當我們說「瀏覽器是JS的家」時我真正的意思是瀏覽器提供運行時環境來執行我們的JS代碼。


瀏覽器的主要組件包括調用堆棧,事件循環,任務隊列和Web
API。像setTimeout,setInterval和Promise這樣的全局函數不是JavaScript的一部分,而是Web
API的一部分。JavaScript環境的可視化形式如下所示:

JS調用棧是後進先出(LIFO)的。引擎每次從堆棧中取出一個函數,然後從上到下依次運行代碼。每當它遇到一些非同步代碼,如setTimeout,它就把它交給Web
API(箭頭1)。因此,每當事件被觸發時,callback都會被發送到任務隊列(箭頭2)。


事件循環(Eventloop)不斷地監視任務隊列(TaskQueue),並按它們排隊的順序一次處理一個回調。每當調用堆棧(call
stack)為空時,Eventloop獲取回調並將其放入堆棧(stack
)(箭頭3)中進行處理。請記住,如果調用堆棧不是空的,則事件循環不會將任何回調推入堆棧。


現在,有了這些知識,讓我們來回答前面提到的問題:


步驟


1.調用foo()會將foo函數放入調用堆棧(callstack)。


2.在處理內部代碼時,JS引擎遇到setTimeout。


3.然後將foo回調函數傳遞給WebAPIs(箭頭1)並從函數返回,調用堆棧再次為空


4.計時器被設置為0,因此foo將被發送到任務隊列(箭頭2)。


5.由於調用堆棧是空的,事件循環將選擇foo回調並將其推入調用堆棧進行處理。


6.進程再次重復,堆棧不會溢出。


問題5:不會響應


解析:


大多數時候,開發人員假設在事件循環loop>圖中只有一個任務隊列。但事實並非如此,我們可以有多個任務隊列。由瀏覽器選擇其中的一個隊列並在該隊列中處理回調


在底層來看,JavaScript中有宏任務和微任務。setTimeout回調是宏任務,而Promise回調是微任務。


主要的區別在於他們的執行方式。宏任務在單個循環周期中一次一個地推入堆棧,但是微任務隊列總是在執行後返回到事件循環之前清空。因此,如果你以處理條目的速度向這個隊列添加條目,那麼你就永遠在處理微任務。只有當微任務隊列為空時,事件循環才會重新渲染頁面、


現在,當你在控制台中運行以下代碼段


functionfoo(){


returnPromise.resolve().then(foo);


};


每次調用'foo'都會繼續在微任務隊列上添加另一個'foo'回調,因此事件循環無法繼續處理其他事件(滾動,單擊等),直到該隊列完全清空為止。因此,它會阻止渲染。


問題6:會導致TypeError錯誤


解析:


展開語法和for-of語句遍歷iterable對象定義要遍歷的數據。Array或Map
是具有默認迭代行為的內置迭代器。對象不是可迭代的,但是可以通過使用iterable和iterator協議使它們可迭代。


在Mozilla文檔中,如果一個對象實現了@@iterator方法,那麼它就是可迭代的,這意味著這個對象(或者它原型鏈上的一個對象)必須有一個帶有@@iterator鍵的屬性,這個鍵可以通過常量Symbol.iterator獲得。


上述語句可能看起來有點冗長,但是下面的示例將更有意義:varobj={x:1,y:2,z:3};

obj[Symbol.iterator]=function(){

//iterator是一個具有next方法的對象,

//它的返回至少有一個對象

//兩個屬性:value&done。

//返回一個iterator對象

return{

ext:function(){

if(this._countDown===3){

constlastValue=this._countDown;

return{value:this._countDown,done:true};

}

this._countDown=this._countDown+1;

return{value:this._countDown,done:false};

},

_countDown:0

};

};

[...obj];//列印[1,2,3]

還可以使用generator函數來定製對象的迭代行為:

varobj={x:1,y:2,z:3}

obj[Symbol.iterator]=function*(){

yield1;

yield2;

yield3;

}

[...obj];//列印[1,2,3]

問題7:a,b,c


解析:


for-in循環遍歷對象本身的可枚舉屬性以及對象從其原型繼承的屬性。可枚舉屬性是可以在for-in循環期間包含和訪問的屬性。varobj={a:1,b:2};

vardescriptor=Object.getOwnPropertyDescriptor(obj,"a");

console.log(descriptor.enumerable);//true

console.log(descriptor);

//{value:1,writable:true,enumerable:true,configurable:true}

現在你已經掌握了這些知識,應該很容易理解為什麼我們的代碼要列印這些特定的屬性


varobj={a:1,b:2};//a,b都是enumerables屬性


//將{c:3}設置為'obj'的原型,並且我們知道


//for-in循環也迭代obj繼承的屬性


//從它的原型,'c'也可以被訪問。


Object.setPrototypeOf(obj,{c:3});


//我們在'obj'中定義了另外一個屬性'd',但是


//將'enumerable'設置為false。這意味著'd'將被忽略。


Object.defineProperty(obj,"d",{value:4,enumerable:false});


for(letpropinobj){


console.log(prop);


}


//列印


//a


//b


//c


問題8:10


解析:


在全局范圍內初始化x時,它成為window對象的屬性(不是嚴格的模式)。看看下面的代碼:varx=10;//globalscope

varfoo={

x:90,

getX:function(){

returnthis.x;

}

};

foo.getX();//prints90

letxGetter=foo.getX;

xGetter();//prints10

咱們可以斷言:


window.x===10;//true


this
始終指向調用方法的對象。因此,在foo.getx()的例子中,它指向foo對象,返回90的值。而在xGetter()的情況下,this指向window對象,返回
window中的x的值,即10。


要獲取foo.x的值,可以通過使用Function.prototype.bind將this的值綁定到foo對象來創建新函數。


letgetFooX=foo.getX.bind(foo);


getFooX();//90


就這樣!如果你的所有答案都正確,那麼幹得漂亮。咱們都是通過犯錯來學習的。這一切都是為了了解背後的「原因」。


以上就是小編今天為大家分享的一些關於JavaScript的相關問題,想要了解更多Web相關知識記得關注北大青鳥Web培訓官網。最後祝願小夥伴們工作順利,成為一名優秀的Web前端工程師!


英文:AmandeepSingh,譯文:前端小智


來源:#/post/5d2d146bf265da1b9163c5c9


㈡ win10打開網頁就提示堆棧溢出怎麼解決

電腦中無法打開網頁並提示堆棧溢出的原因分析及解決方法 1、函數調用層次過深,每調用一次,函數的參數、局部變數等信息就壓一次棧; 2、局部靜態變數體積太大。 解決方法: 1、按win+r打開運行,輸入cmd,並按回車; 2、打開命令提示符後,分別輸入並執行以下命令: regsvr32 atl.dll regsvr32 shdocvw.dll regsvr32 urlmon.dll regsvr32 browseui.dll regsvr32 oleaut32.dll regsvr32 shell32.dll regsvr32 jscript.dll regsvr32 vbscript.dll regsvr32 mshtmled.dll regsvr32 CLBCATQ.DLL regsvr32 cscui.dll regsvr32 MLANG.dll regsvr32 stobject.dll regsvr32 WINHTTP.dll regsvr32 msxml3.dll regsvr32 query.dll regsvr32 jscript9.dll regsvr32 hlink.dll

㈢ 在web應用系統開發框架中,什麼是全堆棧框架

這種概念全然不用去理會它,完全噱頭而言,一個前端的開發能跟堆棧扯上個毛線關系,
堆棧的概念與應用都是涉及到內存的操作,特別是匯編中尤為重要,與前端沒一毛錢關系,前端的框架99%用的都是JS,封裝一下就成了不同版本的了,頂多頂多用了下,後進先出,先進先出這些堆棧的概念而已,就妄稱而已

㈣ 執行當前 Web 請求期間生成了未處理的異常.可以使用下面的異常堆棧跟蹤信息確定

找你代碼中的調用
String.SubString
方法的地方
=============================
System.String.Substring(Int32
startIndex)
+17
=============================
一般來說,你在用這個方法截取子字元串時,所指定的
開始位置或結束位置已經超出或低於(startIndex
=
-1)它的長度。

㈤ c# 來自網頁的提示:堆棧溢出 webbrowser

部分代碼如下:
在窗口及WebBrowser創建完以後,寫此代碼:
WebBrowser.OnNewWindow2:=IE1NewWindow2;
給主窗口創建一個方法:
procere TBrowForm.IE1NewWindow2(Sender: TObject; var ppDisp: IDispatch;var Cancel: WordBool);
Var NewForm:TBrowForm;
begin
try
NewForm :=TPopBrowerForm.Create(application);
NewForm.WebBrowser.OnNewWindow2 :=IE1NewWindow2;//如果在窗口的Oncreate事件
//有此代碼,此處就可以省略
ppDisp := NewForm.WebBrowser.Application;
NewForm.Show;
Cancel:=false;
except
end;
end;

㈥ vs2008 打開窗體時顯示調用堆棧 這是什麼原因啊

窗體裡面某個控制項在設計視圖中載入的時候出錯了 根據提示信息排查一下

㈦ WebDev.WebServer40.exe 停止工作.WebDev.WebServer40.exe 中發生未處理的Microsoft .NETFramework異常,

這個問題,它說明你的站點裡面存有致命錯誤。經過斷點調試,發現了如下問題:


反思:雖然這是個馬虎引起的問題,但也確實說明一個該注意的問題。就是運用分層編程時,同一條線上各層之間的方法名稱最好別完全相同,應該加一些前綴或後綴標識會更加安全和規范。