成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

JavaScript中變量提升與預(yù)編譯的示例分析-創(chuàng)新互聯(lián)

這篇文章主要為大家展示了JavaScript中變量提升與預(yù)編譯的示例分析,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶大家一起來(lái)研究并學(xué)習(xí)一下“JavaScript中變量提升與預(yù)編譯的示例分析”這篇文章吧。

“只有客戶發(fā)展了,才有我們的生存與發(fā)展!”這是創(chuàng)新互聯(lián)的服務(wù)宗旨!把網(wǎng)站當(dāng)作互聯(lián)網(wǎng)產(chǎn)品,產(chǎn)品思維更注重全局思維、需求分析和迭代思維,在網(wǎng)站建設(shè)中就是為了建設(shè)一個(gè)不僅審美在線,而且實(shí)用性極高的網(wǎng)站。創(chuàng)新互聯(lián)對(duì)成都做網(wǎng)站、網(wǎng)站建設(shè)、外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)站開(kāi)發(fā)、網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站優(yōu)化、網(wǎng)絡(luò)推廣、探索永無(wú)止境。

Java的特點(diǎn)有哪些

Java的特點(diǎn)有哪些 1.Java語(yǔ)言作為靜態(tài)面向?qū)ο缶幊陶Z(yǔ)言的代表,實(shí)現(xiàn)了面向?qū)ο罄碚摚试S程序員以優(yōu)雅的思維方式進(jìn)行復(fù)雜的編程。 2.Java具有簡(jiǎn)單性、面向?qū)ο?、分布式、安全性、平臺(tái)獨(dú)立與可移植性、動(dòng)態(tài)性等特點(diǎn)。 3.使用Java可以編寫(xiě)桌面應(yīng)用程序、Web應(yīng)用程序、分布式系統(tǒng)和嵌入式系統(tǒng)應(yīng)用程序等。

一、有趣的現(xiàn)象

按照大家的常識(shí),JavaScript代碼在執(zhí)行是一定是自上而下的,你需要輸出一個(gè)字符串,當(dāng)然需要提前聲明一個(gè)保存string類型的變量。如果深?yuàn)W的道理我都能懂,于是我閱讀了下面的代碼。

1.1 我以為的開(kāi)局
var str = '123';console.log(str); // 123

我們調(diào)換一下代碼的位置在再看:

console.log(str); // undefinedvar str = '123';

我好像找到規(guī)律了!!!

當(dāng)我看完了前兩段代碼并且進(jìn)行了“深度思考”后,我好像找到規(guī)律了,那就是:在當(dāng)前代碼塊后函數(shù)中,在變量聲明和初始化之前使用變量,會(huì)拿不到正確的值。

1.2 實(shí)際上是這樣的

帶著上面的“結(jié)論”我來(lái)到了這里

var val = '余光';(function(){
    console.log(val); // 余光})();

果然如此!,在變量聲明和初始化之后耶穌也阻擋不了我拿到val的值,我說(shuō)的?。?!

當(dāng)我看到下面一段代碼時(shí),我已經(jīng)產(chǎn)生了動(dòng)搖,此事必要蹊蹺。

var val = '余光';(function(){
    console.log(val); // undefined
    var val = '測(cè)試';})();

Ps:如果大家立即執(zhí)行函數(shù)存在疑問(wèn),不妨看看《JavaScript之深入理解立即調(diào)用函數(shù)表達(dá)式(IIFE)》吧~

這…我慫了,是什么原因?qū)е逻@樣的現(xiàn)象發(fā)生的呢?Js又是如果處理的呢?

二、Js的預(yù)解析

在當(dāng)前的作用域內(nèi),無(wú)論在哪里變量聲明,在幕后,都會(huì)進(jìn)行一次看不見(jiàn)的移動(dòng)。

注意:僅聲明被“移動(dòng)”。即聲明和賦值在某些時(shí)候被動(dòng)分開(kāi)了。而這次看不見(jiàn)的移動(dòng)實(shí)際上就是Js在編譯階段的解析

來(lái)看一段《你知不知道的Js》中經(jīng)典的例子:

name = '余光'; // 未添加關(guān)鍵字(未聲明),name為全局變量,,即window.name = '余光'var name; // 再次聲明name,此時(shí)name未進(jìn)行初始化,它的值是undefined嗎?console.log(name); // ?

結(jié)果是成功打印“余光”,這樣看不見(jiàn)的移動(dòng)就發(fā)生在Js預(yù)解析(編譯)之中。

2.1 核心:預(yù)解析

為了搞明白這個(gè)核心問(wèn)題,我們需要回顧一下,引擎會(huì)在解釋JavaScript代碼之前首先對(duì)其進(jìn)行編譯。編譯階段中的一部分工作就是找到所有的聲明,并用合適的作用域?qū)⑺鼈冴P(guān)聯(lián)起來(lái)。感興趣的小伙伴可以閱讀《JavaScript中的變量對(duì)象》和《從作用域到作用域鏈》這兩篇文章哦~

