javascript函數篇4、函數的屬性和方法——apply()、call()和bind()方法區別

> 本篇文章的內容:
> 函數的屬性:length、prototypy、caller;
> 函數的方法: apply()、call()、bind()javascript

由於在javascript中函數也是對象,因此函數也有屬性和方法。每一個函數都包含三個屬性。java

length數組

function fn (n1, n2) {
    return n1 + n2
}
console.log(fn.length) // 2

 

**length屬性表示函數但願接收的函數個數。**瀏覽器

prototypy
每個函數都有一個prototype屬性,它是一個對象,prototype是一個極其重要的屬性,這裏只作一個簡單羅列,之後會詳細介紹。app

caller
ECMAScript5還規範化了一個函數對象的屬性,就是caller,它指向的是調用當前函數的函數的引用,若是是在全局做用域中調用當前函數,它的值爲null。函數

function a () {
    b()
}
function b () {
    console.log(b.caller) // 打印a函數的源代碼
}
a()

注意當函數在嚴格模式下執行的時候會致使錯誤!this

每一個函數都包含兩個方法:apply()和call(),另外在ECMAScript5中還定義了一個方法bind()。下面來介紹這三個方法。spa

apply()、call()、bind()
一、apply()和call()
首先apply()和call()的做用都是改變函數執行的上下文,也就是this值。每一個函數都有這兩個方法,它們的第一個參數都是你要指定的上下文,第二參數就是傳遞的參數。prototype

var obj = {
    a: 1
}
function add (b, c) {
    return this.a + b + c
}
console.log(add.apply(obj, [1, 2])) // 4
console.log(add.call(obj, 3, 4)) // 8

apply()和call()兩種方法的區別僅僅在於傳參方式,apply要以數組的形式傳參,call則須要一一傳入。對象

二、與call和apply不一樣,bind()不會當即執行
***bind()在使用的時候,調用bind()方法的函數不會當即執行,而是返回一個改變了上下文的函數副本(即從新建立了一個函數,而後將this指向bind函數的第一個參數,最後將這個新建立的函數返回)***

bind()方法是如何實現的呢?爲了更好的理解bind方法咱們來模擬一下bind方法的實現:

if (!function(){}.bind) { // 若是沒有bind方法則向Function對象的原型中添加自定義的bind方法,由於有的瀏覽器(如ie6~ie8)並不支持bind,因此若想在多個瀏覽器中使用bind能夠這樣作兼容處理
    Function.prototype.bind = function(cnt) {
        var fn = this // 獲取調用bind方法的函數
        var args = Array.prototype.slice.call(arguments) // 這裏是將bind方法內的arguments對象轉爲數組,以便arguments能使用數組的方法
            return function () { //返回一個函數, 而這個函數的內部是執行調用bind()的函數,並將執行的結果返回
                return fn.apply(cnt, args.slice(1))
            }
       }
}    

經過模擬bind()能夠清晰的看到bind方法的實現原理,爲了好理解假設有以下調用:fn.bind(obj, a, b):
在bind函數的內部是這樣操做的,首先經過this拿到調用bind方法的函數fn利用arguments對象處理傳入bind方法的參數,拿到除第一個參數之外的參數(這裏的a,b)。整個bind方法返回一個函數,函數內部執行調用bind方法的函數fn,並利用apply方法將fn的this指向傳入bind函數的第一參數(obj),並將fn執行結果返回

利用bind()方法不會當即執行的特色,咱們能夠在一些交互的時間處理函數中使用bind()。

var btn = document.getElementById("btn")
var lines = document.getElementById("lines")
btn.onclick = function() {
    console.log(this.id) // lines
}.bind(lines) // 此時處理函數不會當即執行,當點擊事件觸發時,bind()返回的函數副本執行,返回了fn.apply(cnt, args.slice(1)); apply當即執行

調用了bind方法的點擊事件處理函數不會當即執行,當點擊事件觸發時,bind()返回的函數副本執行,這時候返回了fn.apply(cnt, args.slice(1)); apply當即執行處理函數,同時改變了this指向,輸出結果爲lines。

相關文章
相關標籤/搜索