JavaScript高級

1.編程思想

2.對象與類

3.面向?qū)ο蟀鎡ab 欄切換

4.構(gòu)造函數(shù)和原型

5.繼承

6.ES5新增方法

7.函數(shù)的定義和調(diào)用

8.this

9.嚴(yán)格模式

10.高階函數(shù)

11.閉包

12.遞歸

13.正則表達(dá)式概述

14.正則表達(dá)式在js中的使用

15.正則表達(dá)式中的特殊字符

16. ES6相關(guān)概念

17. ES6新增語法

18. ES6 的內(nèi)置對象擴(kuò)展

1.編程思想

1.1面向過程POP

  • 面向過程就是分析出解決問題所需要的步驟懒熙,然后用函數(shù)把這些步驟一步一步實(shí)現(xiàn),使用的時候再一個一個的依次調(diào)用就可以了
  • 類似蛋炒飯

1.2面向?qū)ο?/h3>
  • 面向?qū)ο笫前咽聞?wù)分解成為一個個對象,然后由對象之間分工與合作
  • 特性:封裝性、繼承性洁奈、多態(tài)性
  • 類似蓋澆飯

1.3面向過程與面向?qū)ο髮Ρ?/h3>
面向過程 面向?qū)ο?/th>
優(yōu)點(diǎn) 性能比面向?qū)ο蟾?/strong>诊赊,適合跟硬件聯(lián)系很緊密的東西,例如單片機(jī)就采用的面向過程編程夺谁。 易維護(hù)、易復(fù)用肉微、易擴(kuò)展匾鸥,由于面向?qū)ο笥蟹庋b、繼承碉纳、多態(tài)性的特性勿负,可以設(shè)計(jì)出低耦合的系統(tǒng),使系統(tǒng) 更加靈活劳曹、更加易于維護(hù)
缺點(diǎn) 不易維護(hù)奴愉、不易復(fù)用琅摩、不易擴(kuò)展 性能比面向過程低

2.對象與類

面向?qū)ο蟮乃季S特點(diǎn):

  • 抽象對象的屬性和行為組成一個類
  • 通過類的實(shí)例化,可以得到一個類的對象

2.1對象

對象是由屬性和方法組成的:是一個無序鍵值對的集合锭硼,指的是一個具體的事物

  • 屬性:事物的特征房资,在對象中用屬性來表示(常用名詞)
  • 方法:事物的行為,在對象中用方法來表示(常用動詞)

2.1.1創(chuàng)建對象

//以下代碼是對對象的復(fù)習(xí)
//字面量創(chuàng)建對象
var ldh = {
    name: '劉德華',
    age: 18
}
console.log(ldh);//{ name: '劉德華', age: 18}

//構(gòu)造函數(shù)創(chuàng)建對象
  function Star(name, age) {
    this.name = name;
    this.age = age;
 }
var ldh = new Star('劉德華', 18)//實(shí)例化對象
console.log(ldh);   //Star{ name: '劉德華', age: 18}

2.2類

  • 在 ES6 中新增加了類的概念账忘,可以使用 class 關(guān)鍵字聲明一個類志膀,之后以這個類來實(shí)例化對象。類抽象了對象的公共部分鳖擒,它泛指某一大類(class),對象特指某一個溉浙,通過類實(shí)例化一個具體的對象

2.2.1創(chuàng)建類

  1. 語法:
//步驟1 使用class關(guān)鍵字
class name {
  // class body
}     
//步驟2使用定義的類創(chuàng)建實(shí)例  注意new關(guān)鍵字
var xx = new name();     
  1. 示例
 // 1. 創(chuàng)建類 class  創(chuàng)建一個 明星類
 class Star {
   // 類的共有屬性放到 constructor 里面
   constructor(name, age) {
   this.name = name;
   this.age = age;
   }
 }
   // 2. 利用類創(chuàng)建對象 new
   var ldh = new Star('劉德華', 18);
   console.log(ldh);//Star{ name: '劉德華', age: 18}

通過結(jié)果我們可以看出,運(yùn)行結(jié)果和使用構(gòu)造函數(shù)方式一樣

2.2.2類添加屬性和方法

 // 1. 創(chuàng)建類 class  創(chuàng)建一個類
class Star {
    // 類的共有屬性放到 constructor 里面 constructor是 構(gòu)造器或者構(gòu)造函數(shù)
    constructor(uname, age) {
      this.uname = uname;
      this.age = age;
    }//------------------------------------------->注意,方法與方法之間不需要添加逗號
    sing(song) {
      console.log(this.uname + '唱' + song);
    }
}
// 2. 利用類創(chuàng)建對象 new
var ldh = new Star('劉德華', 18);
console.log(ldh); // Star {uname: "劉德華", age: 18}
ldh.sing('冰雨'); // 劉德華唱冰雨

注意喲:

  1. 通過class 關(guān)鍵字創(chuàng)建類, 類名我們還是習(xí)慣性定義首字母大寫
  2. 類里面有個constructor 函數(shù),可以接受傳遞過來的參數(shù),同時返回實(shí)例對象
  3. constructor 函數(shù) 只要 new 生成實(shí)例時,就會自動調(diào)用這個函數(shù), 如果我們不寫這個函數(shù),類也會自動生成這個函數(shù)
  4. 多個函數(shù)方法之間不需要添加逗號分隔
  5. 生成實(shí)例 new 不能省略
  6. 語法規(guī)范, 創(chuàng)建類 類名后面不要加小括號,生成實(shí)例 類名后面加小括號, 構(gòu)造函數(shù)不需要加function

2.2.3類的繼承

  1. 語法
// 父類
class Father {   
} 

// 子類繼承父類
class Son extends Father {  
}       
  1. 示例
class Father {
      constructor(surname) {
        this.surname= surname;
      }
      say() {
        console.log('你的姓是' + this.surname);
       }
}

class Son extends Father{  // 這樣子類就繼承了父類的屬性和方法
}
var damao= new Son('劉');
damao.say();      //結(jié)果為 你的姓是劉
  • 子類使用super關(guān)鍵字訪問父類的方法

    //定義了父類
    class Father {
       constructor(x, y) {
           this.x = x;
           this.y = y;
       }
       sum() {
           console.log(this.x + this.y);
      }
     }
    //子元素繼承父類
        class Son extends Father {
               constructor(x, y) {
              super(x, y); //使用super調(diào)用了父類中的構(gòu)造函數(shù)
          }
            //sum() {
            //   super.sum();
            //}
        }
      var son = new Son(1, 2);
        son.sum(); //結(jié)果為3
    
  
**注意:** 
  
1. 繼承中,如果實(shí)例化子類輸出一個方法,先看子類有沒有這個方法,如果有就先執(zhí)行子類的
  
2. 繼承中,如果子類里面沒有,就去查找父類有沒有這個方法,如果有,就執(zhí)行父類的這個方法(就近原則)
  
  3. 如果子類想要繼承父類的方法,同時在自己內(nèi)部擴(kuò)展自己的方法,利用super 調(diào)用父類的構(gòu)造函數(shù),super 必須在子類this之前調(diào)用
  
     ```js
      // 父類有加法方法
      class Father {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
        sum() {
             console.log(this.x + this.y);
        }
      }
      // 子類繼承父類加法方法 同時 擴(kuò)展減法方法
      class Son extends Father {
        constructor(x, y) {
        // 利用super 調(diào)用父類的構(gòu)造函數(shù) super 必須在子類this之前調(diào)用,放到this之后會報錯
          super(x, y);
            this.x = x;
            this.y = y;
  
           }
           subtract() {
                 console.log(this.x - this.y);
           }
     }
     var son = new Son(5, 3);
     son.subtract(); //2
   son.sum();//8
  1. 時刻注意this的指向問題,類里面的共有的屬性和方法一定要加this使用.

    1. constructor中的this指向的是new出來的實(shí)例對象
    2. 自定義的方法,一般也指向的new出來的實(shí)例對象
    3. 綁定事件之后this指向的就是觸發(fā)事件的事件源
class Star {
             constructor(uname, age) {
                 //1. constructor 里面的this 指向的是 創(chuàng)建的實(shí)例對象
                 that = this;
                 console.log(this);
 
                 this.uname = uname;
                 this.age = age;
                 // this.sing();4.共有的屬性和方法一定要加this使用
                 this.btn = document.querySelector('button');
                 this.btn.onclick = this.sing;
             }
             sing() {
                 // 2.sing方法里面的this 指向 btn 按鈕,因?yàn)檫@個按鈕調(diào)用了這個函數(shù)
                 console.log(this);//<button>點(diǎn)擊</button> 
               console.log(this.uname);//undefined btn沒有uname屬性
                 console.log(that.uname); // 劉德華 指向constructor的this
             }
             dance() {
                 // 2. dance里面的this 指向?qū)嵗龑ο?ldh 因?yàn)閘dh 調(diào)用了這個函數(shù)
                 _that = this;
                 console.log(this);
 
             }
         }
 var ldh = new Star('劉德華');
 console.log(that === ldh);//true
 console.log(_that === ldh);//true
 ```
  1. 在 ES6 中類沒有變量提升,所以必須先定義類蒋荚,才能通過類實(shí)例化對象

3.面向?qū)ο蟀鎡ab 欄切換

3.1功能需求

  1. 點(diǎn)擊 tab欄,可以切換效果.
  2. 點(diǎn)擊 + 號, 可以添加 tab 項(xiàng)和內(nèi)容項(xiàng).
  3. 點(diǎn)擊 x 號, 可以刪除當(dāng)前的tab項(xiàng)和內(nèi)容項(xiàng).
  4. 雙擊tab項(xiàng)文字或者內(nèi)容項(xiàng)文字可以修改里面的文字內(nèi)容

3.2案例準(zhǔn)備

  1. 獲取到標(biāo)題元素
  2. 獲取到內(nèi)容元素
  3. 獲取到刪除的小按鈕 x號
  4. 新建js文件,定義類,添加需要的屬性方法(切換,刪除,增加,修改)
  5. 時刻注意this的指向問題

