JavaScript提升篇之預解釋做用域以及this原理及其應用

1.預解釋

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>預解釋1</title>
 6 
 7     <script type="text/javascript">
 8         /*js中的數據類型:*/
 9             //1.基本數據類型:(按照值來進行操做的)
10                 //number,string,Boolean,undefined,null
11 
12             //2.引用數據類型:(是按照地址進行操做的)
13                 //object:{} [] /^$/ Date
14                 //function:
15         // 例1:
16                 console.log(num);//num=undefined,爲何是未定義,由於聲名了可是沒有賦值,因此是未定義。
17                 var num=12;
18                 console.log(num);//定義了12;因此值是12;
19                 var obj={name:"lizebo",age:23};
20                 fn(100,200);//300能夠在上面執行,由於預解釋的時候聲明+定義已經完成了。
21                 function fun(){
22                     console.log("easy js!")
23                 }
24                 console.log(fun)//->把整個函數的定義部分(函數自己)在控制檯輸出
25                 console.log(fn(1,2))//->把當前函數執行的返回結果(return後面的值放回,若是沒有return,默認返回的是undefined)
26                                         //圖片見images中的基本數據類型和引用數據類型的存儲方式.PNG
27                     //1.當瀏覽器加載HTML頁面的時候,首先會提供一個全局JS代碼執行的環境>全局做用域
28                     //(global/window)
29 
30                     //2.預解釋(變量提聲)
31                     //在當前的做用域中,JS代碼執行以前,瀏覽器首先會把默認的全部帶var和function的進行提早聲明或者(注意是或者,function就是聲明+定義)定義(這是瀏覽器的
32                     //機制).
33                         //1)聲明和定義:
34                         //var num =12;
35                         //聲明(declare):var num;-->告訴瀏覽器在全局做用域中有一個num的變量。
36                         //定義(defined):num=12;-->num=12;-->給咱們的變量進行賦值。
37 
38                         //2)對於帶var和function關鍵字的在預解釋的時候操做仍是不同的
39                         //var ->在預解釋的時候只是提早的聲明
40                         //function->在預解釋的時候提早的申明+定義都完成了。
41                                 //見圖:瀏覽器預解釋過程.png
42                         //3)預解釋只發生在當前的做用域下,列入:開始只對window下進行預解釋,只有函數執行的時候纔會對函數中的內容進行預解釋。
43 
44                     //3.js中內存的分類
45                     //堆內存:用來存儲引用數據類型的值-》對象存儲的是屬性名和屬性值,函數存儲的是字符串代碼塊
46                     //棧內存:用來提供一個js代碼執行的環境-》做用域(全局做用域和私有做用域)
47                 function fn(num1,num2){
48                     var total=num1+num2;
49                     console.log(total);
50                 }
51     </script>
52 </head>
53 <body>
54 
55 </body>
56 </html>
View Code

 

                      1)基本數據類型和引用數據類型的存儲方式javascript

                    2)瀏覽器預解釋過程html

2.做用域

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>做用域鏈2</title>
 6 
 7     <script type="text/javascript">
 8         //1.如何區分私有變量和全局變量(做用域鏈機制)
 9         //1)在全局做用域下申明(預解釋的時候)的變量是全局變量
10         //2)在私有做用域中聲明的變量和函數的形參都是私有的變量
11         //在私有做用域中,咱們代碼執行的的時候遇到了一個變量,首先咱們須要肯定他是否是私有變量,若是是私有變量,那麼和外面的沒有關係。
12         //若是不是私有的,則往當前做用域的上級做用域進行查找,若是上級做用域也沒有則繼續查找,一直找到window。
13 
14         //2.當函數執行的時候(直接目的:讓函數體中的代碼執行),首先會造成私有的做用域(在棧內存中)
15         //而後按照以下步驟執行:
16         //1)若是有形參,先給形參賦值
17         //2)進行私有做用域中的預解釋
18         //3)私有做用域中的代碼從上到下執行
19         //...未完待續
20         //函數造成一個新的私有做用域保護了裏面的私有變量不受外界的干擾(外面修改不了私有的,私有的也修改不了外面的。
21         //          這種機制就是「閉包「--簡單說就是互不影響。
22         //
23         console.log(totlal);//undefined
24         var total=0;
25         function  fn(num1,num2) {
26             console.log(total);//undefined
27             var total=num1+num2;
28             console.log(total);//300
29         }
30         fn(100,200);
31         console.log(total)//0
32 
33         //=========另一個例子========
34         console.log(total1);//undefined
35         var total1=0;
36         function  fn22(num2,num3) {
37             console.log(total1);//0;
38             total1=num3+num2;
39             console.log(total1);//300:這裏爲何是300不是其餘值,就是由於做用域鏈的機制。。
40         }
41         fn22(100,200);
42         console.log(total1)
43     </script>
44 </head>
45 <body>
46 
47 </body>
48 </html>
View Code

