bind、call、apply 区别?如何实现一个bind?

巴拉米 等级 765 0 0
标签: bindJavascript

一、作用

callapplybind作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向

那么什么情况下需要改变this的指向呢?下面举个例子

var name="lucy";  
const obj={  
    name:"martin",  
    say:function () {  
        console.log(this.name);  
    }  
};  
obj.say(); //martin,this指向obj对象  
setTimeout(obj.say,0); //lucy,this指向window对象  

从上面可以看到,正常情况say方法输出martin

但是我们把say放在setTimeout方法中,在定时器中是作为回调函数来执行的,因此回到主栈执行时是在全局执行上下文的环境中执行的,这时候this指向window,所以输出luck

我们实际需要的是this指向obj对象,这时候就需要该改变this指向了

setTimeout(obj.say.bind(obj),0); //martin,this指向obj对象  

二、区别

下面再来看看applycallbind的使用

apply

apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入

改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){  
    console.log(this,args);  
}  
let obj = {  
    myname:"张三"  
}  

fn.apply(obj,[1,2]); // this会变成传入的obj,传入的参数必须是一个数组;  
fn(1,2) // this指向window  

当第一个参数为nullundefined的时候,默认指向window(在浏览器中)

fn.apply(null,[1,2]); // this指向window  
fn.apply(undefined,[1,2]); // this指向window  

call

call方法的第一个参数也是this的指向,后面传入的是一个参数列表

apply一样,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){  
    console.log(this,args);  
}  
let obj = {  
    myname:"张三"  
}  

fn.call(obj,1,2); // this会变成传入的obj,传入的参数必须是一个数组;  
fn(1,2) // this指向window  

同样的,当第一个参数为nullundefined的时候,默认指向window(在浏览器中)

fn.call(null,[1,2]); // this指向window  
fn.call(undefined,[1,2]); // this指向window  

bind

bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)

改变this指向后不会立即执行,而是返回一个永久改变this指向的函数

function fn(...args){  
    console.log(this,args);  
}  
let obj = {  
    myname:"张三"  
}  

const bindFn = fn.bind(obj); // this 也会变成传入的obj ,bind不是立即执行需要执行一次  
bindFn(1,2) // this指向obj  
fn(1,2) // this指向window  

小结

从上面可以看到,applycallbind三者的区别在于:

  • 三者都可以改变函数的this对象指向

  • 三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefinednull,则默认指向全局window

  • 三者都可以传参,但是apply是数组,而call是参数列表,且applycall是一次性传入参数,而bind可以分为多次传入

  • bind是返回绑定this之后的函数,applycall 则是立即执行

三、实现

实现bind的步骤,我们可以分解成为三部分:

  • 修改this指向

  • 动态传递参数

// 方式一:只在bind中传递函数参数  
fn.bind(obj,1,2)()  

// 方式二:在bind中传递函数参数,也在返回函数中传递参数  
fn.bind(obj,1)(2)  
  • 兼容new关键字

整体实现代码如下:

Function.prototype.myBind = function (context) {  
    // 判断调用对象是否为函数  
    if (typeof this !== "function") {  
        throw new TypeError("Error");  
    }  

    // 获取参数  
    const args = [...arguments].slice(1),  
          fn = this;  

    return function Fn() {  

        // 根据调用方式,传入不同绑定值  
        return fn.apply(this instanceof Fn ? new fn(...arguments) : context, args.concat(...arguments));   
    }  
}  
收藏
评论区

相关推荐

