JavaScript-18


1.函數進階

  • 函數的定義和使用
    • 函數聲明方式function關鍵字(命名函數)
    • 函數表達式(匿名函數)
    • new Function()
      • Function里面的參數必須都是字符串格式
      • 第三種方式執行效率低,也不方便書寫,因此較少使用
      • 所有函數都是Function的實例(對象)
      • 函數也屬於對象
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //函數的定義方式
10             //1.自定義函數
11             function fn(){};
12             //2.函數表達式
13             var fun = function(){};
14             //3.利用new Function('參數1','參數2','函數體');
15             var f = new Function('a','b','console.log(a+b)');
16             f(1,2);
17             //4.所有的函數都是Function的實例對象
18         </script>
19     </body>
20 </html>
  • 函數的調用方式
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //函數的調用方式
10             
11             //1.普通函數
12             function fn(){
13                 console.log("普通函數");
14             }
15             // fn();
16             // fn.call();
17             //2.對象的方法
18             var obj = {
19                 sayHi: function(){
20                     console.log("Hi");
21                 }
22             }
23             obj.sayHi();
24             //3.構造函數
25             function Star(){};
26             new Star();
27             //4.綁定時間的函數
28             // btn.onclick = function(){};
29             //點擊按鈕就可以調用這個函數
30             //5.定時器函數
31             setInterval(function(){},1000);
32             //這個函數是定時器自動每秒鍾調用一次
33             //6.立即執行函數
34             (function(){console.log("怎么也飛不出,花花的世界~~~")})()
35             //立即執行函數是自動調用
36         </script>
37     </body>
38 </html>
  • this
調用方式 this指向
普通函數調用 window
構造函數調用 實例對象,原型對象里面的方法也指向實例對象
對象方法調用 該方法所屬對象
事件綁定調用 綁定事件對象
定時器函數 window
立即執行函數 window

 

 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //函數的調用方式
10             //函數的不同決定了this的指向不同
11             //1.普通函數 this指向window
12             function fn(){
13                 console.log("普通函數"+this);
14             }
15             // fn();
16             // fn.call();
17             //2.對象的方法 this指向對象
18             var obj = {
19                 sayHi: function(){
20                     console.log("Hi"+this);
21                 }
22             }
23             // obj.sayHi();
24             //3.構造函數 this指向的是實例對象,原型對象里面的this指向的也是實例對象
25             function Star(){};
26             new Star();
27             //4.綁定時間的函數 this指向函數的調用者btn
28             // btn.onclick = function(){};
29             //點擊按鈕就可以調用這個函數
30             //5.定時器函數 this指向window
31             setInterval(function(){},1000);
32             //這個函數是定時器自動每秒鍾調用一次
33             //6.立即執行函數this指向window
34             (function(){console.log("怎么也飛不出,花花的世界~~~")})()
35             //立即執行函數是自動調用
36         </script>
37     </body>
38 </html>
  • 改變函數內部this指向

    JavaScript為我們提供了一些函數方法幫助我們改變函數內部this指向問題,常用的有bind()、call()、apply()三種方法

    • call方法

      call方法調用一個對象,簡單理解為調用函數的方式,但是它可以改變函數的this指向

    • apply()方法
      • fun.apply(thisArg,[argsArray])
      • thisArg:在fun函數運行時指定的this值
      • argsArray:傳遞的值,必須包含在數組里面
      • 返回值值就是函數的返回值,因為它必須是調用函數
    • bind()方法:不會調用函數
      • fun.bind(thisArg,arg1,arg2,…)
      • thisArg:在fun函數運行時指定this的值
      • arg1、arg2:傳遞其他參數
      • 返回由指定的this值和初始化參數改造的原函數拷貝
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script type="text/javascript">
            //改變函數內this指向,js提供了三種方式call()、apply()、bind()
            //1.call()
            var o = {
                name: 'bbh'
            };
            function fn(arr,num){
                console.log(this);
                console.log(arr+num)
            }
            // fn.call(o);
            //call第一個可以調用函數,第二個可以改變函數內部的this指向
            //call的主要作用可以實現繼承
            //2.apply()應用運用的意思
            // fn.apply(o,['bbh','56']);
            //(1)也是調用函數,第二個可以改變函數內部的this指向
            //(2)但是他的參數必須是數組、偽數組
            //(3)apply的主要應用比如我們可以利用apply借助於數學內置對象找最大值
            //3.bind()綁定捆綁的意思
            var res = fn.bind(o);
            //(1)不會調用原來的函數 可以改變原來函數內部this指向
            //(2)返回的是原函數改變this之后產生的新函數
            console.log(res);
        </script>
    </body>