3.3切換

  • 為獲取到的標(biāo)題綁定點(diǎn)擊事件,展示對應(yīng)的內(nèi)容區(qū)域,存儲對應(yīng)的索引

     this.lis[i].index = i;
     this.lis[i].onclick = this.toggleTab;
    
  • 使用排他,實(shí)現(xiàn)只有一個元素的顯示

     toggleTab() {
       //將所有的標(biāo)題與內(nèi)容類樣式全部移除
         for (var i = 0; i < this.lis.length; i++) {
         this.lis[i].className = '';
         this.sections[i].className = '';
         }
       //為當(dāng)前的標(biāo)題添加激活樣式
         this.className = 'liactive';
        //為當(dāng)前的內(nèi)容添加激活樣式
         that.sections[this.index].className = 'conactive';
      }
    

3.4添加

  • 為添加按鈕+ 綁定點(diǎn)擊事件

     this.add.onclick = this.addTab;
    
  • 實(shí)現(xiàn)標(biāo)題與內(nèi)容的添加,做好排他處理

    addTab() {
        that.clearClass();
        // (1) 創(chuàng)建li元素和section元素 
        var random = Math.random();
        var li = '<li class="liactive"><span>新選項(xiàng)卡</span><span class="iconfont icon-guanbi">               </span></li>';
        var section = '<section class="conactive">測試 ' + random + '</section>';
        // (2) 把這兩個元素追加到對應(yīng)的父元素里面戳稽,appendChild()不能追加字符串,需要createElement()創(chuàng)建元素期升,insertAdjacentHTML()可以直接追加字符串
        that.ul.insertAdjacentHTML('beforeend', li);
        that.fsection.insertAdjacentHTML('beforeend', section);
        that.init();
        }
    

3.5刪除

  • 為元素的刪除按鈕x綁定點(diǎn)擊事件

     this.remove[i].onclick = this.removeTab;
    
  • 獲取到點(diǎn)擊的刪除按鈕的所在的父元素的所有,刪除對應(yīng)的標(biāo)題與內(nèi)容

     removeTab(e) {
         e.stopPropagation(); // 阻止冒泡 防止觸發(fā)li 的切換點(diǎn)擊事件
         var index = this.parentNode.index;
         console.log(index);
         // 根據(jù)索引號刪除對應(yīng)的li 和section   remove()方法可以直接刪除指定的元素
         that.lis[index].remove();
         that.sections[index].remove();
         that.init();
         // 當(dāng)我們刪除的不是選中狀態(tài)的li 的時候,原來的選中狀態(tài)li保持不變
         if (document.querySelector('.liactive')) return;
         // 當(dāng)我們刪除了選中狀態(tài)的這個li 的時候, 讓它的前一個li 處于選定狀態(tài)
         index--;
         // 手動調(diào)用我們的點(diǎn)擊事件  不需要鼠標(biāo)觸發(fā)
         that.lis[index] && that.lis[index].click();
     }
    

3.6編輯

  • 為元素(標(biāo)題與內(nèi)容)綁定雙擊事件

     this.spans[i].ondblclick = this.editTab;
     this.sections[i].ondblclick = this.editTab;
    
  • 在雙擊事件處理文本選中狀態(tài),修改內(nèi)部DOM節(jié)點(diǎn),實(shí)現(xiàn)新舊value值的傳遞

    editTab() {
        var str = this.innerHTML;
        // 雙擊禁止選定文字
        window.getSelection ? window.getSelection().removeAllRanges() :                   document.selection.empty();
        // alert(11);
          this.innerHTML = '<input type="text" />';
          var input = this.children[0];
          input.value = str;
          input.select(); // 文本框里面的文字處于選定狀態(tài)
          // 當(dāng)我們離開文本框就把文本框里面的值給span 
          input.onblur = function() {
              this.parentNode.innerHTML = this.value;
          };
          // 按下回車也可以把文本框里面的值給span
          input.onkeyup = function(e) {
              if (e.keyCode === 13) {
                  // 手動調(diào)用表單失去焦點(diǎn)事件  不需要鼠標(biāo)離開操作 不用加on-
                    this.blur();
              }
        }
    }
    

4.構(gòu)造函數(shù)和原型

4.1對象的三種創(chuàng)建方式--復(fù)習(xí)

  1. 字面量方式

    var obj = {};
    
  2. new關(guān)鍵字

    var obj = new Object();
    
  3. 構(gòu)造函數(shù)方式

    function Person(name,age){
      this.name = name;
      this.age = age;
    }
    var obj = new Person('zs',12);
    

new執(zhí)行時做的4件事:

  • 在內(nèi)存中創(chuàng)建一個新的空對象
  • 將this指向創(chuàng)建的對象
  • 執(zhí)行構(gòu)造函數(shù)時惊奇,給新對象添加屬性和方法
  • 返回這個新對象(所以構(gòu)造函數(shù)不需要return)

4.2靜態(tài)成員和實(shí)例成員

4.2.1實(shí)例成員

實(shí)例成員就是構(gòu)造函數(shù)內(nèi)部通過this添加的成員 uname age sing 就是實(shí)例成員,實(shí)例成員只能通過實(shí)例化的對象來訪問

 function Star(uname, age) {
     this.uname = uname;
     this.age = age;
     this.sing = function() {
     console.log('我會唱歌');
    }
}
var ldh = new Star('劉德華', 18);
console.log(ldh.uname);//實(shí)例成員只能通過實(shí)例化的對象來訪問

4.2.2靜態(tài)成員

靜態(tài)成員 在構(gòu)造函數(shù)本身上添加的成員 sex 就是靜態(tài)成員,靜態(tài)成員只能通過構(gòu)造函數(shù)來訪問

 function Star(uname, age) {
     this.uname = uname;
     this.age = age;
     this.sing = function() {
     console.log('我會唱歌');
    }
}
Star.sex = '男';
var ldh = new Star('劉德華', 18);
console.log(Star.sex);//靜態(tài)成員只能通過構(gòu)造函數(shù)來訪問

4.3構(gòu)造函數(shù)的問題

構(gòu)造函數(shù)方法很好用,但是存在浪費(fèi)內(nèi)存的問題播赁。

img1.png

4.4構(gòu)造函數(shù)原型prototype

構(gòu)造函數(shù)通過原型分配的函數(shù)是所有對象所共享的颂郎。

JavaScript 規(guī)定,每一個構(gòu)造函數(shù)都有一個prototype 屬性容为,prototype就是一個對象乓序,這個對象的所有屬性和方法,都會被構(gòu)造函數(shù)所擁有

我們可以把那些不變的方法坎背,直接定義在 prototype 對象上替劈,這樣所有對象的實(shí)例就可以共享這些共有的方法

function Star(uname, age) {//共有的屬性定義在構(gòu)造函數(shù)內(nèi)
    this.uname = uname;
    this.age = age;
}
Star.prototype.sing = function() {//共有的方法定位在原型對象上
    console.log('我會唱歌');
}
var ldh = new Star('劉德華', 18);
var zxy = new Star('張學(xué)友', 19);
ldh.sing();//我會唱歌
zxy.sing();//我會唱歌

4.5對象原型

為什么構(gòu)造函數(shù)實(shí)例化的對象,可以使用構(gòu)造函數(shù)原型對象的方法?

因?yàn)閷ο蠖紩幸粋€屬性 __proto__ 指向構(gòu)造函數(shù)的 prototype 原型對象,即ldh.__proto__ === Star.prototype阴挣,當(dāng)實(shí)例化對象內(nèi)部找不到某方法富玷,就會到__proto__去找

__proto__對象原型和原型對象 prototype 是等價的
__proto__對象原型的意義就在于為對象的查找機(jī)制提供一個方向,或者說一條路線,但是它是一個非標(biāo)準(zhǔn)屬性,因此實(shí)際開發(fā)中,不可以使用這個屬性坛猪,它只是內(nèi)部指向原型對象 prototype
img3.png

4.6constructor構(gòu)造函數(shù)

對象原型( __proto__)和構(gòu)造函數(shù)(prototype)原型對象里面都有一個屬性 constructor 屬性 ,constructor 我們稱為構(gòu)造函數(shù)皂股,因?yàn)樗富貥?gòu)造函數(shù)本身墅茉。
constructor 主要用于記錄該對象引用于哪個構(gòu)造函數(shù),它可以讓原型對象重新指向原來的構(gòu)造函數(shù)。
一般情況下就斤,對象的方法都在構(gòu)造函數(shù)的原型對象中設(shè)置悍募。如果有多個對象的方法,我們可以給原型對象采取對象形式賦值洋机,但是這樣就會覆蓋構(gòu)造函數(shù)原型對象原來的內(nèi)容坠宴,這樣修改后的原型對象 constructor  就不再指向當(dāng)前構(gòu)造函數(shù)了。此時绷旗,我們可以在修改后的原型對象中喜鼓,添加一個 constructor 指向原來的構(gòu)造函數(shù)。

如果我們修改了原來的原型對象,給原型對象賦值的是一個對象,則必須手動的利用constructor指回原來的構(gòu)造函數(shù)如:

 function Star(uname, age) {
     this.uname = uname;
     this.age = age;
 }
 // 很多情況下,我們需要手動的利用constructor 這個屬性指回 原來的構(gòu)造函數(shù)
 Star.prototype = {
 // 如果我們修改了原來的原型對象,給原型對象賦值的是一個對象,則必須手動的利用constructor指回原來的構(gòu)造函數(shù)
   constructor: Star, // 手動設(shè)置指回原來的構(gòu)造函數(shù)
   sing: function() {
     console.log('我會唱歌');
   },
   movie: function() {
     console.log('我會演電影');
   }
}
var zxy = new Star('張學(xué)友', 19);
console.log(zxy)

以上代碼運(yùn)行結(jié)果,設(shè)置constructor屬性如圖:

img8.png
img9.png

4.7原型鏈

    每一個實(shí)例對象又有一個__proto__屬性衔肢,指向的構(gòu)造函數(shù)的原型對象庄岖,構(gòu)造函數(shù)的原型對象也是一個對象,也有__proto__屬性角骤,這樣一層一層往上找就形成了原型鏈隅忿。