因此,發(fā)生這樣的事情,包括變量函數(shù)在內(nèi)的所有聲明都會(huì)在任何代碼被執(zhí)行前首先被處理。當(dāng)你看到var a = 2;時(shí),可能會(huì)認(rèn)為這是一個(gè)聲明。但JavaScript實(shí)際上會(huì)將其看成兩個(gè)聲明:var a;和a = 2;。

  • 第一個(gè)定義聲明是在編譯階段進(jìn)行的。

  • 第二個(gè)賦值聲明會(huì)被留在原地等待執(zhí)行階段。

即代碼是這樣寫(xiě)的:

// 我們看到的代碼:var name = '余光';

但Js會(huì)將它解析成:

// 聲明(Declaration)var name; // 聲明但未初始化,所以分配 undefined// 初始化(Initialization)name = '余光'; // 初始化(賦值)

所以本小結(jié)的一段代碼應(yīng)該這樣分析:

var name; // 聲明name提到作用域頂部,并被分配了一個(gè)undefinedname = '余光'; // 進(jìn)行初始化操作console.log(name); // '余光'
2.2 注意:只有聲明被提升了

只有聲明會(huì)被提升,而賦值和其他代碼邏輯會(huì)在執(zhí)行到代碼的位置時(shí)才會(huì)生效。所以會(huì)有下面的問(wèn)題:

foo();function foo(){
    console.log(name); // undefined
    var name = '余光';}

函數(shù)被提升了,自然可以正常執(zhí)行,但變量?jī)H僅是聲明被提升了。

2.3 每個(gè)作用域都會(huì)進(jìn)行提升操作

還是上面的代碼:

foo();function foo(){
    console.log(name); // undefined
    var name = '余光';}

實(shí)際它在編譯時(shí)是這樣的:

function foo(){
    var name; // 聲明
    console.log(name); // undefined
    name = '余光'; // 初始化}foo(); // 函數(shù)執(zhí)行

三、提升之間的優(yōu)先級(jí)

既然我們知道了變量函數(shù)會(huì)被提升,他們之間又是如何判斷優(yōu)先級(jí)的呢?

3.1 函數(shù)會(huì)被首先提升,然后才是變量

我們分析下面的代碼:

foo();var foo; // 1function foo(){
    console.log('余光');}foo = function(){
    console.log('小李');}

本著函數(shù)優(yōu)先提升的原則,他會(huì)被解析成這樣:

function foo(){
    console.log('余光');}foo(); // 余光foo = function(){
    console.log('小李');}

注意,var foo 因?yàn)槭且粋€(gè)重復(fù)聲明,且優(yōu)先級(jí)低于函數(shù)聲明所以它被忽略掉了。

3.2 函數(shù)字面量不會(huì)進(jìn)行函數(shù)提升

最直觀的例子,就是在函數(shù)字面量前調(diào)用該函數(shù):

foo();var foo = function(){
    console.log(1);}// TypeError: foo is not a function

