call ,apply,bind

213 阅读1分钟

call apply bind 都可以改变函数的this指向

call和apply的区别

参数不同

call 语法

function.call(thisArg,arg1,arg2,…)

Apply 语法

func.apply(thisArg, [argsArray])

可以看到call和apply的第一个参数都是函数在运行时的this值,call之后接收的是参数列表,而apply接收的是数组或者类数组的值 它们的返回值都是调用有指定this值和参数的函数的结果

应用:

  • 简单用法
var name = "雪糕"
var o = {
	name:'日月当空照'
	fn:function(){
    	console.log(this.name)
    }
}

var person = {
	name:'小明'
}

o.fn.call(person) // 小明

  • 将一个数组添加到另一个数组上
var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
  • 判断数据类型
let a = {}
Object.toString.prototype.call(a)

bind

语法

function.bind(thisArg[, arg1[, arg2[, ...]]])
  • thisArg 作为this参数传递给目标函数
  • arg1,arg2 目标函数的参数
  • 返回一个新的函数

用法

function LateBloomer() {
  this.petalCount = Math.ceil(Math.random() * 12) + 1;
}

// 在 1 秒钟后声明 bloom
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};

LateBloomer.prototype.declare = function() {
  console.log('I am a beautiful flower with ' +
    this.petalCount + ' petals!');
};

var flower = new LateBloomer();
flower.bloom();  // 一秒钟后, 调用 'declare' 方法

call,apply 和 bind的区别

call和apply 会立即调用,bind是返回新的函数

手写实现call

Function.prototype.call2 = function (context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    var result = eval('context.fn(' + args +')');

    delete context.fn
    return result;
}

es6

Function.prototype.call2 = function(context, ...reset) {

    var context = context || window;
    context.fn = this;

    var result = context.fn(...reset);

    delete context.fn
    return result;
}

 

实现apply

Function.prototype.apply = function (context, arr) {
    var context = Object(context) || window;
    context.fn = this;

    var result;
    if (!arr) {
        result = context.fn();
    }
    else {
        var args = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            args.push('arr[' + i + ']');
        }
        result = eval('context.fn(' + args + ')')
    }

    delete context.fn
    return result;
}

实现bind

// 第四版
Function.prototype.bind2 = function (context) {

    var self = this;
    var args = Array.prototype.slice.call(arguments, 1);

    var fNOP = function () {};

    var fBound = function () {
        var bindArgs = Array.prototype.slice.call(arguments);
        return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
    }

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();
    return fBound;
}

参考

github.com/mqyqingfeng…