js的預編譯階段是代碼寫完後嗎
A. js代碼執行順序的問題
JS變數提升問題,顧名思義,就是把下面的東西提到上面。具體資料可以網路搜索,
vart=1;
functioncon(){
console.log(t);//在函數內部,有變數提升
vart=2;
console.log(t);
}
con();
變為如下:
vart=1;
functioncon(){
vart;
console.log(t);//在函數內部,有變數提升
t=2;
console.log(t);
}
con();
如果想要改變t變數的值,那麼在函數內部就不要定義x變數
vart=1;
functioncon(){
console.log(t);//1
t=2;
console.log(t);//2
}
con();
B. 一個前端 javascript的問題,有點迷,好像沒有問這種問題了,但是問了好多人都模糊其詞
1、在{}里的funcion也會提升,提升到全局和代碼塊頂部。並新建局部作用域。
2、當執行到function的聲明語句,會把聲明語句之前的值復制給全局。
3、之後的賦值全是在局部作用域中進行。
C. javascript的作用
JavaScript是一種屬於網路的腳本語言,已經被廣泛用於Web應用開發,常用來為網頁添加各式各樣的動態功能,為用戶提供更流暢美觀的瀏覽效果。通常JavaScript腳本是通過嵌入在HTML中來實現自身的功能的。[3]
是一種解釋性腳本語言(代碼不進行預編譯)。[4]
主要用來向HTML(標准通用標記語言下的一個應用)頁面添加交互行為。[4]
可以直接嵌入HTML頁面,但寫成單獨的js文件有利於結構和行為的分離。[4]
跨平台特性,在絕大多數瀏覽器的支持下,可以在多種平台下運行(如Windows、Linux、Mac、Android、iOS等)。
Javascript腳本語言同其他語言一樣,有它自身的基本數據類型,表達式和算術運算符及程序的基本程序框架。Javascript提供了四種基本的數據類型和兩種特殊數據類型用來處理數據和文字。而變數提供存放信息的地方,表達式則可以完成較復雜的信息處理。
JavaScript腳本語言具有以下特點:
(1)腳本語言。JavaScript是一種解釋型的腳本語言,C、C++等語言先編譯後執行,而JavaScript是在程序的運行過程中逐行進行解釋。
(2)基於對象。JavaScript是一種基於對象的腳本語言,它不僅可以創建對象,也能使用現有的對象。
(3)簡單。JavaScript語言中採用的是弱類型的變數類型,對使用的數據類型未做出嚴格的要求,是基於Java基本語句和控制的腳本語言,其設計簡單緊湊。
(4)動態性。JavaScript是一種採用事件驅動的腳本語言,它不需要經過Web伺服器就可以對用戶的輸入做出響應。在訪問一個網頁時,滑鼠在網頁中進行滑鼠點擊或上下移、窗口移動等操作JavaScript都可直接對這些事件給出相應的響應。
(5)跨平台性。JavaScript腳本語言不依賴於操作系統,僅需要瀏覽器的支持。因此一個JavaScript腳本在編寫後可以帶到任意機器上使用,前提上機器上的瀏覽器支 持JavaScript腳本語言,目前JavaScript已被大多數的瀏覽器所支持。[3]
不同於伺服器端腳本語言,例如PHP與ASP,JavaScript主要被作為客戶端腳本語言在用戶的瀏覽器上運行,不需要伺服器的支持。所以在早期程序員比較青睞於JavaScript以減少對伺服器的負擔,而與此同時也帶來另一個問題:安全性。
而隨著伺服器的強壯,雖然程序員更喜歡運行於服務端的腳本以保證安全,但JavaScript仍然以其跨平台、容易上手等優勢大行其道。同時,有些特殊功能(如AJAX)必須依賴Javascript在客戶端進行支持。隨著引擎如V8和框架如Node.js的發展,及其事件驅動及非同步IO等特性,JavaScript逐漸被用來編寫伺服器端程序。
D. 在JavaScript中「代碼執行不進行預編譯」這句話怎麼理解
編譯型語言可以看做出書
寫完了,出版,一起給用戶看
解釋型語言可以看做面談
對方說一句你聽一句
代碼執行不用編譯就是說,Javascript是讀一句執行一句的,所以不會先將所有的都編譯
E. js執行順序
你現在是先定義了函數a,然後定義了函數b,然後再去執行函數a
即使你把代碼改成這樣依舊能夠正常運行
a();
functiona(){
b();
}
functionb(){
console.log(111)
}
因為JS運行環境會把定義的代碼(變數/函數)提升到作用域的最前面
F. 如何確保JavaScript的執行順序
1.1
按HTML文檔流順序執行JavaScript代碼
首先,讀者應該清楚,HTML文檔在瀏覽器中的解析過程是這樣的:瀏覽器是按著文檔流從上到下逐步解析頁面結構和信息的。JavaScript代碼作為嵌入的腳本應該也算做HTML文檔的組成部分,所以JavaScript代碼在裝載時的執行順序也是根據腳本標簽<script>的出現順序來確定的。例如,瀏覽下面文檔頁面,你會看到代碼是從上到下逐步被解析的。
復制代碼
代碼如下:
<script>
alert("頂部腳本");
</script>
<html><head>
<script>
alert("頭部腳本");
</script>
<title></title>
</head>
<body>
<script>
alert("頁面腳本");
</script>
</body></html>
<script>
alert("底部腳本");
</script>
如果通過腳本標簽<script>的src屬性導入外部JavaScript文件腳本,那麼它也將按照其語句出現的順序來執行,而且執行過程是文檔裝載的一部分。不會因為是外部JavaScript文件而延期執行。例如,把上面文檔中的頭部和主體區域的腳本移到外部JavaScript文件中,然後通過src屬性導入。繼續預覽頁面文檔,你會看到相同的執行順序。
復制代碼
代碼如下:
<script>
alert("頂部腳本");
</script>
<html>
<head>
<script src="http://www.jb51.net/head.js"></script>
<title></title>
</head>
<body>
<script src="http://www.jb51.net/body.js"></script>
</body>
</html>
<script>
alert("底部腳本");
</script>
1.2 預編譯與執行順序的關系
在Javascript中,function才是Javascript的第一型。當我們寫下一段函數時,其實不過是建立了一個function類型的實體。
就像我們可以寫成這樣的形式一樣:
復制代碼
代碼如下:
functionHello()
{
alert("Hello");
}
Hello();
varHello = function()
{
alert("Hello");
}
Hello();
其實都是一樣的。 但是當我們對其中的函數進行修改時,會發現很奇怪的問題。
復制代碼
代碼如下:
<scripttype="text/javascript">
functionHello() {
alert("Hello");
}
Hello();
functionHello() {
alert("Hello World");
}
Hello();
</script>
我們會看到這樣的結果:連續輸出了兩次Hello
World。
而非我們想像中的Hello和Hello World。
這是因為Javascript並非完全的按順序解釋執行,而是在解釋之前會對Javascript進行一次「預編譯」,在預編譯的過程中,會把定義式的函數優先執行,也會把所有var變數創建,默認值為undefined,以提高程序的執行效率。
也就是說上面的一段代碼其實被JS引擎預編譯為這樣的形式:
復制代碼
代碼如下:
<scripttype="text/javascript">
varHello = function() {
alert("Hello");
}
Hello = function() {
alert("Hello World");
}
Hello();
Hello();
</script>
我們可以通過上面的代碼很清晰地看到,其實函數也是數據,也是變數,我們也可以對「函數「進行賦值(重賦值)。
當然,我們為了防止這樣的情況,也可以這樣:
復制代碼
代碼如下:
<scripttype="text/javascript">
functionHello() {
alert("Hello");
}
Hello();
</script>
<scripttype="text/javascript">
functionHello() {
alert("Hello World");
}
Hello();
</script>
這樣,程序被分成了兩段,JS引擎也就不會把他們放到一起了。
當JavaScript引擎解析腳本時,它會在預編譯期對所有聲明的變數和函數進行處理。
做如下處理:
1.
在執行前會進行類似「預編譯」的操作:首先會創建一個當前執行環境下的活動對象,並將那些用var申明的變數設置為活動對象的屬性,但是此時這些變數的賦值都是undefined,並將那些以function定義的函數也添加為活動對象的屬性,而且它們的值正是函數的定義。
2.
在解釋執行階段,遇到變數需要解析時,會首先從當前執行環境的活動對象中查找,如果沒有找到而且該執行環境的擁有者有prototype屬性時則會從prototype鏈中查找,否則將會按照作用域鏈查找。遇到var
a = ...這樣的語句時會給相應的變數進行賦值(注意:變數的賦值是在解釋執行階段完成的,如果在這之前使用變數,它的值會是undefined)
所以,就會出現當JavaScript解釋器執行下面腳本時不會報錯:
復制代碼
代碼如下:
alert(a); //
返回值undefined
var a =1;
alert(a); //
返回值1
由於變數聲明是在預編譯期被處理的,所以在執行期間對於所有代碼來說,都是可見的。但是,你也會看到,執行上面代碼,提示的值是undefined,而不是1。這是因為,變數初始化過程發生在執行期,而不是預編譯期。在執行期,JavaScript解釋器是按著代碼先後順序進行解析的,如果在前面代碼行中沒有為變數賦值,則JavaScript解釋器會使用默認值undefined。由於在第二行中為變數a賦值了,所以在第三行代碼中會提示變數a的值為1,而不是undefined。
同理,下面示例在函數聲明前調用函數也是合法的,並能夠被正確解析,所以返回值為1。
復制代碼
代碼如下:
f(); //
調用函數,返回值1
function f(){
alert(1);
}
但是,如果按下面方式定義函數,則JavaScript解釋器會提示語法錯誤。
復制代碼
代碼如下:
f(); //
調用函數,返回語法錯誤
var f = function(){
alert(1);
}
這是因為,上面示例中定義的函數僅作為值賦值給變數f,所以在預編譯期,JavaScript解釋器只能夠為聲明變數f進行處理,而對於變數f的值,只能等到執行期時按順序進行賦值,自然就會出現語法錯誤,提示找不到對象f。
再見一些例子:
復制代碼
代碼如下:
<script type="text/javascript">
/*在預編譯過程中func是window環境下的活動對象中的一個屬性,值是一個函數,覆蓋了undefined值*/
alert(func); //function func(){alert("hello!")}
var func = "this is a variable"
function func(){
alert("hello!")
}
/*在執行過程中遇到了var重新賦值為"this is a variable"*/
alert(func); //this is a variable
</script>
復制代碼
代碼如下:
<script type="text/javascript">
var name = "feng"; function func()
{
/*首先,在func環境內先把name賦值為undefined,然後在執行過程中先尋找func環境下的活動對象的name屬性,此時之前已經預編譯值為undefined,所以輸出是undefined,而不是feng*/
alert(name); //undefined var name = "JSF";
alert(name); //JSF
}
func();
alert(name);
//feng
</script>
雖然變數和函數聲明可以在文檔任意位置,但是良好的習慣應該是在所有JavaScript代碼之前聲明全局變數和函數,並對變數進行初始化賦值。在函數內部也是先聲明變數,然後再引用。
1.3 按塊執行JavaScript代碼
所謂代碼塊就是使用<script>標簽分隔的代碼段。例如,下面兩個<script>標簽分別代表兩個JavaScript代碼塊。
復制代碼
代碼如下:
<script>
// JavaScript代碼塊1
var a =1;
</script>
<script>
// JavaScript代碼塊2
function f(){
alert(1);
}
</script>
JavaScript解釋器在執行腳本時,是按塊來執行的。通俗地說,就是瀏覽器在解析HTML文檔流時,如果遇到一個<script>標簽,則JavaScript解釋器會等到這個代碼塊都載入完後,先對代碼塊進行預編譯,然後再執行。執行完畢後,瀏覽器會繼續解析下面的HTML文檔流,同時JavaScript解釋器也准備好處理下一個代碼塊。
由於JavaScript是按塊執行的,所以如果在一個JavaScript塊中調用後面塊中聲明的變數或函數就會提示語法錯誤。例如,當JavaScript解釋器執行下面代碼時就會提示語法錯誤,顯示變數a未定義,對象f找不到。
復制代碼
代碼如下:
<script>
// JavaScript代碼塊1
alert(a);
f();
</script>
<script>
// JavaScript代碼塊2
var a =1;
function f(){
alert(1);
}
</script>
雖然說,JavaScript是按塊執行的,但是不同塊都屬於同一個全局作用域,也就是說,塊之間的變數和函數是可以共享的。
1.4 藉助事件機制改變JavaScript執行順序
由於JavaScript是按塊處理代碼,同時又遵循HTML文檔流的解析順序,所以在上面示例中會看到這樣的語法錯誤。但是當文檔流載入完畢,如果再次訪問就不會出現這樣的錯誤。例如,把訪問第2塊代碼中的變數和函數的代碼放在頁面初始化事件函數中,就不會出現語法錯誤了。
復制代碼
代碼如下:
<script>
// JavaScript代碼塊1
window.onload = function(){ // 頁面初始化事件處理函數
alert(a);
f();
}
</script>
<script>
// JavaScript代碼塊2
var a =1;
function f(){
alert(1);
}
</script>
為了安全起見,我們一般在頁面初始化完畢之後才允許JavaScript代碼執行,這樣可以避免網速對JavaScript執行的影響,同時也避開了HTML文檔流對於JavaScript執行的限制。
注意
如果在一個頁面中存在多個windows.onload事件處理函數,則只有最後一個才是有效的,為了解決這個問題,可以把所有腳本或調用函數都放在同一個onload事件處理函數中,例如:
復制代碼
代碼如下:
window.onload = function(){
f1();
f2();
f3();
}
而且通過這種方式可以改變函數的執行順序,方法是:簡單地調整onload事件處理函數中調用函數的排列順序。
除了頁面初始化事件外,我們還可以通過各種交互事件來改變JavaScript代碼的執行順序,如滑鼠事件、鍵盤事件及時鍾觸發器等方法,詳細講解請參閱第14章的內容。
1.5 JavaScript輸出腳本的執行順序
在JavaScript開發中,經常會使用document對象的write()方法輸出JavaScript腳本。那麼這些動態輸出的腳本是如何執行的呢?例如:
復制代碼
代碼如下:
document.write('<script
type="text/javascript">');
document.write('f();');
document.write('function f(){');
document.write('alert(1);');
document.write('}');
document.write('</script>');
運行上面代碼,我們會發現:document.write()方法先把輸出的腳本字元串寫入到腳本所在的文檔位置,瀏覽器在解析完document.write()所在文檔內容後,繼續解析document.write()輸出的內容,然後才按順序解析後面的HTML文檔。也就是說,JavaScript腳本輸出的代碼字元串會在輸出後馬上被執行。
請注意,使用document.write()方法輸出的JavaScript腳本字元串必須放在同時被輸出的<script>標簽中,否則JavaScript解釋器因為不能夠識別這些合法的JavaScript代碼,而作為普通的字元串顯示在頁面文檔中。例如,下面的代碼就會把JavaScript代碼顯示出來,而不是執行它。
復制代碼
代碼如下:
document.write('f();');
document.write('function f(){');
document.write('alert(1);');
document.write(');');
但是,通過document.write()方法輸出腳本並執行也存在一定的風險,因為不同JavaScript引擎對其執行順序不同,同時不同瀏覽器在解析時也會出現Bug。
Ø 問題一,找不到通過document.write()方法導入的外部JavaScript文件中聲明的變數或函數。例如,看下面示例代碼。
復制代碼
代碼如下:
document.write('<script
type="text/javascript" src="http://www.jb51.net/test.js">
</script>');
document.write('<script type="text/javascript">');
document.write('alert(n);'); // IE提示找不到變數n
document.write('</script>');
alert(n+1); // 所有瀏覽器都會提示找不到變數n
外部JavaScript文件(test.js)的代碼如下:
復制代碼
代碼如下:
var n =
1;
分別在不同瀏覽器中進行測試,會發現提示語法錯誤,找不到變數n。也就是說,如果在JavaScript代碼塊中訪問本代碼塊中使用document.write()方法輸出的腳本中導入的外部JavaScript文件所包含的變數,會顯示語法錯誤。同時,如果在IE瀏覽器中,不僅在腳本中,而且在輸出的腳本中也會提示找不到輸出的導入外部JavaScript文件的變數(表述有點長和繞,不懂的讀者可以嘗試運行上面代碼即可明白)。
Ø 問題二,不同JavaScript引擎對輸出的外部導入腳本的執行順序略有不同。例如,看下面示例代碼。
復制代碼
代碼如下:
<script type="text/javascript">
document.write('<script type="text/javascript"
src="http://shaozhuqing.com/test1.js">
</script>');
document.write('<script type="text/javascript">');
document.write('alert(2);')
document.write('alert(n+2);');
document.write('</script>');
</script>
<script type="text/javascript">
alert(n+3);
</script>
外部JavaScript文件(test1.js)的代碼如下所示。
復制代碼
代碼如下:
var n = 1;
alert(n);
在IE瀏覽器中的執行順序如圖1-6所示。
圖1-6 IE 7瀏覽器的執行順序和提示的語法錯誤
在符合DOM標準的瀏覽器中的執行順序與IE瀏覽器不同,且沒有語法錯誤,如圖1-7所示的是在Firefox 3.0瀏覽器中的執行順序。
圖1-7 Firefox 3瀏覽器的執行順序和提示的語法錯誤
解決不同瀏覽器存在的不同執行順序,以及可能存在Bug。我們可以把凡是使用輸出腳本導入的外部文件,都放在獨立的代碼塊中,這樣根據上面介紹的JavaScript代碼塊執行順序,就可以避免這個問題。例如,針對上面示例,可以這樣設計:
復制代碼
代碼如下:
<script type="text/javascript">
document.write('<script type="text/javascript"
src="http://www.jb51.net/test1.js"></script>');
</script>
<script type="text/javascript">
document.write('<script type="text/javascript">');
document.write('alert(2);') ; // 提示2
document.write('alert(n+2);'); // 提示3
document.write('</script>');
alert(n+3); // 提示4
</script>
<script type="text/javascript">
alert(n+4); // 提示5
</script>
這樣在不同瀏覽器中都能夠按順序執行上面代碼,且輸出順序都是1、2、3、4和5。存在問題的原因是:輸出導入的腳本與當前JavaScript代碼塊之間的矛盾。如果單獨輸出就不會發生沖突了。
G. JS編程是什麼意思
計算機專業語言。
簡單來說,就是編寫編定程序,讓計算機代碼解決某個問題,對某個計算體系規定一定的運算方式,使計算體系按照該計算方式運行,並最終得到相應結果的過程。
為了使計算機能夠理解人的想法,人類通過某種方式,將需解決的問題的思路、方法和手段通過計算機能夠理解的形式告訴它,讓計算機完成人的指令。
H. JavaScript預編譯與執行順序的關系
按照代碼塊的先後順序關系,先對代碼塊進行預編譯,再執行。代碼塊指的是script標簽包含的js片段。具體如下:
step 1. 讀入第一個代碼塊。
step 2. 做語法分析,有錯則報語法錯誤(比如括弧不匹配等),並跳轉到step5。
step 3. 對var變數和function定義做「預編譯處理」(永遠不會報錯的,因為只解析正確的聲明)。
step 4. 執行代碼段,有錯則報錯(比如變數未定義)。
step 5. 如果還有下一個代碼段,則讀入下一個代碼段,重復step2。
step6. 結束。
I. js的執行原理是什麼
JS是解釋執行的,即讀取一個語句就執行一個。以前的嚴格JS是以分號為語句的分隔符,但現在一些瀏覽器已經接受以換行符為分隔符(似乎是很多人喜歡用基於對象的編程了,而在JS中寫對象的函數是需要加分號的,所以很多人都愛忘)。
JS本身只提供語法解析與少部分內部函數支持,其他的均由宿主支持。比如在網頁JS中的window, document, navigator等對象,均是由瀏覽器提供基於其它語言的代碼,這些代碼通常被隱藏,但很大程度上決定了JS的運行效率。如果你有興趣,打開Chrome,按F12,調處Console,然後輸alert(注意沒有()),你就會發現[native code]這個東西。
J. 向大家請教一javascript問題: JS中可以先寫調用,再寫函數瀏覽器不是按順序執行的嗎先
頁面載入過程中,瀏覽器會對頁面上或載入的每個js代碼塊(或文件)進行掃描,
如果遇到定義式函數,則進行預處理(類似於C等的編譯),
處理完成之後再開始 由上至下執行腳本中的內容