JavaScript高級

==============part1==========

1.面向過程與面向?qū)ο?/h2>

1.1面向過程

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

1.2面向?qū)ο?/h3>
  • 面向?qū)ο笫前咽聞?wù)分解成為一個個對象,然后由對象之間分工與合作捏题。

1.3面向過程與面向?qū)ο髮Ρ?/h3>
面向過程 面向?qū)ο?/th>
優(yōu)點 性能比面向?qū)ο蟾吣蕴猓m合跟硬件聯(lián)系很緊密的東西,例如單片機就采用的面向過程編程屏轰。 易維護颊郎、易復用、易擴展霎苗,由于面向?qū)ο笥蟹庋b姆吭、繼承、多態(tài)性的特性唁盏,可以設(shè)計出低耦合的系統(tǒng)内狸,使系統(tǒng) 更加靈活、更加易于維護
缺點 不易維護厘擂、不易復用昆淡、不易擴展 性能比面向過程低

2.對象與類

2.1對象

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

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

2.1.1創(chuàng)建對象

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

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

2.2類

  • 在 ES6 中新增加了類的概念昂灵,可以使用 class 關(guān)鍵字聲明一個類,之后以這個類來實例化對象舞萄。類抽象了對象的公共部分眨补,它泛指某一大類(class)對象特指某一個,通過類實例化一個具體的對象

2.2.1創(chuàng)建類

  1. 語法:
//步驟1 使用class關(guān)鍵字
class name {
  // class body
}     
//步驟2使用定義的類創(chuàng)建實例  注意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);

以上代碼運行結(jié)果:


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

2.2.2類創(chuàng)建添加屬性和方法

 // 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('冰雨'); // 劉德華唱冰雨

以上代碼運行結(jié)果:


注意:

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

以上代碼運行結(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ù)
      }
    }
    var son = new Son(1, 2);
    son.sum(); //結(jié)果為3
    

    注意:

    1. 繼承中,如果實例化子類輸出一個方法,先看子類有沒有這個方法,如果有就先執(zhí)行子類的

    2. 繼承中,如果子類里面沒有,就去查找父類有沒有這個方法,如果有,就執(zhí)行父類的這個方法(就近原則)

    3. 如果子類想要繼承父類的方法,同時在自己內(nèi)部擴展自己的方法,利用super 調(diào)用父類的構(gòu)造函數(shù),super 必須在子類this之前調(diào)用

       // 父類有加法方法
       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 調(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
      

      以上代碼運行結(jié)果為:


    4. 時刻注意this的指向問題,類里面的共有的屬性和方法一定要加this使用.

      1. constructor中的this指向的是new出來的實例對象
      2. 自定義的方法,一般也指向的new出來的實例對象
      3. 綁定事件之后this指向的就是觸發(fā)事件的事件源
    5. 在 ES6 中類沒有變量提升倒脓,所以必須先定義類撑螺,才能通過類實例化對象

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

3.1功能需求

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

3.2案例準備

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

3.3切換

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

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

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

3.4添加

  • 為添加按鈕+ 綁定點擊事件

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

    addTab() {
        that.clearClass();
        // (1) 創(chuàng)建li元素和section元素 
        var random = Math.random();
        var li = '<li class="liactive"><span>新選項卡</span><span class="iconfont icon-guanbi">               </span></li>';
        var section = '<section class="conactive">測試 ' + random + '</section>';
        // (2) 把這兩個元素追加到對應(yīng)的父元素里面
        that.ul.insertAdjacentHTML('beforeend', li);
        that.fsection.insertAdjacentHTML('beforeend', section);
        that.init();
        }
    

3.5刪除

  • 為元素的刪除按鈕x綁定點擊事件

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

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

3.6編輯

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

     this.spans[i].ondblclick = this.editTab;
     this.sections[i].ondblclick = this.editTab;
    
  • 在雙擊事件處理文本選中狀態(tài),修改內(nèi)部DOM節(jié)點,實現(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)
          // 當我們離開文本框就把文本框里面的值給span 
          input.onblur = function() {
          this.parentNode.innerHTML = this.value;
          };
          // 按下回車也可以把文本框里面的值給span
          input.onkeyup = function(e) {
          if (e.keyCode === 13) {
          // 手動調(diào)用表單失去焦點事件  不需要鼠標離開操作
          this.blur();
          }
        }
    }
    

