apply()、call()、bind()三個方法

apply 和 call 都是爲了解決改變 this 的指向。做用都是相同的,只是傳參的方式不一樣。
第一個參數都是改變this的指向,apply 接收一個數組做爲參數,call 接收一個參數列表。
而bind 則返回一個函數。數組

let obj = {
    value: 1
}
function getValue(name, age){
    console.log(name, age, this.value)
}
getValue.apply(obj, ['zhangsan', '18'])  // zhangsan 18 1
getValue.call(obj, 'lisi', '20')  // lisi 20 1
getValue.bind(obj, 'wangwu', '20')()  // wangwu 20 1
getValue.bind(obj)('wangwu', '20')  // wangwu 20 1


//使用apply實現二維數組降維
[].concat.apply([], [1,2,[3,4,5],[6,7]]) 
//使用call將參數列表轉爲數組
function fn(){return [].slice.call(arguments)}
function fn(...args){return arg}

//一個通用的事件綁定函數,call實現代理
function bindEvent(elem, type, selector, fn) {
    if (fn == null) {
        fn = selector
        selector = null
    }
    elem.addEventListener(type, function (e) {
        var target
        if (selector) {
            target = e.target
            if (target.matches(selector)) {
                //改變指向到目標元素
                fn.call(target, e)
            }
        } else {
            fn(e)
        }
    })
}
//使用代理
var div1 = document.getElementById('div')
    bindEvent(div1, 'click', 'a.class', function (e) {
  console.log(this.innerHTML)
})

//兼容IE8的寫法
var addEvent = (function() {
    if(window.addEventListener) {
        return function(el, type, fn, capture) {
            el.addEventListener(type, function(e) {
                fn.call(el, e);
            }, capture);
        }
    }else {
        return function(ele, type, fn) {
            el.attachEvent('on' + type, function(e) {
                fn.call(el, e);
            })
        }
    }
})()

如何實現一個apply函數

Function.prototype.myApply = function(context){
    context = context || window
    context.foo = this;
    //判斷第二個參數是否存在且是數組
    let result = arguments[1] ?
                ( Array.isArray(arguments[1]) ?
                        context.foo(...arguments[1]) : context.foo(arguments[1]))
                : context.foo()
    delete context.foo
    return result
}

如何實現一個call函數

Function.prototype.myCall = function(context){
    context = context || window
    // 第一個參數爲函數的執行上下文,就把函數賦值給foo
    context.foo = this;
    //將剩餘參數取出
    let args = [...arguments].slice(1);
    let result = context.foo(...args);
    // 執行完畢須要刪除foo屬性
    delete context.foo;
    return result;
}

如何實現一個bind函數

Function.prototype.myCall = function(context){
    context = context || window
    let _this = this;
    let args = [...arguments].slice(1);
    return fcuntion(){
        _this.apply(context, args.concat(...arguments))
    }
}
相關文章
相關標籤/搜索