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 可以理解为动态绑定,与调用者无关

作者:EGBDFACE

出处:https://www.cnblogs.com/EGBDFACE/p/16267447.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   EGBDFACE  阅读(613)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示