==============part2==========

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

1.1對象的三種創(chuàng)建方式--復習

  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);
    

1.2靜態(tài)成員和實例成員

1.2.1實例成員

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

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

1.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ù)來訪問

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

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


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

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

JavaScript 規(guī)定,每一個構(gòu)造函數(shù)都有一個prototype 屬性吊履,指向另一個對象安皱。注意這個prototype就是一個對象,這個對象的所有屬性和方法艇炎,都會被構(gòu)造函數(shù)所擁有酌伊。

我們可以把那些不變的方法,直接定義在 prototype 對象上,這樣所有對象的實例就可以共享這些方法居砖。

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
}
Star.prototype.sing = function() {
    console.log('我會唱歌');
}
var ldh = new Star('劉德華', 18);
var zxy = new Star('張學友', 19);
ldh.sing();//我會唱歌
zxy.sing();//我會唱歌

1.5對象原型

對象都會有一個屬性 proto 指向構(gòu)造函數(shù)的 prototype 原型對象虹脯,之所以我們對象可以使用構(gòu)造函數(shù) prototype 原型對象的屬性和方法,就是因為對象有 proto 原型的存在奏候。
proto對象原型和原型對象 prototype 是等價的
proto對象原型的意義就在于為對象的查找機制提供一個方向循集,或者說一條路線,但是它是一個非標準屬性蔗草,因此實際開發(fā)中咒彤,不可以使用這個屬性,它只是內(nèi)部指向原型對象 prototype

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

對象原型( __proto__)和構(gòu)造函數(shù)(prototype)原型對象里面都有一個屬性 constructor 屬性 咒精,constructor 我們稱為構(gòu)造函數(shù)镶柱,因為它指回構(gòu)造函數(shù)本身。
constructor 主要用于記錄該對象引用于哪個構(gòu)造函數(shù)模叙,它可以讓原型對象重新指向原來的構(gòu)造函數(shù)歇拆。
一般情況下,對象的方法都在構(gòu)造函數(shù)的原型對象中設(shè)置范咨。如果有多個對象的方法故觅,我們可以給原型對象采取對象形式賦值,但是這樣就會覆蓋構(gòu)造函數(shù)原型對象原來的內(nèi)容渠啊,這樣修改后的原型對象 constructor  就不再指向當前構(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('張學友', 19);
console.log(zxy)

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


如果未設(shè)置constructor屬性,如圖:


1.7原型鏈

每一個實例對象又有一個__proto__屬性,指向的構(gòu)造函數(shù)的原型對象灭返,構(gòu)造函數(shù)的原型對象也是一個對象盗迟,也有__proto__屬性,這樣一層一層往上找就形成了原型鏈熙含。

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

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

1.9原型鏈和成員的查找機制

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

當訪問一個對象的屬性(包括方法)時罚缕,首先查找這個對象自身有沒有該屬性。
如果沒有就查找它的原型(也就是 proto指向的 prototype 原型對象)怎静。
如果還沒有就查找原型對象的原型(Object的原型對象)邮弹。
依此類推一直找到 Object 為止(null)。
proto對象原型的意義就在于為對象成員查找機制提供一個方向蚓聘,或者說一條路線腌乡。

1.10原型對象中this指向

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

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指向的是對象實例 ldh
console.log(that === ldh);//true
// 2.原型對象函數(shù)里面的this 指向的是 實例對象 ldh

1.11通過原型為數(shù)組擴展內(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()進行數(shù)據(jù)的求

2.繼承

2.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,

2.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ù)的對象實例
   this.uname = uname;
   this.age = age;
 }
  // 2 .子構(gòu)造函數(shù) 
function Son(uname, age, score) {
  // this 指向子構(gòu)造函數(shù)的對象實例
  3.使用call方式實現(xiàn)子繼承父的屬性
  Father.call(this, uname, age);
  this.score = score;
}
var son = new Son('劉德華', 18, 100);
console.log(son);