</html>
  • bind方法應用
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <button>點擊</button>
 9         <script type="text/javascript">
10             //1.如果有的函數我們不需要立即調用,但是又想改變函數內部的this指向
11             //2.我們有一個按鈕當我們點擊了之后就禁用這個按鈕,3秒之后啟動
12             var btn = document.querySelector("button");
13             btn.onclick = function(){
14                 this.disabled = true;
15                 setTimeout(function(){
16                     this.disabled = false;
17                     //這個this指向的btn
18                 }.bind(this),3000)
19             }
20         </script>
21     </body>
22 </html>
  • call、apply、bind總結
    • 相同點
      • 都可以改變函數內部的this指向
    • 區別點
      • call和apply會調用函數,並且改變函數內部this指向
      • call和apply傳遞的參數不一樣,call傳遞參數arg1,arg2,…形式,apply必須數組形式[arg]
      • bind不會調用函數,可以改變函數內部this指向
    • 主要應用場景
      • call經常做繼承
      • apply經常跟數組有關系,比如借助數學對象實現數組最大值和最小值
      • bind不調用函數,但是還想改變this指向,比如改變定時器里的this指向

2.嚴格模式

  JavaScript除了提供正常模式外,還提供了嚴格模式(strict mode)。即在嚴格的條件下運行JS代碼

  • 嚴格模式
    • 消除了JavaScript語法的一些不合理,不嚴謹之處,減少了一些怪異行為
    • 消除代碼運行的一些不安全之處,保證代碼運行的安全
    • 提高編譯器效率,增加運行速度
    • 禁用了在ECMAScript的未來版本中可能會使用的一些語法,例如一些保留字:class
  • 開啟嚴格模式:嚴格模式可以應用到整個腳本或個別函數中。我們價格嚴格模式分為腳本開啟嚴格模式和函數開啟嚴格模式
    • 腳本開啟嚴格模式
      • 為整個腳本文件開啟嚴格模式,需要在所有語句之前放一個特定語句"use strict"
    • 函數開啟嚴格模式
      • 需要把"use strict"聲明放在函數題所有語句之前
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <!-- 為整個腳本(script標簽)開啟嚴格模式 -->
 9         <script type="text/javascript">
10             'use strict';
11             //下面的js代碼會按照嚴格模式執行代碼
12         </script>
13         <script type="text/javascript">
14             (function(){
15                 'use strict';
16             })()
17         </script>
18         <!-- 為某個函數開啟嚴格模式 -->
19         <script type="text/javascript">
20             function fn(){
21                 //此時只是給函數fn開啟嚴格模式
22                 'use strict';
23             }
24             function fun(){
25                 //里面還是按照普通模式執行
26             }
27         </script>
28     </body>
29 </html>
  • 嚴格模式中的變化
    • 變量規定
      • 嚴格模式中,變量都必須先用var聲明,然后再使用
      • 嚴禁刪除已經聲明的變量
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <!-- 為整個腳本(script標簽)開啟嚴格模式 -->
 9         <script type="text/javascript">
10             'use strict';
11             //下面的js代碼會按照嚴格模式執行代碼
12             //1.變量名必須先聲明再使用
13             // num = 1;
14             // console.log(num);// num is not defined
15             //2.我們不能隨意刪除已經聲明好的變量
16             // var num = 10;
17             // delete num;//Delete of an unqualified identifier in strict mode
18             
19         </script>
20         
21     </body>
22 </html
    • 嚴格模式下this指向問題
      • 嚴格模式下全局作用域中的函數this指向的是undefined
      • 嚴格模式下,如果構造函數不加new調用,this就會報錯
    • 函數變化
      • 函數不能有重名的參數
      • 函數必須聲明在頂層,不允許在非函數代碼塊內聲明函數

 3.高階函數

  高階函數是對其他函數進行操作的函數,它接收函數作為參數或將函數作為返回值輸出

  • 函數作為參數傳遞
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //高階函數-函數可以作為參數傳遞
10             function fn(a,b,callback){
11                 console.log(a+b);
12                 callback&&callback();
13             }
14             fn(1,2,function(){
15                 console.log("success");
16             });
17         </script>
18     </body>
19 </html>
  • 閉包

  閉包指有權訪問另一個函數作用域中的變量的函數

 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //閉包(closure)指有權訪問另一個函數作用域中變量的函數
