js中this指向以及改变this指向的几种方法和区别

本文记录下call、apply、bind方法的作用及其区别。

call、apply、bind都可以改变上下文即重定义this对象(函数中的this对象改变为传入的某个参数),但是call、apply是立即执行,而bind是返回一个改变上下文的函数副本,原来函数不发生变化。

apply方法接收两个参数,一个是函数运行的作用域,另一个是参数数组;call方法与apply方法不同之处在于传递给函数的参数必须列举出来。bind参数方式同call相同。

拓展

apply可以将一个数组默认转换成一个参数列表

  • 可以使用Math.max得到数组中最大项:Math.max.apply(null,array)
  • Math.min得到数组中最小项。
  • Array.prototype.push合并两个数组:Array.prototype.push.apply(arr1,arr2)

模拟实现call和apply

可以从一下几点考虑来实现:

  • 不传入第一个参数,默认为window
  • 改变了this指向,让新的对象可以执行该函数,那么思路就变成了给新的对象添加一个函数,然后再执行完以后删除。

call:

Function.prototype.myCall = function (context) {
    var context = context || window;
    // 给context添加一个属性
    context.fn = this; // 这里this就是指向调用的函数
    var args = [...arguments].slice(1); // call传递给函数的必须列举出来
    var result = context.fn(...args);
    delete context.fn;
    return result;
}

apply:

Function.prototype.myApply = function (context) {
    var context = context || window;
    context.fn = this;
    var result;
    if (arguments[1]) { // apply传递的是参数数组
        result = context.fn(...arguments[1]);
    } else {
        result = context.fn();
    }
    delete context.fn;
    return result;
}

bind:

Function.prototype.myBind = function (context) {
    if (typeof this != 'function') {
        throw new TypeError('Error');
    }
    var _this = this;
    var args = [...arguments].slice(1);
    // 返回一个函数
    return function F() {
        // 因为返回一个函数,可以使用 new F(),需要判断
        if (this instanceof F){
            return new _this(...args, ...arguments);
        }
        return _this.apply(context,args.concat(...arguments));
    }
}

this 指向问题

var length = 0;
function fn(){
    console.log(this.length);
}
var obj = {
    length: 6,
    method: function(){
        fn();
    }
}
var objBind = {
  length: 7,
  method: () => {
    fn()
  }
}
obj.method(); // 输出?
objBind.method();
// 箭头函数的 this 可以理解为动态绑定,与调用者无关
posted @ 2022-05-13 17:13  EGBDFACE  阅读(623)  评论(0)    收藏  举报