3.全局變量的細節問題

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>全局變量的細節問題3</title>
 6 
 7     <script type="text/javascript">
 8         //在全局做用域中,帶var和不帶var的關係?
 9         //區別:帶var的能夠進行預解釋,因此在賦值的前面執行不會報錯;不帶var的是不能進行預解釋的
10         //在前面執行會報錯。
11                console.log(num);//->undefined
12                 var num=12;
13 
14                 //console.log(num2);//->Uncaught ReferenceError: num2 is not defined
15                 num2=12;
16 
17         //============例子2===========
18             //關係:num2=12->至關於給window增長了一個叫作num2的屬性名,屬性值是12;
19             //var num=12;->首先它至關於給全局做用域增長了一個全局變量num,可是不只如此,
20             //它也至關於給window增長了一個屬性名,屬性值是12;
21             var num3=12;
22             console.log(num3);
23             num4=12;
24             console.log(num4);
25             console.log(window.num4)
26     </script>
27 </head>
28 <body>
29 
30 </body>
31 </html>
View Code

4.total加var和不加var的區別

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>total加var和不加var的區別4</title>
 6 <!--js中迷幻賦值,究竟是給變量賦值,仍是給屬性賦值?-->
 7     <script type="text/javascript">
 8             //私有做用域中出現的一個變量不是私有的,則往上級做用域進行查找,上級做用域沒有則繼續向上
 9             //進行查找,一直知道到window爲止3,若是window下也沒有呢?
10             //咱們是獲取值:console.log(total);-->報錯,沒有聲明變量
11             //咱們是設置值total=100;->至關於window增長了一個屬性名爲total,屬性值爲100;
12 
13             function fn(){
14                 total=100;
15                 //這裏不是變量賦值,他是看私有域-沒有var聲明的變量-》向上找-沒有—》window也沒有就只能給window賦值,使得屬性名字是total,值是100;
16             }
17             fn();
18             console.log(total)
19             //這一這裏的total不是變量,是window的屬性值,這是2個不一樣的概念,可是值是相同的。
20             //至關於:
21             console.log("這一這裏的total不是變量,是window的屬性值,這是2個不一樣的概念,可是值是相同的。")
22             console.log(window.total);
23     </script>
24 </head>
25 <body>
26 
27 </body>
28 </html>
View Code

5.預解釋是一種毫無節操的機制

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>預解釋是一種毫無節操的機制5</title>
 6 
 7     <script type="text/javascript">
 8         //預解釋是一種毫無節操的機制
 9 