img5.png

4.8構(gòu)造函數(shù)實(shí)例和原型對象三角關(guān)系

1.構(gòu)造函數(shù)的prototype屬性指向了構(gòu)造函數(shù)原型對象
2.實(shí)例對象是由構(gòu)造函數(shù)創(chuàng)建的,實(shí)例對象的__proto__屬性指向了構(gòu)造函數(shù)的原型對象
3.構(gòu)造函數(shù)的原型對象的constructor屬性指向了構(gòu)造函數(shù),實(shí)例對象的原型的constructor屬性也指向了構(gòu)造函數(shù)
img4.png

1.9原型鏈和成員的查找機(jī)制

任何對象都有原型對象,也就是prototype屬性,任何原型對象也是一個對象,該對象就有proto屬性,這樣一層一層往上找,就形成了一條鏈,我們稱此為原型鏈;

1.當(dāng)訪問一個對象的屬性(包括方法)時,首先查找這個對象自身有沒有該屬性邦尊。
2.如果沒有就查找該對象的原型(也就是 __proto__指向的 prototype 原型對象)背桐。
3.如果還沒有就查找原型對象的原型(Object的原型對象)。
4.依此類推一直找到 Object 為止(null)蝉揍。
5.__proto__對象原型的意義就在于為對象成員查找機(jī)制提供一個方向链峭,或者說一條路線。

4.10原型對象中this指向

構(gòu)造函數(shù)中的this和原型對象的this,都指向我們new出來的實(shí)例對象

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
}
var that;
Star.prototype.sing = function() {
    console.log('我會唱歌');
    that = this;
}
var ldh = new Star('劉德華', 18);
// 1. 在構(gòu)造函數(shù)中,里面this指向的是對象實(shí)例 ldh
console.log(that === ldh);//true
// 2.原型對象函數(shù)又沾,里面的this 指向的是 實(shí)例對象 ldh

1.11通過原型為數(shù)組擴(kuò)展內(nèi)置方法

 Array.prototype.sum = function() {
   var sum = 0;
   for (var i = 0; i < this.length; i++) {
        sum += this[i];
   }
   return sum;
 };
 //此時數(shù)組對象中已經(jīng)存在sum()方法了  可以始終 數(shù)組.sum()進(jìn)行數(shù)據(jù)的求

5.繼承

5.1call()

  • call()可以調(diào)用函數(shù)
  • call()可以修改this的指向,使用call()的時候 參數(shù)一是修改后的this指向,參數(shù)2,參數(shù)3..使用逗號隔開連接
 function fn(x, y) {
     console.log(this);
     console.log(x + y);
}
  var o = {
    name: 'andy'
  };
  fn.call(o, 1, 2);//調(diào)用了函數(shù)此時的this指向了對象o,
//{name: "andy"}
//3

5.2子構(gòu)造函數(shù)繼承父構(gòu)造函數(shù)中的屬性

  1. 先定義一個父構(gòu)造函數(shù)
  2. 再定義一個子構(gòu)造函數(shù)
  3. 子構(gòu)造函數(shù)繼承父構(gòu)造函數(shù)的屬性(使用call方法)
 // 1. 父構(gòu)造函數(shù)
 function Father(uname, age) {
   // this 指向父構(gòu)造函數(shù)的對象實(shí)例
   this.uname = uname;
   this.age = age;
 }
  // 2 .子構(gòu)造函數(shù) 
function Son(uname, age, score) {
  // this 指向子構(gòu)造函數(shù)的對象實(shí)例
  // 3.使用call方式實(shí)現(xiàn)子繼承父的屬性
  Father.call(this, uname, age);
  this.score = score;
}
var son = new Son('劉德華', 18, 100);
console.log(son);
//Son{uname: "劉德華", age: 18, acore: 100}

5.3借用原型對象繼承方法

  1. 先定義一個父構(gòu)造函數(shù)
  2. 再定義一個子構(gòu)造函數(shù)
  3. 子構(gòu)造函數(shù)繼承父構(gòu)造函數(shù)的屬性(使用call方法)
// 1. 父構(gòu)造函數(shù)
function Father(uname, age) {
  // this 指向父構(gòu)造函數(shù)的對象實(shí)例
  this.uname = uname;
  this.age = age;
}
Father.prototype.money = function() {
  console.log(100000);
 };
 // 2 .子構(gòu)造函數(shù) 
  function Son(uname, age, score) {
      // this 指向子構(gòu)造函數(shù)的對象實(shí)例
      Father.call(this, uname, age);
      this.score = score;
  }
// Son.prototype = Father.prototype;  這樣直接賦值會有問題,如果修改了子原型對象,父原型對象也會跟著一起變化
  Son.prototype = new Father();
  // 如果利用對象的形式修改了原型對象,別忘了利用constructor 指回原來的構(gòu)造函數(shù)
  Son.prototype.constructor = Son;
  // 這個是子構(gòu)造函數(shù)專門的方法
  Son.prototype.exam = function() {
    console.log('孩子要考試');

  }
  var son = new Son('劉德華', 18, 100);
  console.log(son);

如上代碼結(jié)果如圖:

img12.png

6.ES5新增方法

6.1數(shù)組方法forEach遍歷數(shù)組

 arr.forEach(function(value, index, array) {
       //參數(shù)一是:數(shù)組元素
       //參數(shù)二是:數(shù)組元素的索引
       //參數(shù)三是:當(dāng)前的數(shù)組
 })
  //相當(dāng)于數(shù)組遍歷的 for循環(huán) 沒有返回值

6.2數(shù)組方法filter過濾數(shù)組

  var arr = [12, 66, 4, 88, 3, 7];
  var newArr = arr.filter(function(value, index,array) {
     //參數(shù)一是:數(shù)組元素
     //參數(shù)二是:數(shù)組元素的索引
     //參數(shù)三是:當(dāng)前的數(shù)組
     return value >= 20;
  });
  console.log(newArr);//[66,88] //返回值是一個新數(shù)組

3.3數(shù)組方法some

some 查找數(shù)組中是否有滿足條件的元素 
 var arr = [10, 30, 4];
 var flag = arr.some(function(value,index,array) {
    //參數(shù)一是:數(shù)組元素
     //參數(shù)二是:數(shù)組元素的索引
     //參數(shù)三是:當(dāng)前的數(shù)組
     return value < 3;
  });
console.log(flag);//false 返回值是布爾值,只要查找到滿足條件的一個元素就立馬終止循環(huán)

6.4篩選商品案例

  1. 定義數(shù)組對象數(shù)據(jù)

    var data = [{
                id: 1,
                pname: '小米',
                price: 3999
            }, {
                id: 2,
                pname: 'oppo',
                price: 999
            }, {
                id: 3,
                pname: '榮耀',
                price: 1299
            }, {
                id: 4,
                pname: '華為',
                price: 1999
            }, ];
    
  2. 使用forEach遍歷數(shù)據(jù)并渲染到頁面中

    data.forEach(function(value) {
      var tr = document.createElement('tr');
      tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>';
      tbody.appendChild(tr);
     });
    
  3. 根據(jù)價格篩選數(shù)據(jù)

    1. 獲取到搜索按鈕并為其綁定點(diǎn)擊事件

      search_price.addEventListener('click', function() {
      });
      
    2. 使用filter將用戶輸入的價格信息篩選出來

      search_price.addEventListener('click', function() {
            var newDate = data.filter(function(value) {
              //start.value是開始區(qū)間
              //end.value是結(jié)束的區(qū)間
                return value.price >= start.value && value.price <= end.value;
            });
            console.log(newDate);
       });
      
    3. 將篩選出來的數(shù)據(jù)重新渲染到表格中

      1. 將渲染數(shù)據(jù)的邏輯封裝到一個函數(shù)中

        function setDate(mydata) {
              // 先清空原來tbody 里面的數(shù)據(jù)
          tbody.innerHTML = '';
          mydata.forEach(function(value) {
            var tr = document.createElement('tr');
            tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>';
              tbody.appendChild(tr);
          });
         }
        
      2. 將篩選之后的數(shù)據(jù)重新渲染

         search_price.addEventListener('click', function() {
             var newDate = data.filter(function(value) {
             return value.price >= start.value && value.price <= end.value;
             });
             console.log(newDate);
             // 把篩選完之后的對象渲染到頁面中
             setDate(newDate);
        });
        
    4. 根據(jù)商品名稱篩選

      1. 獲取用戶輸入的商品名稱

      2. 為查詢按鈕綁定點(diǎn)擊事件,將輸入的商品名稱與這個數(shù)據(jù)進(jìn)行篩選

         search_pro.addEventListener('click', function() {
             var arr = [];
             data.some(function(value) {
               if (value.pname === product.value) {
                 // console.log(value);
                 arr.push(value);
                 return true; // return 后面必須寫true  
               }
             });
             // 把拿到的數(shù)據(jù)渲染到頁面中
             setDate(arr);
        })
        

6.5some和forEach區(qū)別

  • 如果查詢數(shù)組中唯一的元素, 用some方法更合適,在some 里面 遇到 return true 就是終止遍歷 迭代效率更高
  • 在forEach 里面 return 不會終止迭代

6.6trim方法去除字符串兩端的空格

var str = '   hello   '
console.log(str.trim())  //hello 去除兩端空格
var str1 = '   he l l o   '
console.log(str.trim())  //he l l o  去除兩端空格

6.7獲取對象的屬性名

Object.keys(對象) 獲取到當(dāng)前對象中的屬性名 弊仪,返回值是一個數(shù)組

 var obj = {
     id: 1,
     pname: '小米',
     price: 1999,
     num: 2000
};
var result = Object.keys(obj)
console.log(result)//[id,pname,price,num]

6.8Object.defineProperty

Object.defineProperty設(shè)置或修改對象中的屬性