10             //閉包:我們fun這個函數作用域 訪問了另外一個函數fn里面的局部變量
11             //我們fn 外面的作用域可以訪問fn,內部的額局部變量
12             //閉包的主要作用,延伸了變量的作用范圍
13             function fn(){
14                 var num = 10;
15                 function fun(){
16                     console.log(num);
17                 }
18                 return fun;
19             }
20             var f = fn();
21             /*  
22                 類似於
23                 f = function fun(){
24                     console.log(num);
25                 }
26             */
27            f();
28         </script>
29     </body>
30 </html>
  • 循環注冊點擊事件
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <ul class="nav">
 9             <li>榴蓮</li>
10             <li>臭豆腐</li>
11             <li>鯡魚罐頭</li>
12             <li>大豬蹄子</li>
13         </ul>
14         <script type="text/javascript">
15             //閉包應用-點擊li輸出當前li的索引號
16             var lis = document.querySelectorAll(".nav li");
17             //1.利用動態添加屬性的方式
18             // for(var i = 0 ; i < lis.length ; i++){
19             //     lis[i].index = i;
20             //     lis[i].onclick = function(){
21             //         console.log(this.index);
22             //     }
23             // }
24             //2.利用閉包的方式得到當前小li的索引號
25             for(var i = 0 ; i < lis.length ; i++){
26                 //利用for循環創建了4個執行函數
27                 (function(i){
28                     lis[i].onclick = function(){
29                         console.log(i);
30                     }
31                 })(i);
32             }
33         </script>
34     </body>
35 </html>
  • 定時器中的閉包
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <ul class="nav">
 9             <li>榴蓮</li>
10             <li>臭豆腐</li>
11             <li>鯡魚罐頭</li>
12             <li>大豬蹄子</li>
13         </ul>
14         <script type="text/javascript">
15             //閉包應用-3秒鍾之后,打印所有li元素的內容
16             var lis = document.querySelectorAll(".nav li");
17             for(var i = 0 ; i < lis.length ; i++){
18                 (function(i){
19                     setTimeout(function(){
20                         console.log(lis[i].innerText);
21                     },3000);
22                 })(i)
23             }
24         </script>
25     </body>
26 </html>
  • 打車價格
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //閉包應用-計算打車價格
10             //打車起步價13(3公里內),之后每多一公里增加5塊錢,用戶輸入公里數就可以計算打車價格
11             //如果有擁堵情況,總價格多收取10塊錢擁堵費
12             var res = (function(){
13                 var start = 13;//起步價
14                 var total = 0;//總價
15                 return {
16                     price: function(n){//正常價格
17                         if(n <= 3)
18                             total = 13;
19                         else{
20                             total = (n-3)*5 + 13;
21                         }
22                         return total;
23                     },
24                     yongdu: function(flag){//擁堵價格
25                         return flag ? total+10 : total;
26                     }
27                 }
28             })();
29             console.log(res.price(5));
30             console.log(res.yongdu(true));
31         </script>
32     </body>
33 </html>
  • 閉包總結
    • 閉包是一個函數(一個作用域可以訪問另一個函數的作用域)
    • 閉包的作用:延伸變量的作用范圍

4.遞歸

  如果一個函數可以在內部調用其本身,這個函數就是遞歸函數

 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //遞歸函數:函數內部自己調用自己,這個函數就是遞歸函數