10         //in:"num" in window 判斷num是否爲window這個對象的屬性,是的話返回true不是的話返回false
11 
12         var obj={name:"lizbe",age:23};
13         console.log("name" in obj);//true
14         console.log("eat" in obj);//false;
15 
16         //1.預解釋的時候,無論條件是否成立都要把帶var的進行提早聲明。
17         //window的預解釋:var num;->window.num;說白了就是先進性預解釋在執行代碼,並且不會管條件判斷,由於在一個域中。
18         if(!("num" in window)){
19             var num=12;
20         }
21         console.log(num);//undefined
22         console.log("========例2=======");
23         //2.預解釋的時候只預解釋」=「左邊的,右邊的值,不參與預解釋
24         //匿名函數之函數表達式:把函數定義的部分看成一個值賦值給咱們的變量或者元素的某一個事件。
25 
26         //window下的預解釋:var fn;
27         //fun();//fn is not a function
28         var fun=function(){
29             console.log("ok");
30         };  //這也再次正式了fun存的是一個地址指向堆內存中的字符串,function(){
31             //console.log("ok");
32             //};
33             //正式因爲js(預解釋的存在,全球惟一的機制),因此能夠屢次使用這種模式,他能夠定義一個函數,這個函數的上面是不能夠執行的。
34 
35 
36 //        fn();
37 //        function () {
38 //            console.log("ok")
39 //        }
40 //        fn();
41 
42         //3.自執行函數定義的那個function在全局做用下不進行預解釋,當代碼執行到了這個位置的時候定義和執行一塊兒完成了。
43         //自執行函數:定義和執行一塊兒完成了
44         //
45         (function (num) {})(100);
46                 //如下是裝逼寫法:
47         +function (num) {}(100);
48         -function (num) {}(100);
49         ~function (num) {}(100);
50         !function (num) {}(100);
51 
52         //4.函數體中,return下面的代碼雖然不在執行了,可是瀏覽器一運行就已經進行了預解釋,因此預解釋優先一切。
53         //return後面跟着的是返回的值,因此不進行預解釋;
54         function  funct() {
55             console.log(num);//-》undefined
56             return function(){
57 
58             };
59             var num =100;
60         }
61         funct();
62 
63         //5.在預解釋的時候,若是名字已經聲明過;不須要從新的聲明;可是須要從新的賦值。
64         //在js中若是變量的名字和函數的名字重複了,也算衝突。
65         //預解釋:var fn,window.fn; fn=xxxabbb23,window.fn=xxxabbb23;
66         var fn1=13;
67         function fn1() {
68                 console.log("ok")
69         }
70 
71 
72         //======例子=======
73                     //window預解釋:
74                     //聲明+定義 fn333=xxxfff111
75                     //聲明var fn333;(不須要從新聲明)
76                     //聲明(不重複進行)+定義(可是會定義) fn333=xxxfff222
77                     //-》fn=xxxfff222
78         //=====牛逼的例子:=========
79         console.log("牛逼的例子關於預解釋!!!!!!")
80         fn333();//->2
81         function fun333() {console.log(1);};
82         fn333();//->2
83         var fn333=10;
84         fn333();//->error: fn is not a function.
85         function fn333() {console.log(2);};
86         fn333();
87     </script>
88 </head>
89 <body>
90 
91 </body>
92 </html>
View Code

6.如何查找上級做用域

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>如何查找上級做用域</title>
 6 
 7     <script type="text/javascript">
 8     //如何查找當前做用域的上級做用域?
 9     //看當前函數實在那個做用域下定義的,那麼它的上級做用域就是誰。
10     //和函數在哪裏執行沒有任何關係,
11            var num=12;
12         function fn() {
13                 var num=120;
14                 //見圖做用域鏈.png你就知道這裏爲何能夠不寫函數名稱,由於這是一個指針鏈條。簡稱做用域鏈。
15                 return function () {
16                   console.log(num)
17                 };
18             }
19             var f= fn();
20             f();//問執行結果:120;
21 
22             //這個結果又是什麼呢?
23         !function () {var num=1200;f()}();//120;
24 
25     </script>
26 </head>
27 <body>
28 
29 </body>
30 </html>
View Code

7.關於內存釋放和做用域銷燬的研究

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>7.關於內存釋放和做用域銷燬的研究.html</title>
 6 
 7     <script type="text/javascript">
 8         //1.堆內存
 9         //對象數據類型或者函數數據類型在定義的時候首先都會開啓一個堆內存,而且堆內存有一個引用地址,若是外邊有變量知道了這個地址