2.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ù)的對象實例
  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ù)的對象實例
      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é)果如圖:


3.ES5新增方法

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

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

3.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ù)三是:當前的數(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ù)三是:當前的數(shù)組
     return value < 3;
  });
console.log(flag);//false返回值是布爾值,只要查找到滿足條件的一個元素就立馬終止循環(huán)

3.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. 獲取到搜索按鈕并為其綁定點擊事件

      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. 為查詢按鈕綁定點擊事件,將輸入的商品名稱與這個數(shù)據(jù)進行篩選

         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);
        })
        

3.5some和forEach區(qū)別

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

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

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

3.7獲取對象的屬性名

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

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

3.8Object.defineProperty

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

Object.defineProperty(對象与纽,修改或新增的屬性名,{
        value:修改或新增的屬性的值,
        writable:true/false,//如果值為false 不允許修改這個屬性值
        enumerable: false,//enumerable 如果值為false 則不允許遍歷
        configurable: false  //configurable 如果為false 則不允許刪除這個屬性 屬性是否可以被刪除或是否可以再次修改特性
})  

==============part3==========

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

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

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

    function fn(){}
    
  2. 方式2 函數(shù)表達式(匿名函數(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ù)也屬于對象
    */
    

1.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ào)用這個函數(shù)
/* 5. 定時器函數(shù)*/
setInterval(function() {}, 1000);  這個函數(shù)是定時器自動1秒鐘調(diào)用一次
/* 6. 立即執(zhí)行函數(shù)(自調(diào)用函數(shù))*/
(function() {
    console.log('人生的巔峰');
})();

2.this

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

這些 this 的指向吏够,是當我們調(diào)用函數(shù)的時候確定的米罚。調(diào)用方式的不同決定了this 的指向不同

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


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

2.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 運行結(jié)果為3
fn.call(o,1,2)//此時的this指向的是對象o,參數(shù)使用逗號隔開,運行結(jié)果為3

以上代碼運行結(jié)果為:


2.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 運行結(jié)果為3
fn.apply(o,[1,2])//此時的this指向的是對象o,參數(shù)使用數(shù)組傳遞 運行結(jié)果為3

2.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ù)使用逗號隔開

2.2.4 call仓坞、apply、bind三者的異同

  • 共同點 : 都可以改變this指向
  • 不同點:
    • 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ù)學對象實現(xiàn)數(shù)組最大值最小值
    3. bind 不調(diào)用函數(shù),但是還想改變this指向. 比如改變定時器內(nèi)部的this指向.

3.嚴格模式

3.1什么是嚴格模式

JavaScript 除了提供正常模式外腰吟,還提供了嚴格模式(strict mode)。ES5 的嚴格模式是采用具有限制性 JavaScript變體的一種方式徙瓶,即在嚴格的條件下運行 JS 代碼毛雇。

嚴格模式在 IE10 以上版本的瀏覽器中才會被支持,舊版本瀏覽器中會被忽略侦镇。

嚴格模式對正常的 JavaScript 語義做了一些更改:

1.消除了 Javascript 語法的一些不合理灵疮、不嚴謹之處,減少了一些怪異行為壳繁。

2.消除代碼運行的一些不安全之處震捣,保證代碼運行的安全。

3.提高編譯器效率闹炉,增加運行速度蒿赢。

4.禁用了在 ECMAScript 的未來版本中可能會定義的一些語法,為未來新版本的 Javascript 做好鋪墊渣触。比如一些保留字如:class,enum,export, extends, import, super 不能做變量名

3.2開啟嚴格模式

