【JavaScript】bind的实现

本文详细解析了JavaScript中bind方法的功能与应用,包括如何改变函数内部的this指向,bind方法与call、apply的区别,以及如何手动实现bind方法。通过实例展示了bind方法在函数调用、柯里化形式传参等场景的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最好先知道的知识:
①call和apply
②闭包以及闭包的传参
③原型链

bind方法干什么的

准确来说是Function.prototype.bind()方法,这是函数原型对象的方法。
我们都知道,函数里面的this指向向来也是一门学问。当我们想要改变这个this指向的时候,有没有什么好办法呢?

bind()方法主要就是将函数绑定到某个对象(当然包括某个函数),bind()会创建一个绑定了一个新的this的函数,函数体内的this对象的值会被绑定到传入bind()第一个参数的值,而其余参数将作为新函数的参数,供调用时使用。

例如,func.bind(obj)相当于obj.f(),这一点和call()很像,不同的是返回的是函数,不会立即执行!(下文有例子区别)

传入参数
调用绑定函数时作为this 传递给目标函数
添加到绑定函数参数列表中的参数
返回值
返回一个原函数的拷贝,并拥有指定的this值和初始参数。

深拷贝

var foo = function(){console.log("你很勇哦")}
var A= foo.bind()
var B= foo.bind()

console.log(A===B) //false 
A()//你很勇哦
B()//你很勇哦

可以看到虽然了A、B两个函数使用了foo.bind()进行拷贝,但是两者是两个独立的函数,在两个不同的内存地址中

函数调用,改变this

var obj = {name:"代码人"}
var foo = function(){
    return this;//返回this
}
var A= foo.bind(obj)
var B= foo.bind(obj)
console.log(A()===B())//true  this指向同一个obj
//记得【调用】
this.name = "window"   
var obj = {
  name: "obj",
  getName: function() { console.log(this.name); }
}

obj.getName()  //obj,对象函数this指向调用对象本身

var A= obj.getName //非严格模式下一般函数的this值window
A()  //window

A.bind(obj)() //obj  重新绑定了this

接收多个参数,柯里化形式传参 fn(1)(2)

function func(y, z){
    console.log( this.x);//这个函数没有x属性,咱们得另外绑定this
    console.log( y );
    console.log( z );
}

var obj={x:1}//一个有x属性的对象

var A =func.bind(obj,2,3)//像call一样的传参方式
A()//1 2 3

var B =func.bind(obj)//像call一样的传参方式
B(2,3)//1 2 3

var C =func.bind(obj,2)//像call一样的传参方式
C(3)//1 2 3
//你或许会疑问,为什么可以这样中断了一样传参?
//柯里化形式传参 fn(1)(2),先看下闭包

手动实现bind/原理

参考:另一个优快云博客

Function.prototype.myBind = function () {
        var self = this;   // 保存原函数
        
        context = [].shift.call(arguments);
        // 保存需要绑定的this上下文,取bind函数的第一个参数
        // 这里就是重新绑定this 的部分

        out_args = [].slice.call(arguments);    // 剩余的参数转为数组
        return function () {                    // 【闭包】返回一个新函数
           let in_args =  [].slice.call(arguments)
           self.apply(context,[].concat.call(out_args ,in_args));
           //“借用”call首先将内外的参数arguments拼接起来并到一起
           //同时也解释了上面ABC三个函数的传参差异导致一样的结果的原因---柯里化形式传参 fn(1)(2)
           //新的this主context“借用”原函数
        }
    }

解释

arguments类数组

类数组不是数组,无法直接使用数组方法,所以需要callapply借到数组对象的方法使用

函数里arguments表示传入的参数数组,具有length属性

function fff(){
	console.log(arguments)
}
fff(1,2,3,"代码")

在这里插入图片描述

[].数组方法

Array.prototype.shift === [].shift   //true
//删除并返回数组的第一个元素

闭包传参

function f1(x){
        
        function f2(y){    //f2是一个闭包
            console.log(x)
            console.log(y)
        }    
        return f2;
    }

f1(1)(2)//1 2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值