10         //咱們就說這個內存被佔用了,不能銷燬。
11         var obj1={name:"張三"};
12         var obj2=obj1;
13             //內存銷燬
14         obj1=null;
15         obj2=null;//null是空對象指針。專門釋放空間的,可是不是當即釋放,瀏覽器空閒的時候回收。換句話說,剛剛等於null的時候,並無銷燬;只是有一個機制
16         //在瀏覽器中,過一段時間,進行銷燬。不僅是賦值爲null,爲1,2...也行。
17         //表示的就是堆內存中沒有任何東西佔用了內存。
18 
19 
20         //2.棧內存:
21         //1)全局做用域:
22         //      只有當頁面關閉的時候,全局做用域纔會銷燬
23         //2)私有做用域:(只有函數執行會產生私有做用域)
24         //       通常狀況下,函數執行會造成一個新的私有做用域,私有做用域中當代碼執行完成後,咱們當前做用域都會進行主動釋放和銷燬。
25         //可是仍是存在特殊狀況的:
26         //                   當前私有做用域中的部份內容被做用域之外的東西佔用了,那麼當前做用域就不能銷燬了。
27         //                    a.函數執行返回了一個引用數據類型的值,而且在函數的外面被其餘東西給接收了,這種狀況下通常造成的私有做用域都不會銷燬。
28         //                      例子:
29         function fn() {
30             var num=100;
31             //返回的是一個引用數據類型的值
32             return function (){
33             };
34         }
35             //一個東西接收了函數的值。
36         var f=fn();//fn造成的私有做用域不能銷燬。
37         var odiv1=document.getElementById("div1");
38         !function () {
39             odiv1.onclick=function () {
40 
41             };
42         }();//當前自執行函數也不能銷燬。
43 
44         //經過DOM方法得到的元素或者是元素集合類型都是對象數據類型的值
45         //                  b.在一個私有的做用域中綁定方法,通常狀況下咱們的私有做用域都不銷燬。
46 
47 
48         //                  c.下述狀況屬於不當即銷燬。--》fn返回的函數沒有被其餘的東西佔用。可是還須要執行一次,因此暫時不銷燬,當返回的值執行完畢後,
49         //                  瀏覽器纔會銷燬。
50         function fnD() {
51             var num=100;
52             return function () {
53 
54             };
55         }
56         funD()();//首先執行fn,返回一個小函數對應的內存地址,緊接着讓對應的小函數再執行。
57                  //
58     </script>
59 </head>
60 <body>
61         <div id="div1" >有本事點我啊</div>
62 </body>
63 </html>
View Code

8.做用域練習題

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>做用域練習題</title>
 6 
 7     <script type="text/javascript">
 8             //++i和i++
 9             //都是自身加1,再和其餘的值進行運算的時候有區別
10             //i++;是先拿i的值進行運算,運算完成自己+1
11             //++i;先自己累加1,而後那累加完成的結果去運算
12             var i=5;
13             console.log(1+(i++));//->6 i=6
14             console.log(1+(++i));//->8 i=7
15             console.log(2+(i++)+(++i)+(++i)+(i++));//38
16             console.log(i);//11
17             console.log("===========================")
18 
19             function fn() {
20                 var i=10;
21                 return function (n) {
22                     console.log(n+(++i));
23                 }
24             }
25             //見圖 練習題.jpn
26             var f=fn();
27             f(10);//21
28             f(20);//32
29             fn()(10);//21
30             fn()(20);//31
31             //再來一題
32             console.log("==============");
33             function fn2(i){
34                 return function (n) {
35                     console.log(n+(i++));
36                 }
37             }
38             var f2=fn2(13);
39             f2(12);//25;
40             f2(14);//28
41             fn2(15)(12);//27
42             fn2(16)(13);//29
43     </script>
44 </head>
45 <body>
46 
47 </body>
48 </html>
View Code

9.this

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <!--說明如下:想要本身開發一個js框架,而不是經過造輪子開發;this必須可以靈活運用。-->
 5     <meta charset="UTF-8">
 6     <title>this</title>
 7 
 8 </head>
 9 <body>