嚴格模式可以應(yīng)用到整個腳本或個別函數(shù)中羡棵。因此在使用時,我們可以將嚴格模式分為為腳本開啟嚴格模式和為函數(shù)開啟嚴格模式兩種情況嗅钻。

  • 情況一 :為腳本開啟嚴格模式

    • 有的 script 腳本是嚴格模式皂冰,有的 script 腳本是正常模式,這樣不利于文件合并养篓,所以可以將整個腳本文件放在一個立即執(zhí)行的匿名函數(shù)之中秃流。這樣獨立創(chuàng)建一個作用域而不影響其他
      script 腳本文件。

      (function (){
        //在當前的這個自調(diào)用函數(shù)中有開啟嚴格模式柳弄,當前函數(shù)之外還是普通模式
          "use strict";
             var num = 10;
          function fn() {}
      })();
      //或者 
      <script>
         "use strict"; //當前script標簽開啟了嚴格模式
      </script>
      <script>
                  //當前script標簽未開啟嚴格模式
      </script>
      
  • 情況二: 為函數(shù)開啟嚴格模式

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

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

3.3嚴格模式中的變化

嚴格模式對 Javascript 的語法和行為,都做了一些改變峻贮。

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

更多嚴格模式要求參考

4.高階函數(shù)

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


此時fn 就是一個高階函數(shù)

函數(shù)也是一種數(shù)據(jù)類型挂捻,同樣可以作為參數(shù),傳遞給另外一個參數(shù)使用船万。最典型的就是作為回調(diào)函數(shù)刻撒。

同理函數(shù)也可以作為返回值傳遞回來

5.閉包

5.1變量的作用域復習

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

  1. 函數(shù)內(nèi)部可以使用全局變量耿导。
  2. 函數(shù)外部不可以使用局部變量声怔。
  3. 當函數(shù)執(zhí)行完畢,本作用域內(nèi)的局部變量會銷毀舱呻。

5.2什么是閉包

閉包(closure)指有權(quán)訪問另一個函數(shù)作用域中變量的函數(shù)醋火。簡單理解就是 ,一個作用域可以訪問另外一個函數(shù)內(nèi)部的局部變量箱吕。


5.3閉包的作用

作用:延伸變量的作用范圍芥驳。

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

5.4閉包的案例

  1. 利用閉包的方式得到當前l(fā)i 的索引號
for (var i = 0; i < lis.length; i++) {
// 利用for循環(huán)創(chuàng)建了4個立即執(zhí)行函數(shù)
// 立即執(zhí)行函數(shù)也成為小閉包因為立即執(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() {
     console.log(lis[i].innerHTML);
     }, 3000)
   })(i);
}
  1. 閉包應(yīng)用-計算打車價格
/*需求分析
打車起步價13(3公里內(nèi)),  之后每多一公里增加 5塊錢.  用戶輸入公里數(shù)就可以計算打車價格
如果有擁堵情況,總價格多收取10塊錢擁堵費*/

 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;
       },
       // 擁堵之后的費用
       yd: function(flag) {
         return flag ? total + 10 : total;
       }
    }
 })();
console.log(car.price(5)); // 23
console.log(car.yd(true)); // 33

5.5案例

 var name = "The Window";
   var object = {
     name: "My Object",
     getNameFunc: function() {
     return function() {
     return this.name;
     };
   }
 };
console.log(object.getNameFunc()())
-----------------------------------------------------------------------------------
var name = "The Window";  
  var object = {    
    name: "My Object",
    getNameFunc: function() {
    var that = this;
    return function() {
    return that.name;
    };
  }
};
console.log(object.getNameFunc()())
       

6.遞歸

6.1什么是遞歸

遞歸:如果一個函數(shù)在內(nèi)部可以調(diào)用其本身,那么這個函數(shù)就是遞歸函數(shù)茬高。簡單理解:函數(shù)內(nèi)部自己調(diào)用自己, 這個函數(shù)就是遞歸函數(shù)

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

6.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.3利用遞歸求斐波那契數(shù)列

// 利用遞歸函數(shù)求斐波那契數(shù)列(兔子序列)  1丽猬、1、2熏瞄、3脚祟、5、8巴刻、13愚铡、21...
// 用戶輸入一個數(shù)字 n 就可以求出 這個數(shù)字對應(yīng)的兔子序列值
// 我們只需要知道用戶輸入的n 的前面兩項(n-1 n-2)就可以計算出n 對應(yīng)的序列值
function fb(n) {
  if (n === 1 || n === 2) {
        return 1;
  }
  return fb(n - 1) + fb(n - 2);
}
console.log(fb(3));

