call、apply、bind的实现

一、如何使用

this的四种指向:this 永远指向最后调用它的那个对象!!!

1、普通函数调用,指向window --- 如果是严格模式,指向undefined
function thisPoint() {
    console.log(this);
}
thisPoint(); //window

function thisPointStrict() {
    'use strict'
    console.log(this);
}
thisPointStrict(); //undefined
2、当this被obj.fn()调用时,指向obj.
var obj = {
    name: '测试this指向的类名字',
    fn() {
        console.log(this);
    }
}
obj.fn(); // obj 对象
3、call 改变this 的指向
function a(a, b, c) {
    name: 'a的名字';
    console.log(this.name);
    console.log(a, b, c);
}
var b = {
    name: 'b的名字'
}
a.call(b, 1, 2, 3); //b的名字  1 2 3
4、apply改变this的指向
a.apply(b, [1, 2, 3]) //b的名字  1 2 3

总结 call和apply

相同点:
  1、都是改变this指向的
使用区别:
  1、call 第一个参数是this指向的对象,后边是参数列表
  2、apply 第一个参数是this指向的对象,后边是参数数

5、bind改变this指向
  bind会生成并且返回一个函数,这个函数的this指向第一个参数。
var c = a.bind(b, 1, 2, 3);
c(); //b的名字  1 2 3

 二、实现

1、call实现code

Function.prototype.mycall = function(context, ...arg) {
    const fn = Symbol('临时属性');
    context[fn] = this;
    context[fn](...arg);
    delete context[fn];
    }
    //思路:
    // 1、通过对象属性的方式调用函数,这个函数里面的this指向这个对象。
    // 每次调用新增一个symbol属性,调用完毕删除。
    // 这个symbol属性就是调用mycall方法的函数
    //函数形参中使用 ...arg 是将多个形参塞到一个数组里面,在函数内部使用arg这个变量时,就是包含所以形参。
    // 在调用context[fn](...arg) 时候,...arg是为了展开数组,依次传入参数调用函数。
var obj = {
    name: '测试的obj的名字'
}

function test(a, b, c) {
    console.log(this.name);
    console.log(a, b, c);
}
test.mycall(obj, 1, 2, 3)

2、apply实现code

Function.prototype.myApply = function(context, arg) {
    const fn = Symbol('属性');
    context[fn] = this;
    context[fn](...arg);
    delete context[fn]
}

const obj2 = {
    name: '测试Obj2的名字'
}

function test(a, b, c) {
    console.log(this.name);
    console.log(a, b, c);
}

test.myApply(obj2, [2, 3, 4])

//总结 :
// call 是传参的列表,所以一开始需要...arg; apply 是传参数组,不需要...arg

3、bind实现code

var obj = {
    name: '我是obj的名字'
}

function test(a, b, c) {
    name: '我是test的名字';
    console.log(this.name);
    console.log(a, b, c);
}
// bind跟call和apply的区别: bind返回一个新的函数,并且不会调用。  call和apply会改变原函数的this指向,并且调用
Function.prototype.myBind = function(objThis, ...params) {
    const _this = this;
    let fToBind = function(...secoundarg) {
        const isNew = this instanceof fToBind;
        const context = isNew ? this : Object(objThis);
        return _this.call(context, ...params, ...secoundarg);
    }
    fToBind.prototype = Object.create(_this.prototype);
    return fToBind;
}
var fnbind = test.myBind(obj, 2, 3, 4)
fnbind()
原文地址:https://www.cnblogs.com/qianqiang0703/p/14885548.html