10         <div id="div1" >有本事點我啊!this總共有5個知識點,就是這樣。</div>
11 
12 <script type="text/javascript">
13         //咱們再js中主要研究的是1.函數中的this
14         console.log(this);
15         console.log("===============");
16         //2.js中的this表明的是當前行爲執行的主體;js中的context表明的是
17         //當前行爲執行的環境或者(區域):
18 
19 
20         //this是誰和函數再哪裏定義的和再哪裏執行的都沒有任何的關係。
21         //如何區分this?
22         //1.函數執行,首先看函數名前面是否有」.「,有的話前面是誰this就是誰;沒有的話就是window
23         function fnct() {
24             console.log(this);
25         }
26         var obj={fnct:fnct};
27         fnct();//this->window
28         obj.fnct();//this-->obj
29 
30         function sum() {
31             fnct();//this-->仍是window
32         }
33         sum();
34 
35         var oo={
36             //
37             sum:function () {
38                fnct();
39             }
40         };
41         oo.sum();//this-->window
42 
43         //2.自執行函數中的this永遠是window
44         //3.給元素的某一個事件綁定方法,當事件觸發的時候,執行對應的方法,方法中的
45         //this是當前的函數。
46         function fnctDemo() {
47             console.log(this)
48         }
49         document.getElementById("div1").onclick=fnctDemo;//fn中的this是#div1
50         document.getElementById("div1").onclick=function () {
51             //this--->#div1
52             console.log("=====")
53             console.log(this);
54             console.log("=========");
55                 fnctDemo();
56         };//當點擊的時候this的值是window,
57     </script>
58 </body>
59 </html>
View Code

10.綜合是實戰題

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>綜合是實戰題</title>
 6 </head>
 7 <body>
 8     <div class="box">
 9         <h1>點擊投票</h1>
10         <div id="btn">你投票嗎?<span id="spanNum">0</span></div>
11     </div>
12     <div class="box1">
13         <h1>點擊投票</h1>
14         <div id="btn1">你投票嗎?<span id="spanNum1">0</span></div>
15     </div>
16 
17 <script type="text/javascript">
18         var oBtn=document.getElementById("btn");
19         var spanNum=document.getElementById("spanNum");
20         //1.利用全局做用域不銷燬的原理,把須要累加的數字定義爲全局變量
21         var count=0;
22         oBtn.onclick=function () {
23             count++;
24             spanNum.innerHTML=count;
25         };
26         //2.爲了放置全局變量的相互衝突,在實際項目當中應該儘可能不使用全局變量,或者說禁止使用全局變量。
27 
28         var oBtn1=document.getElementById("btn1");
29         var spanNum1=document.getElementById("spanNum1");
30             //本身造成一個不銷燬的做用域來保護咱們須要累加的數字
31             +function () {
32                 var count1=0;
33                 oBtn1.onclick=function () {
34                     count1++;
35                     spanNum1.innerHTML=count1;
36                 }
37             }();
38 //          另一種形式:
39 //                oBtn1.onclick=(function () {
40 //                var count=0;
41 //                return function () {
42 //                    count++;
43 //                    spanNum1.innerHTML=count;
44 //                }
45 //        })();
46 
47             //弊端:有一個不銷燬的私有做用域,因此佔那麼一丟丟內存。
48         //另一種:利用innerHtml的方式處理,每一次點擊的時候都到頁面中獲取最新的值,累加,把最後累加的結果從新放回去。
49 //                oBtn1.onclick=function () {
50 //                    //spanNum1獲取的頁面中的內容返回的是一個字符串。
51 //                    //spanNum1.innerHTML=spanNum1.innerHTML+1;
52 //                    spanNum1.innerHTML++;
53 //                };
54 //弊端:每一次都須要把頁面中的內容先轉換爲字符串而後在累加,累加完在從新添加回去,
55 //當從新添加回去的時候瀏覽器都要從新渲染如下。
56 
57     //4.利用自定義屬性存儲:比較好的方式。
58            oBtn1.count=0;
59            oBtn1.onclick=function () {
60                spanNum1.innerHTML=++this.count;
61            };
62 
63 </script>
64 
65 </body>
66 </html>
View Code

11.練習題

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>練習題</title>
 6 </head>
 7 <body>
 8     <h1>見圖練習題.png</h1>
 9     <script type="text/javascript">
10         var num=20;
11         var obj={
12             num:30,
13             fn:(function(num){
14                 this.num*=3;
15                 num+=15;
16                 var num=45;
17                 return function () {
18                     this.num*=4;
19                     num+=20;
20                     console.log(num);
21                 };
22             })(num),//->把全局變量num的值20賦值給了自執行函數的形參,而不是
23             //obj下的30,若是是obj下的30,咱們須要寫obj.mum.
24         };
25         var fn=obj.fn;
26         fn();
27         obj.fn();
28         console.log(window.num,obj.num);
29     </script>
30 </body>
31 </html>
View Code
相關文章
相關標籤/搜索