6.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: '洗衣機'
   }]
 }, {
   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;
       // 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;
}

==============part4==========

1.正則表達式概述

1.1什么是正則表達式

正則表達式( Regular Expression )是用于匹配字符串中字符組合的模式。在JavaScript中胡陪,正則表達式也是對象沥寥。

正則表通常被用來檢索、替換那些符合某個模式(規(guī)則)的文本柠座,例如驗證表單:用戶名表單只能輸入英文字母邑雅、數(shù)字或者下劃線, 昵稱輸入框中可以輸入中文(匹配)妈经。此外淮野,正則表達式還常用于過濾掉頁面內(nèi)容中的一些敏感詞(替換)捧书,或從字符串中獲取我們想要的特定部分(提取)等 。

其他語言也會使用正則表達式骤星,本階段我們主要是利用JavaScript 正則表達式完成表單驗證经瓷。

1.2 正則表達式的特點

  1. 靈活性、邏輯性和功能性非常的強洞难。
  2. 可以迅速地用極簡單的方式達到字符串的復雜控制舆吮。
  3. 對于剛接觸的人來說,比較晦澀難懂队贱。比如:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$
  4. 實際開發(fā),一般都是直接復制寫好的正則表達式. 但是要求會使用正則表達式并且根據(jù)實際情況修改正則表達式. 比如用戶名: /^[a-z0-9_-]{3,16}$/

2.正則表達式在js中的使用

2.1正則表達式的創(chuàng)建

在 JavaScript 中色冀,可以通過兩種方式創(chuàng)建一個正則表達式。

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

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

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

 var rg = /123/;

2.2測試正則表達式

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

3.正則表達式中的特殊字符

3.1正則表達式的組成

一個正則表達式可以由簡單的字符構(gòu)成与学,比如 /abc/,也可以是簡單和特殊字符的組合嘉抓,比如 /ab*c/ 癣防。其中特殊字符也被稱為元字符,在正則表達式中是具有特殊意義的專用符號掌眠,如 ^ 、$ 幕屹、+ 等蓝丙。

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

MDN

jQuery 手冊:正則表達式部分

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

3.2邊界符

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

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

如果 ^和 $ 在一起渺尘,表示必須是精確匹配。

var rg = /abc/; // 正則表達式里面不需要加引號 不管是數(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

3.3字符類

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

3.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個英文字母(大寫和小寫都可以)任何一個字母返回 true  
------------------------------------------------------------------------------------
//取反 方括號內(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

3.3.2量詞符

量詞符用來設(shè)定某個模式出現(xiàn)的次數(shù)拟淮。

量詞 說明
* 重復0次或更多次
+ 重復1次或更多次
? 重復0次或1次
{n} 重復n次
{n,} 重復n次或更多次
{n,m} 重復n到m次

3.3.3用戶名表單驗證

功能需求:

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


分析:

  1. 用戶名只能為英文字母,數(shù)字,下劃線或者短橫線組成, 并且用戶名長度為6~16位.
  2. 首先準備好這種正則表達式模式/$[a-zA-Z0-9-_]{6,16}^/
  3. 當表單失去焦點就開始驗證.
  4. 如果符合正則規(guī)范, 則讓后面的span標簽添加 right類.
  5. 如果不符合正則規(guī)范, 則讓后面的span標簽添加 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)) {
   console.log('正確的');
   span.className = 'right';
   span.innerHTML = '用戶名格式輸入正確';
   } else {
   console.log('錯誤的');
   span.className = 'wrong';
   span.innerHTML = '用戶名格式輸入不正確';
   }
 }
</script>

3.3.4 括號總結(jié)

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

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

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

正則表達式在線測試

3.4預定義類

預定義類指的是某些常見模式的簡寫方式.


案例:驗證座機號碼

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

表單驗證案例

//手機號驗證:/^1[3|4|5|7|8][0-9]{9}$/;
//驗證通過與不通過更換元素的類名與元素中的內(nèi)容
 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>格式不正確,請從新輸入 ';
 }
