函数 this 指向问题

Feb 18, 2023Work

问题引出

公司代码 widget 定义的方式是:

var pipe_manageLayers = L.widget.bindClass(L.widget.BaseWidget.extend({
    // ...
    initOverlaysLayerManager: function () {
        // initOverlaysLayerManager this 指向 pipe_manageLayers
        var setting = {
            callback: {
                onCheck: this.treeOverlays_onCheck,
            }
        };
    },
    treeOverlays_onCheck: function (e, treeId, treeNode) {
        
    },
}));
var pipe_manageLayers = L.widget.bindClass(L.widget.BaseWidget.extend({
    // ...
    initOverlaysLayerManager: function () {
        // initOverlaysLayerManager this 指向 pipe_manageLayers
        var setting = {
            callback: {
                onCheck: this.treeOverlays_onCheck,
            }
        };
    },
    treeOverlays_onCheck: function (e, treeId, treeNode) {
        
    },
}));

pipe_manageLayers 内定义了很多变量和函数。设计逻辑上,在这个模块上定义的所有函数,this 指向都是 pipe_manageLayers。 但是 treeOverlays_onCheck 不被 pipe_manageLayers 所调用,this 指向出现问题。解决方法,在 treeOverlays_onCheck 赋值给 setting.callback.onCheck 时,将 this 绑定为 pipe_manageLayers

bind 原理

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

const module = {
  x: 42,
  getX() {
    return this.x;
  }
};

const unboundGetX = module.getX;
// unboundGetX 是被全局调用的 this 指向 window,window 没有 x
unboundGetX(); // undefined

const boundGetX = unboundGetX.bind(module);
// 将 unboundGetX 的 this 指向 module
boundGetX();//42
const module = {
  x: 42,
  getX() {
    return this.x;
  }
};

const unboundGetX = module.getX;
// unboundGetX 是被全局调用的 this 指向 window,window 没有 x
unboundGetX(); // undefined

const boundGetX = unboundGetX.bind(module);
// 将 unboundGetX 的 this 指向 module
boundGetX();//42

注意:函数只能使用一次 bind,多次 bind 绑定无效,函数的 this 指向始终是第一个 bind 被调用时传入的对象。

apply

const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);
const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);

apply() 方法调用一个具有给定 this 值的函数,以及以一个**数组(或一个类数组对象)**的形式提供的参数。

call

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

备注: 该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组