這段程序中:

  1. 變量標(biāo)識(shí)符foo被提升并分配給所在作用域(在這里是全局作用域),因此在執(zhí)行foo()時(shí)不會(huì)導(dǎo)致ReferenceError(),而是會(huì)提示你foo is not a function

  2. 然后就是執(zhí)行foo,foo此時(shí)并沒(méi)有賦值(注意變量被提升了)。由于對(duì)undefined值進(jìn)行函數(shù)調(diào)用而導(dǎo)致非法操作,因此拋出TypeError異常。

四、ES6和小結(jié)

ES6新增了兩個(gè)命令letconst,用來(lái)聲明變量,有關(guān)它們完整的概念我會(huì)在《ES6基礎(chǔ)系列》中總結(jié),提起它們,是因?yàn)?strong>變量提升在它們身上不會(huì)存在。

4.1 變量提升是可以規(guī)避的

let命令改變了語(yǔ)法行為,它所聲明的變量一定要在聲明后使用,否則報(bào)錯(cuò)。

// var 的情況console.log(foo); // 輸出undefinedvar foo = 2;// let 的情況console.log(bar); // 報(bào)錯(cuò)ReferenceErrorlet bar = 2;

上面代碼中,變量foo用var命令聲明,會(huì)發(fā)生變量提升,即腳本開(kāi)始運(yùn)行時(shí),變量foo已經(jīng)存在了,但是沒(méi)有值,所以會(huì)輸出undefined。變量bar用let命令聲明,不會(huì)發(fā)生變量提升。這表示在聲明它之前,變量bar是不存在的,這時(shí)如果用到它,就會(huì)拋出一個(gè)錯(cuò)誤。

在變量提升上,const和let一樣,只在聲明所在的塊級(jí)作用域內(nèi)有效,也不會(huì)變量提升

4.2 小結(jié)
  1. 變量提升:函數(shù)聲明和變量聲明總是會(huì)被解釋器悄悄地被"提升"到方法體的最頂部,但變量的初始化不會(huì)提升;

  2. 函數(shù)提升:函數(shù)聲明可以被看作是函數(shù)的整體被提升到了代碼的頂部,但函數(shù)字面量表達(dá)式并不會(huì)引發(fā)函數(shù)提升;

  3. 函數(shù)提升優(yōu)先與變量提升;

  4. let和const可以有效的規(guī)避變量提升

最后提煉一下:JavaScript引擎并不總是按照代碼的順序來(lái)進(jìn)行解析。在編譯階段,無(wú)論作用域中的聲明出現(xiàn)在什么地方,都將在代碼本身被執(zhí)行前首先進(jìn)行處理,這個(gè)過(guò)程被稱為提升。聲明本身會(huì)被提升,而包括函數(shù)表達(dá)式的賦值在內(nèi)的賦值操作并不會(huì)提升。

以上就是關(guān)于“JavaScript中變量提升與預(yù)編譯的示例分析”的內(nèi)容,如果改文章對(duì)你有所幫助并覺(jué)得寫(xiě)得不錯(cuò),勞請(qǐng)分享給你的好友一起學(xué)習(xí)新知識(shí),若想了解更多相關(guān)知識(shí)內(nèi)容,請(qǐng)多多關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁(yè)標(biāo)題:JavaScript中變量提升與預(yù)編譯的示例分析-創(chuàng)新互聯(lián)
URL鏈接:http://jinyejixie.com/article30/djejso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、外貿(mào)建站、商城網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)
龙州县| 华坪县| 新闻| 平遥县| 固镇县| 泊头市| 宁阳县| 喀喇| 兴国县| 丹寨县| 绥德县| 九台市| 哈尔滨市| 德庆县| 边坝县| 灵台县| 岚皋县| 拉萨市| 开远市| 普宁市| 宁国市| 柳河县| 贡嘎县| 青冈县| 手机| 桓台县| 普洱| 尤溪县| 甘肃省| 桐城市| 陆川县| 甘孜| 镇江市| 乌鲁木齐县| 六盘水市| 乳山市| 广河县| 秦皇岛市| 伊通| 赞皇县| 义乌市|