1. 程式人生 > >127_ES6 筆記5_函式,Class類,模組

127_ES6 筆記5_函式,Class類,模組

一,函式

函式基礎,參考https://blog.csdn.net/a_horse/article/details/84341897

1,預設引數

  1. 只有在未傳遞引數,或者引數為 undefined 時,才會使用預設引數
    1. function fn(name,age=17){
       console.log(name+","+age);
      }
      fn("Amy",18);  // Amy,18
      fn("Amy","");  // Amy,
      fn("Amy");     // Amy,17

       

  2. 使用函式預設引數時,不允許有同名引數
    1. // 不報錯
      function fn(name,name){
       console.log(name);
      }
       
      // 報錯
      //SyntaxError: Duplicate parameter name not allowed in this context
      function fn(name,name,age=17){
       console.log(name+","+age);
      }

       

  3. null 值被認為是有效的值傳遞
    1. function fn(name,age=17){
          console.log(name+","+age);
      }
      fn("Amy",null); // Amy,null

       

  4. 還未初始化賦值的引數值無法作為其他引數的預設值
    1. function f(x,y=x){
          console.log(x,y);
      }
      f(1);  // 1 1
       
      function f(x=y){
          console.log(x);
      }
      f();  // ReferenceError: y is not defined

       

2,不定引數

  1. 由...加上一個具名引數識別符號組成
  2. 引數為一個數組,可以通過陣列的方式來獲取
  3. function f(...values){
    	console.log(values);
    	console.log(values[0]);
    	console.log(values.length);
    }
    f(1,2);      
    f(1,2,3,4);  
    
    列印:
    [ 1, 2 ]
    1
    2
    [ 1, 2, 3, 4 ]
    1
    4

     

3,箭頭函式

  1. 基本用法
    1. //1,單引數,可以省略引數的()
      var f = a => v;
      //等價於
      var f = function(a){
       return a;
      }
      
      //2,函式單條語句,可以省略{},但預設有返回值,只是省略了return
      var f = (a,b) => a+b;
      f(6,2);  //8
      
      //3,不省略{},需要自己寫return
      var f = (a,b) =>{
      	return	a + b;
      };
      console.log(f(6,2)); //8
       
  2. 返回物件的時候,為了區分於程式碼塊,要用 () 將物件包裹起來
    1. // 報錯
      var f = (id,name) => {id: id, name: name};
      f(6,2);  // SyntaxError: Unexpected token :
       
      // 不報錯
      var f = (id,name) => ({id: id, name: name});
      f(6,2);  // {id: 6, name: 2}

       

  3. 與普通函式的區別
    1. 箭頭函式裡面沒有 this 物件,此時的 this 是外層的 this 物件,即 Window 
    2. 不可以作為建構函式,也就是不能使用 new 命令,否則會報錯
    3. 當我們需要維護一個 this 上下文的時候,就可以使用箭頭函式
      1. //一般函式
        var Person = {
        		'age': 18,
        		'sayHello': function () {
        			var self = this;
        			setTimeout(function () {
        				console.log(self.age);
        			});
        		}
        };
        
        Person.sayHello();  
        
        //箭頭函式
        var Person1 = {
        		'age': 20,
        		'sayHello': function () {
        			setTimeout(()=>{
        				console.log(this.age);
        			});
        		}
        };
        Person1.sayHello();  
        
        列印:
        18
        18

         

    4. 普通函式作為類的物件時,this為當前物件;箭頭函式作為類的物件是,this為全域性
      1. var Person = {
            'age': 18,
            'sayHello': ()=>{
                console.log(this.age);
              }
        };
        var age = 20;
        Person.sayHello();  // 20
        // 此時 this 指向的是全域性物件
         
        var Person1 = {
            'age': 18,
            'sayHello': function () {
                console.log(this.age);
            }
        };
        var age = 20;
        Person1.sayHello();   // 18
        // 此時的 this 指向 Person1 物件

         

    5. 需要動態this的時候,不能夠用箭頭函式
      1. var button = document.getElementById('userClick');
        button.addEventListener('click', () => {
             this.classList.toggle('on');
        });
        
        button 的監聽函式是箭頭函式,所以監聽函式裡面的 this 指向的是定義的時候外層的 this 物件,即 Window,導致無法操作到被點選的按鈕物件。

         

 