call、apply、bind三者为改变this指向的方法。
共同点: 第一个参数都为改变this的指针。若第一参数为null/undefined,this默认指向window 差异点如下: 1.call(无数个参数) 第一个参数:改变this指向 第二个参数:实参 使用之后会自动执行该函数 function fn(a,b,c){ console.log(this,abc); // this指
bind、call、apply 区别?如何实现一个bind?
一、作用 call、apply、bind作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向 那么什么情况下需要改变this的指向呢?下面举个例子 var name"lucy"; const obj{     name:"martin",     say:function () {         co
golang学习之gin(五):数据绑定及验证
一、数据绑定:1\. 数据绑定介绍:Gin提供了两类绑定方法: Must bind: Methods: Bind, BindJSON, BindXML, BindQuery, BindYAML Behavior: 这些方法属于MustBindWith的具体调用. 如果发生绑定错误, 则请求终
JavaScript中call()、apply()、bind()的用法
call() apply() bind() 都是用来更改 this 的指向的其中bind() 返回的是一个函数,必须执行才行传参差异:call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:call的参数是直接放进去的,第二第三第n个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,'
MongoDB配置教程
MongoDB是一个面向文档的非关系型数据库 教程 http://www.runoob.com/mongodb/mongodb-tutorial.html https://www.cnblogs.com/mfmdaoyou/p/7121547.html 1.配置环境变量 将解压目录加入PATH中 2.启动服务 mongod --dbpat
jasypt
1 问题描述 ====== 在Spring Boot中使用jasypt-spring-boot进行加密,但是提示: Description: Failed to bind properties under 'spring.datasource.password' to java.lang.String:
UDT协议实现分析——bind、listen与accept
UDT Server启动之后,基于UDT协议的UDP数据可靠传输才成为可能,因而接下来分析与UDT Server有关的几个主要API的实现,来了解下UDT Server是如何listening在特定UDP端口上的。主要有UDT::bind(),UDT::listen()和UDT::accept()等几个函数。 bind过程 ====== 通常UDT Se
MySQL在Ubuntu远程配置
MySQL远程连接访问 =========== 在普通Linux下配置: ------------ 在这个配置文件 /etc/mysql/my.cnf 修改: bind-address        = 127.0.0.1 修改为 #bind-address        = 127.0.0.1 或者 b
NIS服务器学习
前提环境: 1、安装的必须的软件包 ypserv,yp-bind,yp-tool 关于包的说明: ypserv:服务器端必须的软件包 yp-bind:客户端需要的包 yp-tool:与yp相关的命令的包 PS:NIS服务跟NFS服务有些共同之处,都需要启动portmap服务 检查机器是否已安装的包,若没有,就安装相关的包。基本上系
ES6中箭头函数与普通函数this的区别(转)
看到一篇别人的博客,对this的理解又加深了一些。 **普通函数中的this:** 1\. this总是代表它的直接调用者, 例如 obj.func ,那么func中的this就是obj 2.在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window 3.在严格模式下,没有直接调用者的函数中的thi
IE下propertychange事件引发的栈溢出问题解决
$(".com_text").bind("input propertychange", function() { //函数执行... }); 在IE 下居然 栈溢出。 Stack overflow at line XXX 堆栈溢出几乎都是陷入死循环了. 修改成onkeydown的事件绑定来处
JS 中的this指向问题和call、apply、bind的区别
#### this的指向问题 * 一般情况下this对象指向调用函数的对象,全局环境中执行函数this对象指向window。 function a(){ console.log(this); //输出函数a中的this对象 } function b(){}; var c={name:"call"}
Linux下搭建DNS服务器
1、安装服务 yum –y install bind #安装DNS 服务 yum install bind-utils –y #安装DNS 检测工具 2、编辑配置文件 vi /etc/named.conf ![](https://oscimg.oschina.net/oscnet/6fbaba1ac79f1df84bae
React组件中的函数绑定this的几种方式
在React中使用class定义组件时如果不注意this的指向问题,会带来一些麻烦。 绑定this主要有下面两种方法: 1\. bind() 在class中定义函数,然后在**构造方法**中使用bind()绑定当前的组件对象。 class MyComponent extends React.Component { constr
Redis bind属性的配置与redis连接
Redis连接 ------- 文章出处,https://blog.csdn.net/a578977626/article/details/78202202 **bind配置了什么ip,别人就得访问bind里面配置的ip才访问到redis服务。** 一台主机,可能会有多张网卡,或者对应多网段内网的Ip,公网IP等,也就意味着其他机器可以通过多个IP地址