//QQ號驗證: /^[1-9]\d{4,}$/; 
//昵稱驗證:/^[\u4e00-\u9fa5]{2,8}$/
//驗證通過與不通過更換元素的類名與元素中的內(nèi)容 ,將上一步的匹配代碼進行封裝,多次調(diào)用即可
 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> 格式不正確,請從新輸入 ';
            }
        }
 };
//密碼驗證:/^[a-zA-Z0-9_-]{6,16}$/
//再次輸入密碼只需匹配與上次輸入的密碼值 是否一致

3.5正則替換replace

replace() 方法可以實現(xiàn)替換字符串操作谴忧,用來替換的參數(shù)可以是一個字符串或是一個正則表達式很泊。

var str = 'andy和red';
var newStr = str.replace('andy', 'baby');
console.log(newStr)//baby和red
//等同于 此處的andy可以寫在正則表達式內(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/a,'哈哈')
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>

==============part5==========

ES6

什么是ES6

ES 的全稱是 ECMAScript , 它是由 ECMA 國際標準化組織,制定的一項腳本語言的標準化規(guī)范角虫。


為什么使用 ES6 ?

每一次標準的誕生都意味著語言的完善,功能的加強委造。JavaScript語言本身也有一些令人不滿意的地方戳鹅。

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

ES6新增語法

let(★★★)

ES6中新增了用于聲明變量的關(guān)鍵字

let聲明的變量只在所處于的塊級有效

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

注意:使用let關(guān)鍵字聲明的變量才具有塊級作用域枫虏,使用var聲明的變量不具備塊級作用域特性。

不存在變量提升

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

暫時性死區(qū)

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

 var tmp = 123;
 if (true) { 
     tmp = 'abc';
     let tmp; 
 } 

經(jīng)典面試題

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

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

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

經(jīng)典面試題圖解:此題的關(guā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)鍵字是不具備這個特點的
  • 防止循環(huán)變量變成全局變量
  • 使用let關(guān)鍵字聲明的變量沒有變量提升
  • 使用let關(guān)鍵字聲明的變量具有暫時性死區(qū)特性

const(★★★)

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

具有塊級作用域

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

聲明常量時必須賦值

const PI; // Missing initializer in const declaration

常量賦值后继蜡,值不能修改

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聲明的變量是一個常量
  • 既然是常量不能重新進行賦值回俐,如果是基本數(shù)據(jù)類型,不能更改值稀并,如果是復雜數(shù)據(jù)類型忘瓦,不能更改地址值
  • 聲明 const時候必須要給定值

let蝙场、const、var 的區(qū)別

  • 使用 var 聲明的變量,其作用域為該語句所在的函數(shù)內(nèi),且存在變量提升現(xiàn)象
  • 使用 let 聲明的變量,其作用域為該語句所在的代碼塊內(nèi),不存在變量提升
  • 使用 const 聲明的是常量,在后面出現(xiàn)的代碼中不能再修改該常量的值


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

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

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

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

對象解構(gòu)

 let person = { name: 'zhangsan', age: 20 }; 
 let { name, age } = person;
 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)分解汞斧,然后給變量進行賦值
  • 如果解構(gòu)不成功秋冰,變量跟數(shù)值個數(shù)不匹配的時候,變量的值為undefined
  • 數(shù)組解構(gòu)用中括號包裹,多個變量用逗號隔開募寨,對象解構(gòu)用花括號包裹贵涵,多個變量用逗號隔開
  • 利用解構(gòu)賦值能夠讓我們方便的去取對象中的屬性跟方法

箭頭函數(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)點在于解決了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指向的是被聲明的作用域里面停蕉,而對象沒有作用域的谋旦,所以箭頭函數(shù)雖然在對象中被定義,但是this指向的是全局作用域

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

剩余參數(shù)語法允許我們將一個不定數(shù)量的參數(shù)表示為一個數(shù)組兄纺,不定參數(shù)定義方式付材,這種方式很方便的去聲明不知道參數(shù)情況下的一個函數(shù)

