1. 程式人生 > >JavaScript 函式四種呼叫模式

JavaScript 函式四種呼叫模式

函式有四種形態

-> 函式形態 -> 方法形態 -> 構造器形態 -> 上下文形態(call, apply)

函式的四種呼叫模式

所有的 this 都是由當前函式決定,最終都是由函式的四種呼叫模式決定的。
① 函式呼叫模式,只會執行一段程式碼,同時函式中的 this 是全域性物件 window;返回值由return語句決定,如果沒有return語句就表示沒有返回值
function f1(){
    console.log(this);
}
f1();//window
function f2(){
    return function(){
        console.log(this);
    }
}
var f2n=f2();
f2n();//this——>window,這也是一次函式呼叫模式
function f3(){
    f3n();//函式呼叫模式——————>window
    function f3n(){
        console.log(this);
    }
}
f3();// window

② 方法呼叫模式,只會執行一段程式碼,同時方法中的 this 是方法的所有者,即當前的例項物件;返回值由 return 語句決定
//程式碼1:
var obj={
    age:10,
    say:function(){
        console.log(this.age);
    }
};
obj.say();//方法呼叫模式
//程式碼2:
function f1(){
    console.log(this);
}
var obj2={
    s1:f1//將f1函式賦值給obj2.s1屬性
};
obj2.s1();//方法呼叫模式——>this:obj2
//程式碼3:
var obj3={
    age:10,
    s1:function(){
        console.log(this.age);
    }
};
var obj4={
    age:20,
    s2:obj3.s1//將obj3.s1函式賦值給s2屬性
};
obj4.s2();//方法呼叫模式:this——>obj4

③ 構造器呼叫模式,會用來建立一個物件,還是執行一段程式碼,this 表示當前物件 返回值:    a. 沒有手動新增返回值,預設返回 this b. 返回了一個基本資料型別(number / boolean / string / null / undefined),最終返回 this    c. 返回了一個複雜資料型別(物件),最終返回該物件
//程式碼1:
function Person(){
    this.age=20;
    this.name="張三";
    console.log(this);
}
//建構函式呼叫模式:
var p1=new Person();
//程式碼2;
function P2(){
    this.age=18;
    return "abc";
}
var p2=new P2();//p2.age=18
//程式碼3:
function P3(){
    this.age=10;
    return {};
}
var p3=new P3();//p3.age:undefined
console.log("p3.age");
console.log(p3.age);
//程式碼4:
function P4(){
    this.age=10;
    return [1,3,5];
}
var p4=new P4();//p4.age:undefined
console.log("p4.age");
console.log(p4.age);

④ 上下文呼叫模式,可以用引數來控制 this 的含義 語法:         函式.call(物件,引數列表         函式.apply(物件,引數陣列         call 和 apply 除了引數不同,功能完全相同 this :     a. 傳遞一個 null / undefined ,this 指向 window
    b. 傳遞一個 數字 / 字串 / 布林值,this 指向 對應的基本包裝型別的物件(Number / String / Boolean)
    c. 傳遞一個 物件:this 指向該物件 返回值:由 return 語句決定
例如呼叫 函式 func 需要兩個引數 func( 1, 2 ) 那麼使用上下文呼叫的語法是 func.call(obj, 1, 2); func.apply(obj, [1, 2]); apply 方法就是為了處理偽陣列 借用函式呼叫 p.sayHello => p.sayHello.call(p)    p.sayHello.apply(p)
function f1(){
    console.log(this);
}
//上下文模式
f1.call(null);//window
f1.call(undefined);//window
f1.call(1);//Number的例項
f1.call("abc");//String的例項
f1.call(true);//Boolean的例項


var s1="abc";
console.log(s1.length);//3
console.log(s1[0]);//"a"
//程式碼內部建立了字串所對應的String建構函式的例項
//{0:"a",1:"b",2:"c",length:3}
//程式碼執行完畢之後,就會把這個例項給銷燬


練習題1:
function f1(){
    this.length=5;
    return function(a,b,c){
        this.length=10;
        return [1,3,5];
    }
}
//建構函式呼叫模式:
var r1=new f1();//r1是函式
console.log(r1.length);//任何函式都有一個length屬性表示形參的個數:3
//函式呼叫模式
var r2=r1();//r2:[1,3,5]
console.log(r2.length);//3
//建構函式呼叫模式
var r3=new r1();//r3:[1,3,5]
console.log(r3.length);//3

練習題2:
var length = 10;
function fn() {
    console.log(this.length);
}
var obj = {
    length: 5,
    method: function (f) {
        f();//f變數的值是fn函式,但是這裡是函式呼叫模式--->this:window————>window.length:10
        arguments[0]();//方法呼叫模式,this:arguments——>arguments.length:2
    }
}
obj.method(fn, 1);
var o1={
    0:function(){
    },
    say:function(){
    }
};
o1[0]();
//o1.0();//錯誤
o1.say();
o1["say"]();