<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ## 變量提升 在**當前**作用域當中,把所有帶var和function關鍵字的提前聲明或則定義 ### 聲明和定義 > 在`當前作用域`中,js代碼自上而下執行之前,瀏覽器首先會把所有帶`var/function`關鍵字的進行提前的`聲明或則定義` es6中的`let/const`并不會 >聲明(declare): var num;在當前作用域中吼一嗓子 我有num這個名了 > 定義(defined):num=12;把聲明的名字賦一個值(先有個值,再把這個值和聲明的名字建立鏈接) ### var和function >[warning]帶var關鍵字的只是提前的聲明一下;帶function關鍵字的在變量提升階段把聲明和定義都完成了 ``` console.log(num); console.log(fn); var numb = 13; function fn(){ console.log(a); var a =10; console.log(a); } fn(); console.log(numb) ``` ![](https://box.kancloud.cn/136bf7faf8fae03bc3f278ba98323d72_1732x724.png) > **注意:** 除了全局作用域執行時,函數執行時也會執行自己的變量提升 ### 帶var和不帶var的區別 在項目中,如果目的是創建變量,最好不要省略var #### 帶var是聲明變量(順道在全局下定義一個屬性) 在當前作用域中聲明一個變量,如果當前是全局作用域,也相當于給全局作用域設置了一個屬性叫做a。 ``` //=>變量提升:var a; <=> window.a=undefined; console.log(a); //->undefined var a = 12; //定義了一個變量a并且將12這個值賦給了它,另外順道在 window.a=12 console.log(a); //->12 console.log(window.a); //->window['a'] 在”全局作用域“中,我們聲明一個變量相當于給全局對象window增加了一個屬性名 ``` #### 不帶var是全局屬性 在全局作用域中,如果不帶var,僅僅只是給全局對象設置了一個新的屬性名(相當于window.a=xx) ``` console.log(a); //=>Uncaught ReferenceError:a is not defined //先看是不是變量,如果沒有,在window下看有沒有這個屬性,如果都沒有,就會報錯(瀏覽器會認為你在忽悠它) //如果輸出的window.a,不會報錯,只會輸出undefined a = 12; //<=>window.a = 12 console.log(a); //=>12 console.log(window.a); //=>12 ``` ### 只對等號左邊的進行變量提升 ~~~ 等號= 左邊是變量 右邊都應該是值 ~~~ 匿名函數:函數表達式(把函數當做一個值賦值給變量或則其它內容) ``` oDiv.onclick = function(){ } //<=> oDiv.onclick = aaafff000 ``` 變量提升只會提升等號左邊的,右邊是值不會提前聲明。 ``` console.log(fn);//undefined var fn = function(){ } console.log(fn);//->函數本體 //谷歌瀏覽器中用小f 表示一個function ``` ``` sum(); //報錯 Uncaught TypeError:sum is not a function var sum = function(){} ``` 真實項目中,應用這個原理,我們創建函數的時候可以使用函數表達式的方式。 為了在項目中使代碼更加嚴謹,我們一般都通過函數表達式的方式來定義一個函數(先定義后執行) 因為: 1. 只能對等號左邊的進行提升,所以變量提升完成后,當前函數只是聲明了,沒有定義,想要執行函數只能放在賦值的代碼之后(放在前面執行相當于讓undefined執行,會報錯的) 2. 這樣讓我們的代碼邏輯更加嚴謹,以后想要知道一個執行的函數做了什么功能,只需要向上查找定義的部分即可(不會存在定義的代碼在執行下面的情況) ``` var fn = function sum(){ console.log(sum);//->函數本身 console.log(1); console.log(arguments.callee);//->函數本身 } sum(); //Uncaught TypeError:sum is not a function fn(); ``` ### 不管條件是否成立,都要進行變量提升 不管條件是否成立,**判斷體**當中出現的`var`或則`function`都會進行變量提升,但是在最新版本的瀏覽器當中,function聲明的變量只能提前聲明不能定義了。(前提:函數是在判斷體中) 老版本將瀏覽器的function是聲明加定義,新版本只會聲明(說的是放置在判斷體中時的情況) ``` console.log(num); //->undefined console.log(fn); //->undefined if(1 !== 1){ //不會走 console.log(num); console.log(fn); var num = 12; function fn(){} console.log(num); console.log(fn); } console.log(fn); //=>undefined ``` ``` console.log(num); //->undefined console.log(fn); //->undefined if(1 === 1){ console.log(num); //->undefined console.log(fn); //->函數體本身 var num = 12; function fn(){} console.log(num); //->12 console.log(fn); //=>函數體本身 } console.log(fn); //=>函數體本身 ``` ``` console.log(fn); //undefined for(var i=0;i<9;++i){ function fn(){} } ``` > 代碼執行到條件判斷的地方 >[條件不成立] >進入不到判斷體中,此時之前聲明的變量或則函數依然是undefined > >[條件成立] >進入條件判斷體中的第一件事情不是代碼執行,而是把之前變量提升沒有定義的函數首先定義了(進入到判斷體中函數就定義了,為了迎合ES6中的塊級作用域) ``` f = function(){ return true; } g = function(){ return false; } ~function(){ //=>[私有作用域] //變量提升:g //雖然g提升了但在新版本中,因為這貨在判斷體里,只提升不會定義 //故g()報錯 if(g()&&[]==![]){ f=function(){ return false; }; function g(){ return true; } } }(); console.log(f()); // console.log(g()); //false ``` ### 重命處理 ``` fn(); //4 function fn(){ console.log(1); } fn(); //4 function fn(){ console.log(2); } fn(); //4 var fn = 13; fn(); //報錯 function fn(){ console.log(3); } fn(); function fn(){ console.log(4); } fn(); ``` 在變量提升階段,如果名字重復了,不會重新的進行聲明,但是會重新進行定義(后面賦的值會把前面賦的值替換掉) ## 作用域鏈 ``` function fn(){ a = 123; // <=>window.a = 123; console.log(a); //=>123 } fn(); console.log(a); //=>123 ``` >函數執行形成一個私有的作用域(保護私有變量),進入到私有作用域中,首先變量提升(聲明過的變量是私有的),接下來代碼執行 >1. 執行的時候遇到一個變量,如果這個變量是私有的,變量不受外界干擾 >2. 如果當前這個變量不是私有的,我們需要向它的上級作用域進行查找,上級也沒有,則繼續向上查找,直到找到window全局作用域為止,我們把這種查找機制叫做**作用域鏈** >1)如果上級作用域有,我們當前操作的都是上級作用域中的變量(假如我們在當前作用域把值改了,相當于把上級作用域中的這個值給改了) >2)如果上級作用域中沒有這個變量(找到window也沒有) >變量 = 值:相當于給window設置了一個屬性,以后再操作window下就有了 >alert(變量):想要輸出這個變量,但此時是沒有的,所以會報錯 ``` console.log(x,y);//undefined undefined var x = 10, y = 20; //var x=10;var y=20; function fn(){ console.log(x,y); //undefined 20 var x = y = 100; //var x = 100;y=100; console.log(x,y);// 100 100 } fn(); console.log(x,y);//10,100 ``` 作用域(開辟)->變量提升->逐行運行
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看