function sum (first, ...args) {
     console.log(first); // 10
     console.log(args); // [20, 30] 
 }
 sum(10, 20, 30)

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

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

ES6 的內(nèi)置對象擴展

Array 的擴展方法(★★)

擴展運算符(展開語法)

擴展運算符可以將數(shù)組或者對象轉(zhuǎn)為用逗號分隔的參數(shù)序列

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

構(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方法授嘀,用來對每個元素進行處理,將處理后的值放入返回的數(shù)組

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

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

實例方法:find()

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

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

實例方法:findIndex()

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

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

實例方法:includes()

判斷某個數(shù)組是否包含給定的值血巍,返回布爾值萧锉。

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

String 的擴展方法

模板字符串(★★★)

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

let name = `zhangsan`;

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

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

實例方法:startsWith() 和 endsWith()

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

實例方法:repeat()

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

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

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

ES6 提供了新的數(shù)據(jù)結(jié)構(gòu) Set鲫凶。它類似于數(shù)組禀崖,但是成員的值都是唯一的,沒有重復的值螟炫。

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}

實例方法

  • 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ù)組一樣盏求,也擁有forEach方法,用于對每個成員執(zhí)行某種操作亿眠,沒有返回值碎罚。

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市缕探,隨后出現(xiàn)的幾起案子魂莫,更是在濱河造成了極大的恐慌,老刑警劉巖爹耗,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耙考,死亡現(xiàn)場離奇詭異,居然都是意外死亡潭兽,警方通過查閱死者的電腦和手機倦始,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來山卦,“玉大人鞋邑,你說我怎么就攤上這事诵次。” “怎么了枚碗?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵逾一,是天一觀的道長。 經(jīng)常有香客問我肮雨,道長遵堵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任怨规,我火速辦了婚禮陌宿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘波丰。我一直安慰自己壳坪,他們只是感情好,可當我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布掰烟。 她就那樣靜靜地躺著爽蝴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纫骑。 梳的紋絲不亂的頭發(fā)上霜瘪,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天,我揣著相機與錄音惧磺,去河邊找鬼颖对。 笑死,一個胖子當著我的面吹牛磨隘,可吹牛的內(nèi)容都是我干的缤底。 我是一名探鬼主播,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼番捂,長吁一口氣:“原來是場噩夢啊……” “哼个唧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起设预,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤徙歼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鳖枕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體魄梯,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年宾符,在試婚紗的時候發(fā)現(xiàn)自己被綠了酿秸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡魏烫,死狀恐怖辣苏,靈堂內(nèi)的尸體忽然破棺而出肝箱,到底是詐尸還是另有隱情,我是刑警寧澤稀蟋,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布煌张,位于F島的核電站,受9級特大地震影響退客,放射性物質(zhì)發(fā)生泄漏唱矛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一井辜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧管闷,春花似錦粥脚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碧囊,卻和暖如春树灶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背糯而。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工天通, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人熄驼。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓像寒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瓜贾。 傳聞我的和親對象是個殘疾皇子诺祸,可洞房花燭夜當晚...
    茶點故事閱讀 43,576評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 學習目標: 理解面向?qū)ο箝_發(fā)思想 掌握 JavaScript 面向?qū)ο箝_發(fā)相關(guān)模式 掌握在 JavaScript ...
    xlystar閱讀 298評論 0 0
  • 基本概念 語法區(qū)分大小寫標識符注釋嚴格模式語句 關(guān)鍵字和保留字 變量 數(shù)據(jù)類型typeof 操作符Undefine...
    他愛在黑暗中漫游閱讀 1,120評論 0 1
  • 1.編程思想 2.對象與類 3.面向?qū)ο蟀鎡ab 欄切換 4.構(gòu)造函數(shù)和原型 5.繼承 6.ES5新增方法 7.函...
    Scincyc閱讀 556評論 0 0
  • 學習目標: 理解面向?qū)ο箝_發(fā)思想 掌握 JavaScript 面向?qū)ο箝_發(fā)相關(guān)模式 掌握在 JavaScript ...
    小青年coder閱讀 981評論 0 2
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,106評論 0 21