2016年5月20日 星期五

function (JavaScript 2)

※剩餘參數

window.onload = () => {
    restParam('a','b','c');
}
    
function restParam(...str) {
    for(let s of str) alert(s);
}



※限制參數

限制最多幾個參數

window.onload = () => {
    RestrictionParam(); // undefined-undefined
    RestrictionParam('a','b'); // a-b
    RestrictionParam('a','b','c'); // a-b
}
    
function RestrictionParam(...[p1, p2]) {
    alert(p1 + '-' + p2);
    if(typeof(arguments[2]) != 'undefined'){
        alert(arguments[2]);
    }
}

※實際上沒有真的限制,只是傳進來不用

※...在變數的前面,和java相反

※...只能寫在參數的最後,和 java 一樣

※...傳進來的參數,可以是不同型態


※傳參數但不用

function test(){
    for(var i=0; i<arguments.length; i++){
        alert(arguments[i]);
    }
    
    for(i in arguments){
        alert(arguments[i]);
    }
}
----------
<button onclick="test('a', 'b')">f1</button>

※使用arguments還是可取得參數


※匿名function

<button onclick="(function(){alert(arguments[0])})('a')">f1</button>
<button onclick="(function(p1){alert(p1)})('a')">f2</button>

※兩種方式都可以

※這種匿名外面有圓括號,就是「(function xxx)()」最外層的圓括號,最後的圓括號是傳進去的值


※巢狀function

※無參數

function outer(){
    function inner(){
        return 1;
    }
    
    /*
    var inner = function(){
        return 1;
    }
    */
    
    return inner;
    // return inner(); 
}
----------
<button onclick="alert(outer())">f1</button>
<button onclick="alert(outer()())">f2</button>

※inner兩種方式我測的結果都一樣

※return有沒有加「()」有差
沒加時,f1按鈕是inner整個function;f2按鈕是1
有加時,f1按鈕是1;f2失效


※有參數

function outer(p1){
    function inner(p2){
        return p2;
    }
    return inner(p1); 
}
----------
<button onclick="alert(outer(2))">f1</button>
<button onclick="alert(outer(2)())">f2</button>

※有參數時,呼叫outer當然沒問題,但裡面要傳參數到內部的inner參數時,一定要有「()」,所以外面(button)無法呼叫到裡面的inner,也就是說inner function只供outer使用


※內外層互動

function outer(p1, p2){
    function inner(p3 ,p4){
        return p3 * p4;
    }
    return inner(p1, p2) + p1 + p2;
}
----------
<button onclick="alert(outer(1, 2))">f1</button>

※當然還是不能直接呼叫內部function,inner function只供outer使用


※內外層變數

var x = "xxx";
function outer(){
    var x = "ooo";
    /*
    var inner = function(){
        return x;
    }
    */
    var inner = new Function("return x;");
    return inner; 
}
----------
<button onclick="alert(outer())">f1</button>
<button onclick="alert(outer()())">f2</button>

※正常情形是抓最近的變數,但用new Function只會抓全域的,所以將全域的刪除,裡面new Function也不會抓到


※四種寫法

function f1(x){
    alert(x);
}
    
var f2 = new Function('x', 'alert(x);');
    
var f3 = function(x){
    alert(x);
}
    
var f4 = (x) => {
    alert(x);
}
----------
<button onclick="f1('F1')">f1</button>
<button onclick="f2('F2')">f2</button>
<button onclick="f3('F3')">f3</button>
<button onclick="f4('F4')">f4</button>

※f2的最後一個參數一定是內容就對了,換句話說,如果不放參數,那內容就是第一個

※f4是lambda的寫法,我用IE11了,都還是不支援,而且還會導致其他的function出錯,所以IE不要去用它

※f4可以說是從f3改的,放在f1和f2都不行

※還有匿名寫法,例如就把f1拿掉,就是了,要用時就整個搬到呼叫的方法即可

※箭頭函數沒有 this、super、arguments、new.target

※除了 f1 的寫法外,其他三種寫法,函數名稱一樣,會後者蓋前者,f1 只要名稱一樣,就會最先被蓋過去



※箭頭函數省略寫法

<script>
'use strict';
    window.onload = _ => {
        alert(xxx(9));
        ooo(8);
    }
    
    let xxx = x => {
        return x;
    }
    
    let ooo = o =>
        alert(o);
</script>

※1.如果沒有參數,除了「() =>」,還可以用「_ =>」
2.如果只有一個參數,可以省略「()」
3.如果只有一行,可以不用「{}」,但如果有回傳值,連「return」關鍵字也不能有



※一般函數和箭頭函數比較


※this

<script>
'use strict';
    window.onload = () => {
        let o = new Obj('x');
        alert(o.p);
    }
    
    function Obj(p) {
        this.p = p;
        return p;
    }
    
    /*
    let Obj = (p) => {
        this.p = p;
        return p;
    }
    */
</script>




※arguments

<script>
'use strict';
    window.onload = () => {
        xxx(9,8);
    }
    
    function xxx() {
        alert(arguments.length);
    }
    
    /*
    let xxx = () => {
        alert(arguments.length);
    }
    */
</script>




※new.target

<script>
'use strict';
    window.onload = _ => {
        Foo();
        new Foo();
    
        // x();
        // new x();
    }
    
    function Foo() {
        alert(new.target);
        if(typeof(new.target) == 'undefined'){
            alert('non constructor');
        } else {
            alert('is constructor');
        }
    }
    
    /*
    let x = _ => {
        alert(new.target);
    }
    */
</script>

※使用 new.target 可以知道是不是用 new 的方式進來的


※new.target.name

<script>
'use strict';
    window.onload = _ => {
        new Father(); // Father
        new Me(); // Me
    }
    
    class Father {
        constructor() {
            alert(new.target.name);
        }
    }
    
    class Me extends Father {
        constructor() {
            super();
        }
    }
</script>





※立刻執行的函數

(  function() {alert("一");}  )();
(  function() {alert("二");}  ());
new function() {alert("三");} ();
new Function("alert('四');")  ();
(  () => {alert("五");})      ();
    
+  function() {alert("1");}  ();
-  function() {alert("2");}  ();
!  function() {alert("3");}  ();
~  function() {alert("4");}  ();

※不需要呼叫,自己就執行了,中間可不用空格,只是方便對照而已

※如果有參數,參數值可以寫在最後面的圓括號裡

沒有留言:

張貼留言