Object.defineProperty(對象捍掺,修改或新增的屬性名撼短,{
        value:修改或新增的屬性的值,//不寫時默認(rèn)原來值
        writable:true/false,//如果值為false 不允許修改這個屬性值
        enumerable: false,//enumerable 如果值為false 則不允許遍歷
        configurable: false  //configurable 如果為false 則不允許刪除這個屬性 屬性是否可以被刪除或是否可以再次修改第三參數(shù){}特性
})  
var obj = {
            id: 1,
            pname: '小米',
            price: 1999
        };
        Object.defineProperty(obj, 'num', {
            value: 1000//1.value增
        });
        Object.defineProperty(obj, 'price', {
            value: 99//1.value改
        });
        Object.defineProperty(obj, 'id', {
            writable: false,//2.writable 無法修改id
        });
        obj.id = 2;//id改不了
        console.log(obj);
//結(jié)果:
        // { id: 1, pname: "小米", price: 99, num: 1000 }
var obj = {
            id: 1,
            pname: '小米',
            price: 1999
        };
        
        Object.defineProperty(obj, 'address', {
            value: "廣東佛山",
            writable: false,
            //3. 無法遍歷address
            enumerable: false,
        });
        console.log(obj);
        console.log(Object.keys(obj));//無address

        // { id: 1, pname: "小米", price: 1999, address: "廣東佛山" }
        // (3)["id", "pname", "price"]
var obj = {
            id: 1,
            pname: '小米',
            price: 1999
        };
        
        Object.defineProperty(obj, 'address', {
            value: "廣東佛山",
            writable: false,
            //4. 不允許被刪除 不允許修改第三個參數(shù)的特性 默認(rèn)false
            configurable: false,
        });
        console.log(obj);
        delete obj.pname;//可以刪除pname
        delete obj.address;//無法刪除address
        console.log(obj);
//{id: 1, pname: "小米", price: 1999, address: "廣東佛山"}
//{id: 1, price: 1999, address: "廣東佛山"}
Object.defineProperty(obj, 'address', {
            value: "廣東佛山",
            writable: false,
            //4. 不允許被刪除 不允許修改第三個參數(shù)的特性 默認(rèn)false
            configurable: false,
        });
        Object.defineProperty(obj, 'address', {
            value: "中國",
            writable: true,
            // 不允許被刪除 不允許修改第三個參數(shù)的特性 默認(rèn)false
            configurable: true,
        });
        console.log(obj);
//21-Object.defineProperty方法.html:25 Uncaught TypeError: Cannot redefine property: address
Object.defineProperty(obj, 'card', {
            value: "445281...",
            writable: false,
            // 可以修改第三個參數(shù)的特性 默認(rèn)不可以 false
            configurable: true,
        });
        console.log(obj);
        Object.defineProperty(obj, 'card', {
            value: "466666...",//可以改
            writable: true,//可以改
            configurable: true,//可以改
        });
        console.log(obj);
//{id: 1, price: 1999, address: "廣東佛山", card: "445281..."}
//{id: 1, price: 1999, address: "廣東佛山", card: "466666..."}

7.函數(shù)的定義和調(diào)用

1.1函數(shù)的定義方式

  1. 方式1 函數(shù)聲明方式 function 關(guān)鍵字 (命名函數(shù))

    function fn(){}
    
  2. 方式2 函數(shù)表達(dá)式(匿名函數(shù))

    var fn = function(){}
    
  3. 方式3 new Function()

    var f = new Function('a', 'b', 'console.log(a + b)');
    f(1, 2);
    
    var fn = new Function('參數(shù)1','參數(shù)2'..., '函數(shù)體')
    注意
    /*Function 里面參數(shù)都必須是字符串格式
    第三種方式執(zhí)行效率低再膳,也不方便書寫挺勿,因此較少使用
    所有函數(shù)都是 Function 的實(shí)例(對象)  
    函數(shù)也屬于對象
    */
    

7.2函數(shù)的調(diào)用

/* 1. 普通函數(shù) */
function fn() {
    console.log('人生的巔峰');
}
 fn(); 
/* 2. 對象的方法 */
var o = {
  sayHi: function() {
    console.log('人生的巔峰');
  }
}
o.sayHi();
/* 3. 構(gòu)造函數(shù)*/
function Star() {};
new Star();
/* 4. 綁定事件函數(shù)*/
 btn.onclick = function() {};   // 點(diǎn)擊了按鈕就可以調(diào)用這個函數(shù)
/* 5. 定時器函數(shù)*/
setInterval(function() {}, 1000);  這個函數(shù)是定時器自動1秒鐘調(diào)用一次
/* 6. 立即執(zhí)行函數(shù)(自調(diào)用函數(shù))*/
(function() {
    console.log('人生的巔峰');
})();

8.this

2.1函數(shù)內(nèi)部的this指向

這些 this 的指向,是當(dāng)我們調(diào)用函數(shù)的時候確定的喂柒。調(diào)用方式的不同決定了this 的指向不同

一般指向我們的調(diào)用者.

調(diào)用方式 this指向
普通函數(shù)調(diào)用 window
構(gòu)造函數(shù)調(diào)用 實(shí)例對象(原型對象中函數(shù)this也指向?qū)嵗龑ο螅?/td>
對象方法調(diào)用 該方法所屬的對象
事件綁定方法 綁定事件對象
計(jì)時器函數(shù) window
自調(diào)用函數(shù) window

8.2改變函數(shù)內(nèi)部 this 指向

8.2.1 call方法

call()方法調(diào)用一個對象不瓶。簡單理解為調(diào)用函數(shù),并改變函數(shù)的 this 指向

應(yīng)用場景: 經(jīng)常做繼承.

var o = {
    name: 'andy'
}
 function fn(a, b) {
      console.log(this);
      console.log(a+b)
};
fn(1,2)// 此時的this指向的是window 運(yùn)行結(jié)果為3
fn.call(o,1,2)//此時的this指向的是對象o,參數(shù)使用逗號隔開,運(yùn)行結(jié)果為3
//{name:'andy'}

8.2.2 apply方法

apply() 方法調(diào)用一個函數(shù)灾杰。簡單理解為調(diào)用函數(shù),并改變函數(shù)的 this 指向蚊丐。

應(yīng)用場景: 經(jīng)常跟數(shù)組有關(guān)系

var o = {
    name: 'andy'
}
 function fn(a, b) {
      console.log(this);
      console.log(a+b)
};
fn()// 此時的this指向的是window 運(yùn)行結(jié)果為3
fn.apply(o,[1,2])//此時的this指向的是對象o,參數(shù)使用數(shù)組傳遞 運(yùn)行結(jié)果為3
//{name:'andy'}

8.2.3 bind方法

bind() 方法不會調(diào)用函數(shù),但是能改變函數(shù)內(nèi)部this 指向,返回的是原函數(shù)改變this之后產(chǎn)生的新函數(shù)

如果只是想改變 this 指向,并且不想調(diào)用這個函數(shù)的時候艳吠,可以使用bind

應(yīng)用場景:不調(diào)用函數(shù),但是還想改變this指向

 var o = {
 name: 'andy'
 };

function fn(a, b) {
    console.log(this);
    console.log(a + b);
};
var f = fn.bind(o, 1, 2); //此處的f是bind返回的新函數(shù)
f();//調(diào)用新函數(shù)  this指向的是對象o 參數(shù)使用逗號隔開
//{name:'andy'} 3

8.2.4 call麦备、apply、bind三者的異同

  • 共同點(diǎn) : 都可以改變this指向
  • 不同點(diǎn):
    • call 和 apply 會調(diào)用函數(shù), 并且改變函數(shù)內(nèi)部this指向.
    • call 和 apply傳遞的參數(shù)不一樣,call(分別)傳遞參數(shù)使用逗號隔開,apply使用數(shù)組傳遞
    • bind 不會調(diào)用函數(shù), 可以改變函數(shù)內(nèi)部this指向.
  • 應(yīng)用場景
    1. call 經(jīng)常做繼承.
    2. apply經(jīng)常跟數(shù)組有關(guān)系. 比如借助于數(shù)學(xué)對象實(shí)現(xiàn)數(shù)組最大值最小值
    3. bind 不調(diào)用函數(shù),但是還想改變this指向. 比如改變定時器內(nèi)部的this指向.
var btns = document.querySelectorAll('.btn');
for(var i=0;i<btns.length;i++) {
    btn[i].addEventListener('click', function() {
        this.disabled = true;
        setTimeout(function() {
            this.disabled = false;//btns[i]四次i都是btn最后一個 不能用btns[i]
        }.bind(this), 3000);
    })
}

9.嚴(yán)格模式

9.1什么是嚴(yán)格模式

JavaScript 除了提供正常模式外,還提供了嚴(yán)格模式(strict mode)凛篙。ES5 的嚴(yán)格模式是采用具有限制性 JavaScript變體的一種方式黍匾,即在嚴(yán)格的條件下運(yùn)行 JS 代碼

嚴(yán)格模式在 IE10 以上版本的瀏覽器中才會被支持

嚴(yán)格模式對正常的 JavaScript 語義做了一些更改:

  • 1.消除了 js語法的一些不合理的地方,減少了一些怪異行為(變量不聲明 不能使用)
  • 2.消除代碼運(yùn)行的一些不安全之處呛梆,保證代碼運(yùn)行的安全
  • 3.提高編譯器效率锐涯,增加運(yùn)行速度
  • 4.禁用了在 ECMAScript 的未來版本中可能會定義的一些語法,為未來新版本的 Javascript 做好鋪墊填物。比如一些保留字如:class,enum,export, extends, import, super 不能做變量名

9.2開啟嚴(yán)格模式

嚴(yán)格模式可以應(yīng)用到整個腳本個別函數(shù)中纹腌。因此在使用時,我們可以將嚴(yán)格模式分為為腳本開啟嚴(yán)格模式為函數(shù)開啟嚴(yán)格模式兩種情況滞磺。

  • 情況一 :為腳本開啟嚴(yán)格模式

    (function (){
      //1.將整個腳本文件放在一個立即執(zhí)行的匿名函數(shù)之中升薯,在函數(shù)最前面添加"use strict";開啟嚴(yán)格模式,當(dāng)前函數(shù)之外還是普通模式
        "use strict";
           var num = 10;
        function fn() {}
    })();
    //或者 
    <script>
       "use strict"; //2.當(dāng)前script標(biāo)簽開啟了嚴(yán)格模式
    </script>
    <script>
                  //當(dāng)前script標(biāo)簽未開啟嚴(yán)格模式
    </script>
    
  • 情況二: 為函數(shù)開啟嚴(yán)格模式

    • 要給某個函數(shù)開啟嚴(yán)格模式雁刷,需要把“use strict”; (或 'use strict'; ) 聲明放在函數(shù)體所有語句之前

      function fn(){
        "use strict";
        return "123";
      } 
      //當(dāng)前fn函數(shù)開啟了嚴(yán)格模式
      