二,Class類

類基礎:參考https://blog.csdn.net/a_horse/article/details/84396369

  1. class類的注意點
    1. 本質是function
    2. 一般寫法:匿名類和命名類
      1. // 匿名類
        let Example = class {
            constructor(a) {
                this.a = a;
            }
        }
        // 命名類
        let Example = class Example {
            constructor(a) {
                this.a = a;
            }
        }

         

    3. 不可重複宣告
    4. 類定義不會被提升,這意味著,必須在訪問前對類進行定義,否則就會報錯。
    5. 類中方法不需要 function 關鍵字。
    6. 方法間不能加分號:class Example {}
  2. class類的屬性:4大屬性
    1. class Person {
      	constructor(name) {
      		this.name = name;
      	}
      	
      };
      Person.hands = 2;
      Person.prototype.foot = 5;
      
      var person = new Person('gaga');
      //1,例項屬性
      console.log(person.name);
      //2,靜態屬性
      console.log(Person.hands);
      //3,原型屬性
      console.log(Person.prototype.foot);
      //4,name屬性(自帶,返回class類的名稱)
      console.log(Person.name);
      
      結果:
      gaga
      2
      5
      Person

       

  3. class類的方法:4大方法
    1. class Example{
      	//1,constructor方法
      	constructor(){
      		console.log('我是constructor方法');
      		
      	//2,例項方法
      		this.methodOne =(a, b)=> {
      			console.log('我是例項方法');
      		    }
      	};
      	
      	//3,靜態方法
      	static methodTwo(a, b) {
      		console.log('我是靜態方法');
      	};
      	
      	//4,原型方法
      	methodThree(a, b) {
      		console.log('我是原型方法');
      	};
      }
      
      let exam = new Example();
      exam.methodOne(1,2);
      Example.methodTwo(1,2);
      exam.methodThree(1,2);
      
      結果:
      我是constructor方法
      我是例項方法
      我是靜態方法
      我是原型方法

       

  4. class類的getter / setter方法
    1. 作用:做一些攔截操作,在賦值之前或者賦值之後做某些操作
    2. ES5使用Object的通用方法:
      1. var user ={
        	 name:"狂奔的蝸牛"
        	} ;
        var count = 12;
        Object.defineProperty(user,"age",{
        	 get:function(){
        		console.log('b的getter');
        		return count;
        	 },
        	 set:function(newVal){
        		console.log('b的setter');
        		count=newVal;
        	 }
        	});
        
        console.log(user.age); 
        user.age=145;
        console.log(user.age);//145
        
        結果:
        b的getter
        12
        b的setter
        b的getter
        145
        145

         

    3. ES6使用get,set來訪問:物件初始化就先執行setter方法
      1. class Example1{
        	constructor(a, b) {
        		this.a = a;
        		this.b = b;
        	}
        	get a(){
        		console.log('a的getter');
        		return this._a;
        	}
        	set a(a){
        		console.log('a的setter');
        		this._a = a;
        	}
        	
        }
        
        let exam1 = new Example1(1,2); // 只輸出 setter , 不會呼叫 getter 方法
        console.log(exam1.a); // a可以直接訪問
        console.log(exam1._a); // _a可以直接訪問
        
        結果:
        a的setter
        a的getter
        1
        1

         

  5. class類的繼承
    1. 使用extend
    2. 父類建構函式,只能出現在子類的建構函式
    3. 子類 constructor 方法中必須有 super ,且必須出現在 this 之前
      1. // 父類
        class Father1 {
        	constructor(a,c){
        		this.a = a;
        		this.c = c;
        	}
        }
        
        // 子類
        class Child1 extends Father1 {
        	constructor(b){
        		super();
        		this.b = b;
        	}
        }
        
        let test1 = new Child1();
        test1.a = 2;
        test1.b = 5;
        test1.c = 7;
        console.log(test1.a); 
        console.log(test1.b);
        console.log(test1.c);
        
        結果:
        2
        5
        7
        

         

    4. 呼叫父類方法, super 作為物件,在普通方法中,指向父類的原型物件,在靜態方法中,指向父類
      1. //父類
        class Father {
        	test0(){
        		return 0;
        	}
        	static test1(){
        		return 1;
        	}
        }
        
        //子類
        class Child extends Father {
        	constructor(){
        		super();
        		// 呼叫父類普通方法
        		console.log(super.test0()); // 0
        	}
        	static test3(){
        		// 呼叫父類靜態方法
        		return super.test1() + 2;
        	}
        }
        var child = new Child;
        
        console.log(child.test0());
        console.log(Child.test3());
        
        結果:
        0
        0
        3
        
        
        	

         

 

三,模組

  • 1,匯入和匯出各種型別的變數,如函式,物件,字串,數字,布林值,類等
  • 2,每個模組都有自己的上下文,每一個模組內宣告的變數都是區域性變數,不會汙染全域性作用域。
  • 3,每一個模組只加載一次(是單例的), 若再去載入同目錄下同檔案,直接從記憶體中讀取
    • /*-----匯出的js:export [test.js]-----*/
      let myName = "Tom";
      let myAge = 20;
      let myfn = function(){
          return "My name is" + myName + "! I'm '" + myAge + "years old."
      }
      let myClass =  class myClass {
          static a = "yeah!";
      }
      export { myName, myAge, myfn, myClass }
       
      
      /*-----匯出的js:import [xxx.js]-----*/
      import { myName, myAge, myfn, myClass } from "./test.js";
      console.log(myfn());// My name is Tom! I'm 20 years old.
      console.log(myAge);// 20
      console.log(myName);// Tom
      console.log(myClass.a );// yeah!

       

  • 4,as的用法
    • 1,匯入的變數名,須和匯出的介面名稱相同
    • 2,使用 as 重新定義匯出的介面名稱,隱藏模組內部的變數
    • 3,匯出的地方使用as
      • /*-----匯出的js:export [test.js]-----*/
        let myName = "Tom";
        export { myName as exportName }
         
        /*-----匯入的js:import [xxx.js]-----*/
        import { exportName } from "./test.js";
        console.log(exportName);// Tom

         

    • 4,匯入的地方使用as
      • /*-----匯出的js1:export [test1.js]-----*/
        let myName = "Tom";
        export { myName }
        
        /*-----匯出的js2export [test2.js]-----*/
        let myName = "Jerry";
        export { myName }
        
        /*-----兩個js相同匯入import [xxx.js]-----*/
        import { myName as name1 } from "./test1.js";
        import { myName as name2 } from "./test2.js";
        console.log(name1);// Tom
        console.log(name2);// Jerry

         

  • 4,匯入import
    • 1,不允許在載入模組的腳本里面,改寫介面的引用指向,即可以改寫 import 變數型別為物件的屬性值,不能改寫 import 變數型別為基本型別的值
    • 2,多次import只執行一次
    • 3,不能使用表示式和變數匯入:如import { "f" + "oo" } from "methods";
    • import {a} from "./xxx.js"
      a = {}; // error
       
      import {a} from "./xxx.js"
      a.foo = "hello"; // a = { foo : 'hello' }

       

  • 5,匯出export
    • 1,在一個檔案或模組中,export、import 可以有多個,export default 僅有一個。
    • 2,export default 中的 default 是對應的匯出介面變數。
    • 3,通過 export 方式匯出,在匯入時要加{ },export default 則不需要。
    • 4,export default 向外暴露的成員,可以使用任意變數來接收
    • var a = "My name is Tom!";
      export default a; // 僅有一個
      export default var c = "error"; 
      // error,default 已經是對應的匯出變數,不能跟著變數宣告語句
       
      import b from "./xxx.js"; // 不需要加{}, 使用任意變數接收

       

  • 6,複合使用
    • export 與 import 可以在同一模組使用
    • 可以將匯出介面改名,包括 default。 
    • 複合使用 export 與 import ,也可以匯出全部,當前模組匯出的介面會覆蓋繼承匯出的
    • export { foo, bar } from "methods";
       
      // 約等於下面兩段語句,不過上面匯入匯出方式該模組沒有匯入 foo 與 bar
      import { foo, bar } from "methods";
      export { foo, bar };
       
      /* ------- 特點 1 --------*/
      // 普通改名
      export { foo as bar } from "methods";
      // 將 foo 轉導成 default
      export { foo as default } from "methods";
      // 將 default 轉導成 foo
      export { default as foo } from "methods";
       
      /* ------- 特點 2 --------*/
      export * from "methods";