10             //由於遞歸很容易發生“棧溢出”錯誤,所以必須要加退出條件(return)
11             var num = 0;
12             function fn(){
13                 console.log("bbh");
14                 if(num == 5){
15                     return;//遞歸函數里面必須添加退出條件
16                 }
17                 num++;
18                 fn();
19             }
20             fn();
21         </script>
22     </body>
23 </html>
  • 利用遞歸函數求解數學題
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //遞歸函數:函數內部自己調用自己,這個函數就是遞歸函數
10             //由於遞歸很容易發生“棧溢出”錯誤,所以必須要加退出條件(return)
11             function fn(n){
12                 if(n == 1){
13                     return 1;
14                 }
15                 return n*fn(n-1);
16             }
17             var res = fn(3);
18             console.log(res);
19         </script>
20     </body>
21 </html>
  • 利用遞歸求斐波那契序列
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script type="text/javascript">
            //利用遞歸函數求斐波那契序列
            //用戶輸入一個數字n,就可以求出這個數字對應的兔子序列值
            function fn(n){
                if(n == 1 || n == 2){
                    return 1;
                }else{
                    return fn(n-1)+fn(n-2);
                }
            }    
            console.log(fn(8))
        </script>
    </body>
</html>
  • 根據id返回數據對象
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //根據id返回數據對象
10             var data = [{
11                     id: 1,
12                     name: '家電',
13                     goods: [{
14                         id: 11,
15                         gname: '冰箱'
16                     }, {
17                         id: 22,
18                         gname: '洗衣機',
19                         goods: [{
20                                 id: 2201,
21                                 gname: '滾筒洗衣機'
22                             },
23                             {
24                                 id: 2202,
25                                 gname: '壁掛洗衣機'
26                             }
27                         ]
28                     }]
29                 },
30                 {
31                     id: 2,
32                     name: '服飾'
33                 }
34             ]
35             //我們想要做輸入id號,就可以返回數據對象
36             //1.利用foreach遍歷里面的每一個對象
37             function getId(json, id) {
38                 var res = {};
39                 json.some(function(value) {
40                     if (value.id == id) {
41                         res = value;
42                         return value.id == id;
43                     } else if(value.goods && value.goods.length > 0){
44                             res = getId(value.goods, id);
45                     }
46                 });
47                 return res;
48             }
49             console.log(getId(data, 2202));
50         </script>
51     </body>
52 </html>
  • 深拷貝和淺拷貝
    • 淺拷貝知識拷貝一層,更深層次對象級別的只拷貝引用
    • 深拷貝拷貝多層,每一級別的額數據都會拷貝
    • 淺拷貝
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             var obj = {
10                 id: 1,
11                 name: 'bbh',
12                 msg: {
13                     age:18
14                 }
15             };
16             var o = {};
17             // for(var k in obj){
18             //     o[k] = obj[k];
19             // }
20             // o.msg.age = 30;
21             // console.log(o);
22             // console.log(obj);
23             console.log("---------------------");
24             //ES6提供的淺拷貝語法糖
25             //注意:淺拷貝只拷貝一層,當拷貝的數據里還存在復雜類型數據時,
26             //只會拷貝其地址,對數據進行修改時會影響到原來的數據
27             Object.assign(o,obj);
28             o.msg.age = 30;
29             console.log(obj);
30             console.log(o);
31         </script>
32     </body>
33 </html>
    • 深拷貝
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             var obj = {
10                 id: 1,
11                 name: 'bbh',
12                 msg: {
13                     age:18
14                 },
15                 sing: function(){
16                     
17                 }
18             };
19             var o = {};
20             function fn(obj,o){
21                 for(k in obj){
22                     //判斷屬性值屬於哪種數據類型
23                     //1.獲取屬性值 obj[k]
24                     //2.判斷這個值是否為數組
25                     //3.判斷是否為對象
26                     if(obj[k] instanceof Array){
27                         o[k] = [];
28                         fn(obj[k],o[k]);
29                     }else if(obj[k] instanceof Object){
30                         o[k] = {};
31                         fn(obj[k],o[k]);
32                     }else{
33                         o[k] = obj[k];
34                     }
35                 }
36             }
37             //深拷貝封裝函數
38             fn(obj,o);
39             o.msg.age = 30;
40             console.log(o);
41             console.log(obj);
42         </script>
43     </body>
44 </html>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM