2017年7月1日 星期六

Call、Apply、Closure

※Call、Apply


※this

window.onload = () => {
    new xxx();
    ooo.o();
    xxx();
    xxx.call();
    xxx.apply();
    xxx.call(ooo);
    xxx.apply(ooo);
    xxx.bind(ooo)();
}
    
let ooo = {
    o:xxx
}
    
function xxx(){
    console.log(this);
}

※結果:


※使用 new 時,this 指的是 new 的物件
JSON 裡的變數指定一個 function,此時 this 指的是這個 function
直接呼叫時,this == window
call 和 apply 沒有參數時,this == window;有參數時,this 指的是傳進去的參數

※最後的 bind 也很類似,但不會馬上執行,所以為了馬上執行,我在最後面加上「()」



※暫時變數

window.onload = () => {
    let o = new Obj(1,2);
    o.fun = plus;
    console.log(o.fun(o.x, o.y));
    delete o.fun;
    
    // console.log(plus.call(o, o.x, o.y));
    // console.log(plus.apply(o, [o.x, o.y]));
    
    // 這樣也可以
    // console.log(plus.call(Obj, 1, 2));
    // console.log(plus.apply(Obj, [1, 2]));
}
    
function plus(p1, p2){
    return p1 + p2;
}
    
function Obj (x, y) {
    this.x = x;
    this.y = y;
    return x * y;
}

※原本的作法比較麻煩,直接使用 call 或 apply ,就不用宣告暫時變數

※call 和 apply 第一個都是放物件,而 call 將要傳進去的參數一個一個放在後面;而 apply 只有二個參數,最後放陣列



※this

window.xxx = 'x';
window.onload = () => {
    window.xxx = 'xx';
    let obj = {xxx:'xxx'};
    
    showXxx.call(window); // xx
    showXxx.call(this); // xx
    showXxx.call(obj); // xxx
    
    showXxx.apply(window); // xx
    showXxx.apply(this); // xx
    showXxx.apply(obj); // xxx
}
    
function showXxx(){
    alert(this.xxx);
}

※要注意如果 onload 裡沒有 window.xxx,會抓更外面的


※還可參考高手寫的文章

※Closure

內層可以呼叫外層的變數,但外層不能呼叫內層的變數,但可以利用閉包來達到類似的功能

let name = 'outside 2';
window.onload = () => {
    let name = 'outside';
    let o = {
        name : 'inside',
        getName:function(){
            // return this.name; // inside
            return function(){
                // return xxx();
                return this.name;
            }
        }
    };
    alert(o.getName()()); // outside
}
    
function xxx(){
    return this.name;
}

※閉包首先要了解變數存活在哪



※累加

let name = 'outside';
function xxx(x) {
    let name = x;
    return function(x){
        name += x;
        return name;
    }
}
    
let o = xxx(5);
alert(o(1)); // 6
alert(o(2)); // 8
alert(o(3)); // 11

※還可以參考高手寫的

沒有留言:

張貼留言