9.3嚴(yán)格模式中的變化

嚴(yán)格模式對 Javascript 的語法和行為覆劈,都做了一些改變

'use strict'
num = 10 
console.log(num)//1.嚴(yán)格模式后使用未聲明的變量 報錯
--------------------------------------------------------------------------------
var num2 = 1;
delete num2;//2.嚴(yán)格模式不允許刪除變量 報錯
--------------------------------------------------------------------------------
function fn() {
    console.log(this); // 3.嚴(yán)格模式下全局作用域中函數(shù)中的 this 是 undefined
}
fn();  
---------------------------------------------------------------------------------
function Star() {
     this.sex = '男';
}
// Star();4.嚴(yán)格模式下,如果 構(gòu)造函數(shù)不加new調(diào)用, this 指向的是undefined 如果給他賦值則 會報錯.
var ldh = new Star();
console.log(ldh.sex);
----------------------------------------------------------------------------------
setTimeout(function() {
  console.log(this); //嚴(yán)格模式下,定時器 this 還是指向 window
}, 2000);  

//5.嚴(yán)格模式沛励,函數(shù)的參數(shù)不能重名(普通模式 重名會覆蓋值 不報錯)
function fn(a, a) {
    console.log(a+a);
}
fn(1,2)//'use strict'下報錯  普通下結(jié)果為4 a=2覆蓋a=1

//6.不允許在非函數(shù)的代碼塊內(nèi)聲明函數(shù)责语,可以在函數(shù)內(nèi)部聲明函數(shù)
if(..) {
    function fn() {...}//error嚴(yán)格模式
}
for(..) {
    function fn() {...}//error嚴(yán)格模式
}
function f() {
    function fn() {...}//可
}

更多嚴(yán)格模式要求參考

10.高階函數(shù)

高階函數(shù)是對其他函數(shù)進(jìn)行操作的函數(shù),它接收函數(shù)作為參數(shù)或?qū)⒑瘮?shù)作為返回值輸出

函數(shù)作為參數(shù)目派,最典型的就是作為回調(diào)函數(shù)坤候,div.animate({left: 500}, 300, function() {});

11.閉包

11.1變量的作用域復(fù)習(xí)

變量根據(jù)作用域的不同分為兩種:全局變量和局部變量。

  1. 函數(shù)內(nèi)部可以使用全局變量企蹭。
  2. 函數(shù)外部不可以使用局部變量白筹。
  3. 當(dāng)函數(shù)執(zhí)行完畢,本作用域內(nèi)的局部變量會銷毀谅摄。

11.2什么是閉包

閉包(closure)是 徒河,一個作用域可以訪問另外一個函數(shù)內(nèi)部的局部變量。變量所在的函數(shù)是一個閉包函數(shù)

 function fn() {    //fn就是閉包函數(shù)
   var num = 10;
   function fun() {
       console.log(num);
    }
    fun();
 }
fn();

11.3閉包的作用

作用:延伸變量的作用范圍

 function fn() {
   var num = 10;
   function fun() {
       console.log(num);
    }
    return fun;
     //等價
     //return function() {
     //  console.log(num);
    //}
 }
var f = fn();
f();

11.4閉包的案例

  1. 利用閉包的方式得到當(dāng)前l(fā)i 的索引號(面試)
for (var i = 0; i < lis.length; i++) {
// 利用for循環(huán)創(chuàng)建了4個立即執(zhí)行函數(shù)
// 立即執(zhí)行函數(shù)也成為小閉包送漠,因?yàn)榱⒓磮?zhí)行函數(shù)里面的任何一個函數(shù)都可以使用它的i這變量
(function(i) {
    lis[i].onclick = function() {
      console.log(i);
    }
 })(i);
}
  1. 閉包應(yīng)用-3秒鐘之后,打印所有l(wèi)i元素的內(nèi)容
 for (var i = 0; i < lis.length; i++) {
   (function(i) {
     setTimeout(function() {//異步任務(wù):計(jì)時器 回調(diào)函數(shù) 事件綁定 ajax
     console.log(lis[i].innerHTML);
     }, 3000)
   })(i);
}
  1. 閉包應(yīng)用-計(jì)算打車價格
/*需求分析
打車起步價13(3公里內(nèi)),  之后每多一公里增加 5塊錢.  用戶輸入公里數(shù)就可以計(jì)算打車價格
如果有擁堵情況,總價格多收取10塊錢擁堵費(fèi)*/

 var car = (function() {
     var start = 13; // 起步價  局部變量
     var total = 0; // 總價  局部變量
     return {
       // 正常的總價
       price: function(n) {
         if (n <= 3) {
           total = start;
         } else {
           total = start + (n - 3) * 5
         }
         return total;
       },
       // 擁堵之后的費(fèi)用
       yd: function(flag) {
         return flag ? total + 10 : total;
       }
    }
 })();
console.log(car.price(5)); // 23
console.log(car.yd(true)); // 33

11.5案例

var name = "The Window";
var object = {
      name: "My Object",
      getNameFunc: function() {
          return function() {//匿名函數(shù)
             return this.name;
          };
      }
};
console.log(object.getNameFunc()())//"The Window"
-----------------------------------------------------------------------------------
var name = "The Window";  
var object = {    
    name: "My Object",
    getNameFunc: function() {//閉包函數(shù)
        var that = this;
        return function() {
            return that.name;
        };
    }
};
console.log(object.getNameFunc()())//"My Object"
       

12.遞歸

12.1什么是遞歸

遞歸:函數(shù)內(nèi)部自己調(diào)用自己, 這個函數(shù)就是遞歸函數(shù)

注意:遞歸函數(shù)的作用和循環(huán)效果一樣顽照,由于遞歸很容易發(fā)生“棧溢出”錯誤(stack overflow),所以必須要加退出條件return

12.2利用遞歸求1~n的階乘

//利用遞歸函數(shù)求1~n的階乘 1 * 2 * 3 * 4 * ..n
 function fn(n) {
     if (n == 1) { //結(jié)束條件
       return 1;
     }
     return n * fn(n - 1);
 }
 console.log(fn(3));//6

12.3利用遞歸求斐波那契數(shù)列

// 利用遞歸函數(shù)求斐波那契數(shù)列(兔子序列)  1闽寡、1代兵、2、3爷狈、5植影、8、13涎永、21...
// 用戶輸入一個數(shù)字 n 就可以求出 這個數(shù)字對應(yīng)的兔子序列值
// 我們只需要知道用戶輸入的n 的前面兩項(xiàng)(n-1 n-2)就可以計(jì)算出n 對應(yīng)的序列值
function fb(n) {
  if (n === 1 || n === 2) {
        return 1;
  }
  return fb(n - 1) + fb(n - 2);
}
console.log(fb(3));

12.4利用遞歸遍歷數(shù)據(jù)

// 我們想要做輸入id號,就可以返回的數(shù)據(jù)對象
 var data = [{
   id: 1,
   name: '家電',
   goods: [{
     id: 11,
     gname: '冰箱',
     goods: [{
       id: 111,
       gname: '海爾'
     }, {
       id: 112,
       gname: '美的'
     },

            ]

   }, {
     id: 12,
     gname: '洗衣機(jī)'
   }]
 }, {
   id: 2,
   name: '服飾'
}];
//1.利用 forEach 去遍歷里面的每一個對象
 function getID(json, id) {
   var o = {};
   json.forEach(function(item) {
     // console.log(item); // 2個數(shù)組元素
     if (item.id == id) {
       // console.log(item);
       o = item;
       return o;//返回給下面的調(diào)用getID(item.goods, id);
       // 2. 我們想要得里層的數(shù)據(jù) 11 12 可以利用遞歸函數(shù)
       // 里面應(yīng)該有g(shù)oods這個數(shù)組并且數(shù)組的長度不為 0 
     } else if (item.goods && item.goods.length > 0) {
       o = getID(item.goods, id);
     }
   });
   return o;
}

13.5 淺拷貝和深拷貝

  • 淺拷貝和深拷貝都只針對于引用數(shù)據(jù)類型
  • 淺拷貝只復(fù)制指向某個對象的指針思币,而不復(fù)制對象本身
  • 深拷貝會另外創(chuàng)造一個一模一樣的對象鹿响,新對象跟原對象不共享內(nèi)存
  • 區(qū)別:淺拷貝只復(fù)制對象的第一層屬性、深拷貝可以對對象的屬性進(jìn)行遞歸復(fù)制谷饿;
var obj = {
    id: 1,
    name: 'andy',
    msg: {
        age: 18
    }
}
var o = {};
  • o = obj;
o = obj;
o.msg.age = 88;
o.id = 2;
console.log(obj);//{id: 2,msg: {age: 88},name: "andy"}
console.log(o);//{id: 2,msg: {age: 88},name: "andy"}
  • for...in
for (let k in obj) {
    console.log(k + ' ' + obj[k]);//id拷貝副本 msg拷貝的是地址
    o[k] = obj[k];
}
o.msg.age = 88;
o.id = 2;
console.log(obj);//{id: 1,msg: {age: 88},name: "andy"}
console.log(o);//{id: 2,msg: {age: 88},name: "andy"}
  • Object.assign()實(shí)現(xiàn)淺拷貝及一層的深拷貝 相當(dāng)于for...in
 Object.assign(target, ...sources);
var obj = {
    id: 1,
    name: 'andy',
    msg: {
        age: 18
    }
}
var o = {};
o = Object.assign(o, obj);
o.msg.age = 88;
o.id = 2;
console.log(obj);//{id: 1,msg: {age: 88},name: "andy"}
console.log(o);//{id: 2,msg: {age: 88},name: "andy"}
  • 深拷貝
function deepCopy(newobj, oldobj) {
    for (var k in oldobj) {
        // 判斷數(shù)據(jù)類型
        // 1.獲取屬性值
        var item = oldobj[k];
        // 2.判斷isArray
        if (item instanceof Array) {
            newobj[k] = [];
            deepCopy(newobj[k], item);
        } else if (item instanceof Object) {// 3.判斷{}
            newobj[k] = {};
            deepCopy(newobj[k], item);
        } else {
            newobj[k] = item;
        }
    }
}
deepCopy(o, obj);
o.msg.age = 88;
o.id = 2;
console.log(obj);//{id: 1,msg: {age: 18},name: "andy"}
console.log(o);//{id: 2,msg: {age: 88},name: "andy"}

13.正則表達(dá)式概述

13.1什么是正則表達(dá)式

正則表達(dá)式( Regular Expression )是構(gòu)成搜索模式的字符序列抢野。在JavaScript中,正則表達(dá)式也是對象各墨。

可用于文本搜索和文本替換操作指孤,例如

  • 驗(yàn)證表單:用戶名表單只能輸入英文字母、數(shù)字或者下劃線贬堵, 昵稱輸入框中可以輸入中文(匹配)
  • 常用于過濾掉頁面內(nèi)容中的一些敏感詞(替換)**恃轩,
  • 或從字符串中獲取我們想要的特定部分(提取)等

其他語言也會使用正則表達(dá)式

13.2 正則表達(dá)式的特點(diǎn)

  1. 靈活性、邏輯性和功能性非常的強(qiáng)
  2. 可以迅速地用極簡單的方式達(dá)到字符串的復(fù)雜控制
  3. 對于剛接觸的人來說黎做,比較晦澀難懂叉跛。比如:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$
  4. 實(shí)際開發(fā),一般直接復(fù)制蒸殿,根據(jù)實(shí)際情況修改要求. 比如驗(yàn)證用戶名: /^[a-z0-9_-]{3,16}$/

14.正則表達(dá)式在js中的使用

14.1正則表達(dá)式的創(chuàng)建

方式一:通過調(diào)用RegExp對象的構(gòu)造函數(shù)創(chuàng)建

var regexp = new RegExp(/123/);
console.log(regexp);

方式二:利用字面量創(chuàng)建 正則表達(dá)式

 var rg = /123/;//不加"" /abc/

14.2測試正則表達(dá)式

test() 正則對象方法筷厘,用于檢測字符串是否符合該規(guī)則,符合返回 true 否則 false宏所,其參數(shù)是測試的字符串

var rg = /123/;
console.log(rg.test(123));//匹配字符中是否出現(xiàn)123  出現(xiàn)結(jié)果為true
console.log(rg.test('abc'));//匹配字符中是否出現(xiàn)123 未出現(xiàn)結(jié)果為false

15.正則表達(dá)式中的特殊字符

15.1正則表達(dá)式的組成

一個正則表達(dá)式可以由簡單的字符構(gòu)成酥艳,比如 /abc/,也可以是簡單和特殊字符的組合爬骤,比如 /ab*c/ 充石。其中特殊字符也被稱為元字符,在正則表達(dá)式中是具有特殊意義的專用符號霞玄,如 ^ 開始骤铃、$結(jié)束 、+ 等坷剧。

特殊字符非常多惰爬,可以參考: MDN

jQuery 手冊:正則表達(dá)式部分

