每一個函數都包含兩個非繼承而來的方法,apply()和call(),這兩方法的用途都是在特定的做用域中調用函數,實際上等於設置函數數體內的this對象的值。 apply()和call()第一個參數都同樣,運行函數的做用域 apply()第二個參數是數組,call()其他參數直接傳給函數。
function() sum(num1, num2){ return num1 + num2; } function() callSum1(num1, num2){ return sum.apply(this, arguments); //傳入arguments對象 } function callSum2(num1, num2){ retrun sum.apply(this, [num1, num2]); } alert(callSum1(10,10)); //20 alert(callSum2(10,10)); //20
在上面例子中,callSum1在執行sum()函數傳入了this值(由於是在全局做用域中調用的,因此傳入的就是window對象)和arguments對象。callSum2一樣也調用了sum()函數,但傳入的是this 和一個參數數組。數組
call()方法和apply()方法的做用相同,它們的區別僅在於接收參數的的方式不一樣,對於call()方法而言,第一個參數是this值沒有變化,變化的是其他參數都是直接傳遞給函數,在使用call()方法時,傳遞給函數的參數必須逐個列舉出來。 以下列子所示。閉包
function sum(num1, num2){ return sum1 + num2; } function callSum(num1, num2){ return sum.call(this, num1, num2); } alert(callSum(10, 10)) //20
傳遞參數並不是apply()和call()真正的用武之地,它們真正強大的地方是可以擴充函數賴以運行的做用域。app
window.color = 'red'; var o = { color: 'bule' }; function sayColor() { alert(this.color); } sayColor(); //red sayColor.call(this); //red sayColor.call(window); //red sayColot.call(o); //bule
這個例子是在前面說明this對象的示例基礎上修改而成的,這一次,sayColor()也是做爲全局函數定義的,並且在全局做用域中調用它時,它的確會顯示'red'——由於對this.color的求值會轉換成window.color的求值。而sayColor.call(this)和sayColor.call(window),則是兩種顯示地在全局做用域中調用灌輸的方式,結果固然都會顯示「red」.可是當運行sayColor.call(o)時,函數執行環境就不同, 由於此時函數體內的this對象指向了o,因而結果顯示的是‘blue’。函數
使用call()和apply()來擴充做用域的最大好處,就是對象不須要與方法耦合關係。this
es5還定義了一個方法,bind()。這個方法會建立一函數實例,其this值會被綁定到bind()函數的值。es5
window.color = 'red'; var o = { color: 'blue' } ; functuon sayColor(){ alert(this.color); } var objSayColor = sayColor.bind(o); objSayColor(); //blue
sayColor()調用bind()並傳入對象哦,建立了objSayColor()函數。 objSayColor()函數的this值等於哦,所以即便在全局做用域中調用這個函數,也會看到‘blue’spa
一個簡單bind()函數接受一個函數和一個環境,並返回一個在給定環境中調用給定的函數,而且將全部參數原封不動傳遞過去。語法以下code
function bind(fn, context){ return function(){ return fn.apply(context, arguments); } }
這個函數彷佛很簡單,但其功能是很是的強大,在bind()中建立了一個閉包,閉包使用apple()調用傳入的函數,並給apply()傳遞context對象和參數。注意這裏使用的arguments對象是內部函數的,而非bind()的。當調用返回函數時,它會在給定環境中執行被傳入的函數並給出全部參數。對象