[正則測試工具]( <http://tool.oschina.net/regex)

15.2邊界符

正則表達(dá)式中的邊界符(位置符)用來提示字符所處的位置,主要有兩個字符

邊界符 說明
^ 表示匹配行首的文本(以誰開始)
$ 表示匹配行尾的文本(以誰結(jié)束)

如果 ^和 $ 在一起惫企,表示必須是精確匹配

var rg = /abc/; // 正則表達(dá)式里面不需要加引號 不管是數(shù)字型還是字符串型
// /abc/ 只要包含有abc這個字符串返回的都是true
console.log(rg.test('abc'));
console.log(rg.test('abcd'));
console.log(rg.test('aabcd'));
console.log('---------------------------');
var reg = /^abc/;
console.log(reg.test('abc')); // true
console.log(reg.test('abcd')); // true
console.log(reg.test('aabcd')); // false
console.log('---------------------------');
var reg1 = /^abc$/; // 精確匹配 要求必須是 abc字符串才符合規(guī)范
console.log(reg1.test('abc')); // true
console.log(reg1.test('abcd')); // false
console.log(reg1.test('aabcd')); // false
console.log(reg1.test('abcabc')); // false

15.3字符類

字符類表示有一系列字符可供選擇撕瞧,只要匹配其中一個就可以了。所有可供選擇的字符都放在方括號內(nèi)

15.3.1 [] 方括號

表示有一系列字符可供選擇雅任,只要匹配其中一個就可以了

var rg = /[abc]/; // 或 只要包含有a或者 包含有b 或者包含有c 都返回為true
console.log(rg.test('andy'));//true
console.log(rg.test('baby'));//true
console.log(rg.test('color'));//true
console.log(rg.test('red'));//false

var rg1 = /^[abc]$/; // 三選一 只有是a 或者是 b  或者是c 這三個字母才返回 true
console.log(rg1.test('aa'));//false
console.log(rg1.test('a'));//true
console.log(rg1.test('b'));//true
console.log(rg1.test('c'));//true
console.log(rg1.test('abc'));//false
----------------------------------------------------------------------------------
var reg = /^[a-z]$/ //26個英文字母任何一個字母返回 true  - 表示的是a 到z 的范圍  
console.log(reg.test('a'));//true
console.log(reg.test('z'));//true
console.log(reg.test('A'));//false
-----------------------------------------------------------------------------------
//字符組合
var reg1 = /^[a-zA-Z0-9_-]$/; // 26個英文字母(大寫和小寫都可以)任何一個字母 0-9 _ - 返回 true 
console.log(reg1.test('a'));//true
console.log(reg1.test('B'));//true
console.log(reg1.test(8));//true
console.log(reg1.test('_'));//true
console.log(reg1.test('-'));//true
console.log(reg1.test('!'));//false
------------------------------------------------------------------------------------
//取反 方括號內(nèi)部加上 ^ 表示取反风范,只要包含方括號內(nèi)的字符咨跌,都返回 false
var reg2 = /^[^a-zA-Z0-9]$/;
console.log(reg2.test('a'));//false
console.log(reg2.test('B'));//false
console.log(reg2.test(8));//false
console.log(reg2.test('!'));//true

15.3.2量詞符

量詞符用來設(shè)定某個模式出現(xiàn)的次數(shù)沪么,中間不要有空格!

/^[......]$/多選一(規(guī)定輸入內(nèi)容)

/^[......]${6,16}/ 多選一可以重復(fù)6到16次(規(guī)定輸入次數(shù))

量詞 說明
* 重復(fù)0次或更多次
+ 重復(fù)1次或更多次
? 重復(fù)0次或1次
{n} 重復(fù)n次
{n,} 重復(fù)n次或更多次
{n,m} 重復(fù)n到m次
// 出現(xiàn)次數(shù) >= 0
var reg = /^a*$/;

// >= 1
var reg = /^a+$/;

// 1 || 0
var reg = /^a?$/;

// 3
var reg = /^a{3}$/;

// >=3
var reg = /^a{3,}$/;

// >=3 <=6
var reg = /^a{3,6}$/;

15.3.3用戶名表單驗(yàn)證

功能需求:

  1. 如果用戶名輸入合法, 則后面提示信息為: 用戶名合法,并且顏色為綠色
  2. 如果用戶名輸入不合法, 則后面提示信息為: 用戶名不符合規(guī)范, 并且顏色為紅

分析:

  1. 用戶名只能為英文字母,數(shù)字,下劃線或者短橫線組成, 并且用戶名長度為6~16位.
  2. 首先準(zhǔn)備好這種正則表達(dá)式模式/$[a-zA-Z0-9-_]{6,16}^/
  3. 當(dāng)表單失去焦點(diǎn)就開始驗(yàn)證.
  4. 如果符合正則規(guī)范, 則讓后面的span標(biāo)簽添加 right類.
  5. 如果不符合正則規(guī)范, 則讓后面的span標(biāo)簽添加 wrong類.
<input type="text" class="uname"> <span>請輸入用戶名</span>
 <script>
 //  量詞是設(shè)定某個模式出現(xiàn)的次數(shù)
 var reg = /^[a-zA-Z0-9_-]{6,16}$/; // 這個模式用戶只能輸入英文字母 數(shù)字 下劃線 中劃線
 var uname = document.querySelector('.uname');
 var span = document.querySelector('span');
 uname.onblur = function() {
   if (reg.test(this.value)) {
       span.className = 'right';
       span.innerHTML = '用戶名格式輸入正確';
   } else {
       span.className = 'wrong';
       span.innerHTML = '用戶名格式輸入不正確';
   }
 }
</script>

15.3.4 括號總結(jié)

1.大括號 量詞符. 里面表示重復(fù)次數(shù)

var reg = /^abc{3}$/;
// abccc 精確匹配 c重復(fù)3次

2.中括號 字符集合锌半。匹配方括號中的任意字符.

var reg = /^[abc]$/;
// a || b || c 

3.小括號表示優(yōu)先級

var reg = /^(abc){3}$/;
// abcabcabc 精確匹配 abc重復(fù)3次

正則表達(dá)式在線測試

15.4預(yù)定義類

預(yù)定義類指的是某些常見模式的簡寫方式(大小寫取反)

1.預(yù)定義類 \d      
匹配0-9任一數(shù)字禽车,即[0-9]
2.\D
匹配0-9之外的任一字符寇漫,即 [^0-9]
3.\w
匹配任意字母 數(shù)字 下劃線,相當(dāng)于[A-Za-z0-9]
4.\W
\w取反 即[^A-Za-z0-9]
5.\s
匹配空格(包括換行符 制表符 空格符)殉摔,即[\t\r\n\v\f]
6.\S
匹配非空格的字符州胳,即[^\t\r\n\v\f]

案例:驗(yàn)證座機(jī)號碼

|或符號,{3,4} 3到4位

var reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;
var reg = /^\d{3,4}-\d{7,8}$/;

表單驗(yàn)證案例

//手機(jī)號驗(yàn)證:/^1[3|4|5|7|8][0-9]{9}$/;
//驗(yàn)證通過與不通過更換元素的類名與元素中的內(nèi)容
function regexp(ele, reg) {
    ele.onblur = function() {
      if (reg.test(this.value)) {
        // console.log('正確的');
        this.nextElementSibling.className = 'success';
        this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您輸入正確';
   } else {
     // console.log('不正確');
     this.nextElementSibling.className = 'error';
     this.nextElementSibling.innerHTML = '<i class="error_icon"></i> 格式不正確,請從新輸入 ';
            }
        }
 };
var regtel = /^1[3|4|5|7|8]\d{9}$/;
var tel = document.querySelector('#tel');
regexp(tel, regtel);
//QQ號驗(yàn)證: /^[1-9]\d{4,}$/; 
var regqq = /^[1-9]\d{4,}$/;
var qq = document.querySelector('#qq');
regexp(qq, regqq);
//昵稱驗(yàn)證:/^[\u4e00-\u9fa5]{2,8}$/
var regnic = /^[\u4e00-\u9fa5]{2,8}$/;
var nic = document.querySelector('#nic');
regexp(nic, regnic);
//驗(yàn)證通過與不通過更換元素的類名與元素中的內(nèi)容 ,將上一步的匹配代碼進(jìn)行封裝,多次調(diào)用即可

//密碼驗(yàn)證:/^[a-zA-Z0-9_-]{6,16}$/
var regpwd = /^[a-zA-Z0-9_-]{6,16}$/;
var pwd = document.querySelector('#pwd');
regexp(pwd, regpwd);
//再次輸入密碼只需匹配與上次輸入的密碼值 是否一致
var surepwd = document.querySelector('#surepwd');
surepwd.onblur = function() {
    if (this.value == pwd.value) {
        this.nextElementSibling.className = 'success';
        this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您輸入正確';
    } else {
        this.nextElementSibling.className = 'error';
     this.nextElementSibling.innerHTML = '<i class="error_icon"></i> 密碼不一致 ';
    }
}

15.5正則替換replace

replace() 方法實(shí)現(xiàn)替換字符串操作逸月,用來替換的參數(shù)可以是一個字符串或是一個正則表達(dá)式栓撞,結(jié)合正則表達(dá)式修飾符g i

var str = 'andy和red';
var newStr = str.replace('andy', 'baby');
console.log(newStr)//baby和red
//等同于 此處的andy可以寫在正則表達(dá)式內(nèi)
var newStr2 = str.replace(/andy/, 'baby');
console.log(newStr2)//baby和red
//全部替換
var str = 'abcabc'
var nStr = str.replace(/a/,'哈哈')
console.log(nStr) //哈哈bcabc
//全部替換g
var nStr = str.replace(/a/g,'哈哈')
console.log(nStr) //哈哈bc哈哈bc
//忽略大小寫i
var str = 'aAbcAba';
var newStr = str.replace(/a/gi,'哈哈')//"哈哈哈哈bc哈哈b哈哈"

案例:過濾敏感詞匯

<textarea name="" id="message"></textarea> <button>提交</button>
<div></div>
<script>
    var text = document.querySelector('textarea');
    var btn = document.querySelector('button');
    var div = document.querySelector('div');
    btn.onclick = function() {
        div.innerHTML = text.value.replace(/激情|gay/g, '**');
    }
</script>

16. ES6相關(guān)概念(★★)

16.1 什么是ES6

ES 的全稱是 ECMAScript , 它是由 ECMA 國際標(biāo)準(zhǔn)化組織,制定的一項(xiàng)腳本語言的標(biāo)準(zhǔn)化規(guī)范

es-version.png

16.2 為什么使用 ES6 ?

每一次標(biāo)準(zhǔn)的誕生都意味著語言的完善,功能的加強(qiáng)碗硬。JavaScript語言本身也有一些令人不滿意的地方瓤湘。

  • 變量提升特性增加了程序運(yùn)行時的不可預(yù)測性
  • 語法過于松散,實(shí)現(xiàn)相同的功能恩尾,不同的人可能會寫出不同的代碼

17. ES6新增語法

17.1 let(★★★)

ES6中新增了用于聲明變量的關(guān)鍵字弛说,具有以下特性:

1.let聲明的變量有塊級作用域

 if (true) { 
     let a = 10;
 }
console.log(a) // a is not defined

注意:在一個{}中,使用let關(guān)鍵字聲明的變量才具有塊級作用域翰意,使用var聲明的變量不具備塊級作用域特性

另外木人,let防止循環(huán)變量變成全局變量

 for (let i = 0; i < 4; i++) { 
     
 }
console.log(i) // i is not defined

2.不存在變量提升

console.log(a); // a is not defined 
let a = 20;

3.暫時性死區(qū)

利用let聲明的變量會綁定在這個塊級作用域,不會受外界的影響

 var tmp = 123;
 if (true) { 
     tmp = 'abc';// tmp is not defined報錯 Cannot access 'tmp' before initialization
     let tmp; 
 } 

4.經(jīng)典面試題

 var arr = [];
 for (var i = 0; i < 2; i++) {
     arr[i] = function () {
         console.log(i); 
     }
 }
 arr[0]();//2
 arr[1]();//2

經(jīng)典面試題圖解:此題的關(guān)鍵點(diǎn)在于變量i是全局的冀偶,函數(shù)執(zhí)行時輸出的都是全局作用域下的i值醒第。

 let arr = [];
 for (let i = 0; i < 2; i++) {
     arr[i] = function () {
         console.log(i); 
     }
 }
 arr[0]();//0
 arr[1]();//1

經(jīng)典面試題圖解:此題的關(guān)鍵點(diǎn)在于每次循環(huán)都會產(chǎn)生一個塊級作用域,每個塊級作用域中的變量都是不同的进鸠,函數(shù)執(zhí)行時輸出的是自己上一級(循環(huán)產(chǎn)生的塊級作用域)作用域下的i值.

小結(jié)

  • let關(guān)鍵字就是用來聲明變量的
  • 使用let關(guān)鍵字聲明的變量具有塊級作用域
  • 在一個大括號中 使用let關(guān)鍵字聲明的變量才具有塊級作用域 var關(guān)鍵字是不具備這個特點(diǎn)的
  • 防止循環(huán)變量變成全局變量
  • 使用let關(guān)鍵字聲明的變量沒有變量提升
  • 使用let關(guān)鍵字聲明的變量具有暫時性死區(qū)特性

17.2 const(★★★)

聲明常量淘讥,常量就是值(內(nèi)存地址)不能變化的量

1.具有塊級作用域

 if (true) { 
     const a = 10;
 }
console.log(a) // a is not defined

2.聲明常量時必須賦值

const PI; // Missing initializer in const declaration

3.常量賦值后,值不能修改

const PI = 3.14;
PI = 100; // Assignment to constant variable.

const ary = [100, 200];
ary[0] = 'a';
ary[1] = 'b';
console.log(ary); // ['a', 'b']; 
ary = ['a', 'b']; // Assignment to constant variable.

小結(jié)

  • const聲明的變量是一個常量
  • 既然是常量不能重新進(jìn)行賦值堤如,如果是基本數(shù)據(jù)類型蒲列,不能更改值,如果是復(fù)雜數(shù)據(jù)類型搀罢,不能更改地址值
  • 聲明 const時候必須要給定值

17.3 let蝗岖、const、var 的區(qū)別

  • 使用 var 聲明的變量(值可更改)榔至,其作用域?yàn)樵撜Z句所在的函數(shù)內(nèi)抵赢,且存在變量提升現(xiàn)象
  • 使用 let 聲明的變量(值可更改),其作用域?yàn)樵撜Z句所在的代碼塊內(nèi)唧取,不存在變量提升
  • 使用 const 聲明的是常量(值不可更改)铅鲤,在后面出現(xiàn)的代碼中不能再修改該常量的值

17.4 解構(gòu)賦值(★★★)

ES6中允許從數(shù)組中提取值,按照對應(yīng)位置枫弟,對變量賦值邢享,對象也可以實(shí)現(xiàn)解構(gòu)

1.數(shù)組解構(gòu)

左邊是解構(gòu)的結(jié)構(gòu) 右邊是解構(gòu)的數(shù)組

 let [a, b, c] = [1, 2, 3];
 console.log(a)//1
 console.log(b)//2
 console.log(c)//3
//如果解構(gòu)不成功,變量的值為undefined

2.對象解構(gòu)

左邊是解構(gòu)的結(jié)構(gòu) 右邊是解構(gòu)的對象

 let person = { name: 'zhangsan', age: 20 }; 
 let { name, age } = person;//要和person內(nèi)的屬性名一致
 console.log(name); // 'zhangsan' 
 console.log(age); // 20

 let {name: myName, age: myAge} = person; // myName myAge 屬于別名
 console.log(myName); // 'zhangsan' 
 console.log(myAge); // 20

小結(jié)

  • 解構(gòu)賦值就是把數(shù)據(jù)結(jié)構(gòu)分解淡诗,然后給變量進(jìn)行賦值
  • 如果結(jié)構(gòu)不成功骇塘,變量跟數(shù)值個數(shù)不匹配的時候伊履,變量的值為undefined
  • 數(shù)組解構(gòu)用中括號包裹,多個變量用逗號隔開款违,對象解構(gòu)用花括號包裹唐瀑,多個變量用逗號隔開
  • 利用解構(gòu)賦值能夠讓我們方便的去取對象中的屬性跟方法

17.5 箭頭函數(shù)(★★★)

ES6中新增的定義函數(shù)的方式。

() => {} //():代表是函數(shù)插爹; =>:必須要的符號哄辣,指向哪一個代碼塊;{}:函數(shù)體
const fn = () => {}//代表把一個函數(shù)賦值給fn

函數(shù)體中只有一句代碼赠尾,且代碼的執(zhí)行結(jié)果就是返回值柔滔,可以省略大括號

 function sum(num1, num2) { 
     return num1 + num2; 
 }
 //es6寫法
 const sum = (num1, num2) => num1 + num2; 

如果形參只有一個,可以省略小括號

 function fn (v) {
     return v;
 } 
//es6寫法
 const fn = v => v;

箭頭函數(shù)不綁定this關(guān)鍵字萍虽,箭頭函數(shù)中的this睛廊,指向的是函數(shù)定義位置的上下文this

const obj = { name: '張三'} 
 function fn () { 
     console.log(this);//this 指向 是obj對象
     return () => { 
         console.log(this);//this 指向 的是箭頭函數(shù)定義的位置,那么這個箭頭函數(shù)定義在fn里面杉编,而這個fn指向是的obj對象超全,所以這個this也指向是obj對象
     } 
 } 
 const resFn = fn.call(obj); 
 resFn();

小結(jié)

  • 箭頭函數(shù)中不綁定this,箭頭函數(shù)中的this指向是它所定義的位置邓馒,可以簡單理解成嘶朱,定義箭頭函數(shù)中的作用域的this指向誰,它就指向誰
  • 箭頭函數(shù)的優(yōu)點(diǎn)在于解決了this執(zhí)行環(huán)境所造成的一些問題光酣。比如:解決了匿名函數(shù)this指向的問題(匿名函數(shù)的執(zhí)行環(huán)境具有全局性)疏遏,包括setTimeout和setInterval中使用this所造成的問題

面試題

var age = 100;

var obj = {
    age: 20,
    say: () => {
        alert(this.age)
    }
}

obj.say();//箭頭函數(shù)this指向的是被聲明的作用域里面,而對象沒有作用域的救军,(即obj是在全局下定義的财异,沒有作用域)所以箭頭函數(shù)雖然在對象中被定義,但是this指向的是全局作用域

17.6 剩余參數(shù)(★★)

剩余參數(shù)語法允許我們將一個不定數(shù)量的參數(shù)表示為一個數(shù)組唱遭,

方便去聲明不知道參數(shù)情況下的一個函數(shù)

function sum (first, ...args) {
     console.log(first); // 10
     console.log(args); // [20, 30] 
 }
 sum(10, 20, 30)
const sum = (...args) => {
    let total = 0;
    args.forEach(item => total += item);
    return total;
};
console.log(sum(1,2,3,4));

剩余參數(shù)和解構(gòu)配合使用

let students = ['wangwu', 'zhangsan', 'lisi'];
let [s1, ...s2] = students; 
console.log(s1);  // 'wangwu' 
console.log(s2);  // ['zhangsan', 'lisi']

18. ES6 的內(nèi)置對象擴(kuò)展

18.1 Array 的擴(kuò)展方法(★★)

18.1.1 擴(kuò)展運(yùn)算符(展開語法)

與剩余參數(shù)相反戳寸,擴(kuò)展運(yùn)算符將數(shù)組或者對象轉(zhuǎn)為用逗號分隔的參數(shù)序列

 let ary = [1, 2, 3];
 ...ary  // 1, 2, 3
 console.log(...ary);    // 1 2 3,相當(dāng)于下面的代碼
//逗號被當(dāng)作了log方法的分隔符,所以不見了
 console.log(1,2,3);
1.應(yīng)用于合并數(shù)組
// 方法一 
 let ary1 = [1, 2, 3];
 let ary2 = [3, 4, 5];
 let ary3 = [...ary1, ...ary2];
 // 方法二 
 ary1.push(...ary2);
2.將類數(shù)組或可遍歷對象轉(zhuǎn)換為真正的數(shù)組
let oDivs = document.getElementsByTagName('div'); 
oDivs = [...oDivs];

18.1.2 構(gòu)造函數(shù)方法:Array.from()

將偽數(shù)組或可遍歷對象轉(zhuǎn)換為真正的數(shù)組

//定義一個集合
let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
}; 
//轉(zhuǎn)成數(shù)組
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

方法還可以接受第二個參數(shù)拷泽,作用類似于數(shù)組的map方法疫鹊,用來對每個元素進(jìn)行處理,將處理后的值放入返回的數(shù)組

 let arrayLike = { 
     "0": 1,
     "1": 2,
     "length": 2
 }
 let newAry = Array.from(arrayLike, item => item *2)//[2,4]

注意:如果是對象司致,那么屬性需要寫對應(yīng)的索引

18.1.3 實(shí)例方法:find()

用于找出第一個符合條件的數(shù)組成員拆吆,如果沒有找到返回undefined

let ary = [{
     id: 1,
     name: '張三'
 }, { 
     id: 2,
     name: '李四'
 }]; 
 let target = ary.find((item, index) => item.id == 2);//找數(shù)組里面符合條件的值,當(dāng)數(shù)組中元素id等于2的查找出來脂矫,注意枣耀,只會匹配第一個

8.1.4 實(shí)例方法:findIndex()

用于找出第一個符合條件的數(shù)組成員的位置,如果沒有找到返回-1

let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9); 
console.log(index); // 2

8.1.5 實(shí)例方法:includes()

判斷某個數(shù)組是否包含給定的值羹唠,返回布爾值奕枢。

[1, 2, 3].includes(2) // true 
[1, 2, 3].includes(4) // false

18.2 String 的擴(kuò)展方法

18.2.1 模板字符串特性(★★★)

ES6新增的創(chuàng)建字符串的方式,使用反引號定義

let name = `zhangsan`;

1.模板字符串中可以解析變量
let name = '張三'; 
let sayHello = `hello,my name is ${name}`; // hello, my name is zhangsan
2.模板字符串中可以換行
 let result = { 
     name: 'zhangsan', 
     age: 20,
     sex: '男' 
 } 
 let html = ` <div>
     <span>${result.name}</span>
     <span>${result.age}</span>
     <span>${result.sex}</span>
 </div> `;

3.在模板字符串中可以調(diào)用函數(shù)
const sayHello = function () { 
    return '哈哈哈哈 追不到我吧 我就是這么強(qiáng)大';
 }; 
 let greet = `${sayHello()} 哈哈哈哈`;
 console.log(greet); // 哈哈哈哈 追不到我吧 我就是這么強(qiáng)大 哈哈哈哈

18.2.2 方法:startsWith() 和 endsWith()

  • startsWith():表示參數(shù)字符串是否在原字符串的頭部佩微,返回布爾值
  • endsWith():表示參數(shù)字符串是否在原字符串的尾部缝彬,返回布爾值
let str = 'Hello world!';
str.startsWith('Hello') // true 
str.endsWith('!')       // true

18.2.3 方法:repeat()

repeat方法表示將原字符串重復(fù)n次,返回一個新字符串

'x'.repeat(3)      // "xxx" 
'hello'.repeat(2)  // "hellohello"

18.3 Set 數(shù)據(jù)結(jié)構(gòu)(★★)

ES6 提供了新的數(shù)據(jù)結(jié)構(gòu) Set哺眯。它類似于數(shù)組谷浅,但是成員的值都是唯一的,沒有重復(fù)的值

Set本身是一個構(gòu)造函數(shù)奶卓,用來生成 Set 數(shù)據(jù)結(jié)構(gòu)

const s = new Set();

Set函數(shù)可以接受一個數(shù)組作為參數(shù)一疯,用來初始化

const set = new Set([1, 2, 3, 4, 4]);//{1, 2, 3, 4}
console.log(set.size);//4

實(shí)例方法

  • add(value):添加某個值,返回 Set 結(jié)構(gòu)本身
  • delete(value):刪除某個值夺姑,返回一個布爾值墩邀,表示刪除是否成功
  • has(value):返回一個布爾值,表示該值是否為 Set 的成員
  • clear():清除所有成員盏浙,沒有返回值
 const s = new Set();
 s.add(1).add(2).add(3); // 向 set 結(jié)構(gòu)中添加值 
 s.delete(2)             // 刪除 set 結(jié)構(gòu)中的2值   
 s.has(1)                // 表示 set 結(jié)構(gòu)中是否有1這個值 返回布爾值 
 s.clear()               // 清除 set 結(jié)構(gòu)中的所有值
 //注意:刪除的是元素的值眉睹,不是代表的索引

遍歷

Set 結(jié)構(gòu)的實(shí)例與數(shù)組一樣,也擁有forEach方法废膘,用于對每個成員執(zhí)行某種操作竹海,沒有返回值。

s.forEach(value => console.log(value))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丐黄,一起剝皮案震驚了整個濱河市斋配,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灌闺,老刑警劉巖艰争,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異桂对,居然都是意外死亡园细,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門接校,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猛频,“玉大人,你說我怎么就攤上這事蛛勉÷寡埃” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵诽凌,是天一觀的道長毡熏。 經(jīng)常有香客問我,道長侣诵,這世上最難降的妖魔是什么痢法? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任狱窘,我火速辦了婚禮,結(jié)果婚禮上财搁,老公的妹妹穿的比我還像新娘蘸炸。我一直安慰自己,他們只是感情好尖奔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布搭儒。 她就那樣靜靜地躺著,像睡著了一般提茁。 火紅的嫁衣襯著肌膚如雪淹禾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天茴扁,我揣著相機(jī)與錄音铃岔,去河邊找鬼。 笑死峭火,一個胖子當(dāng)著我的面吹牛德撬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播躲胳,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蜓洪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了坯苹?” 一聲冷哼從身側(cè)響起隆檀,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎粹湃,沒想到半個月后恐仑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡为鳄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年裳仆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片孤钦。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡歧斟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出偏形,到底是詐尸還是另有隱情静袖,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布俊扭,位于F島的核電站队橙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捐康,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一仇矾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧解总,春花似錦贮匕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萍嬉。三九已至乌昔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間壤追,已是汗流浹背磕道。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留行冰,地道東北人溺蕉。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像悼做,于是被迫代替她去往敵國和親疯特。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354