关于绑定首先要说下this的指向问题。

我们都知道:

函数调用时this指向window

对象调用函数时this指向对象本身

看下面得例子:

// 1
function test(){
const name = 'test1';
console.log(this.name)
}
constname = 'test2'
test() // test2
// 当前函数调用指向了window,所以打印的为test2 // 2
var obj = {
name:'test1',
get(){
console.log(this.name)
}
}
var name = 'test2';
obj.get() // test1
// 当前通过对象调用。this指向obj,打印test1 // 3
var obj = {
name:'test1',
get(){
console.log(this.name)
}
}
var name = 'test2';
var fn = obj.get;
fn() // test2
// 将obj.get作为值赋值给fn,执行fn,这时候相当于通过函数执行,this重新指向

那如何将this指向到我们指定的对象中呢?

js提供改变this指向的三种方法:call、apply、bind

其中call和apply执行改变this的同时会执行函数,bind是会返回一个函数。

而call与apply的区别在于参数,call可以传多个参数,而apply传一个数组作为参数。下面来看看实现:

模拟实现call

Function.prototype.myCall = function(thisArg, ...argumentArr){
if(typeof this !== 'function') {
throw new TypeError(`${this} is not function`)
};
if(thisArg === undefined || thisArg === null){
thisArg = window;
}
  //生成一个对象
var obj = Object.create(thisArg)
obj['fn'] = this;
  // 通过对象执行函数将this指向该对象
var result = obj['fn'](...argumentArr)
delete obj['fn'];
return result
} var obj = {
name:'test1',
get(data1, data2){
console.log(this.name, data1, data2)
}
}
obj.get.myCall({name: 'test2'}, 1, 2, 3) // test2,1,2 // 原理就是通过传入的新的对象来执行这个函数,就是通过对象调用函数的方式

模拟实现apply

Function.prototype.myApply = function(thisArg, argumentArr){
if(typeof this !== 'function') {
throw new TypeError(`${this} is not function`)
};
if(thisArg === undefined || thisArg === null){
thisArg = window;
}
if(argumentArr === undefined || argumentArr === null){
argumentArr = []
}
var obj = Object.create(thisArg)
obj['fn'] = this;
var result = obj['fn'](...argumentArr)
delete obj['fn'];
return result
} var obj = {
name:'test1',
get(data1, data2){
console.log(this.name, data1, data2)
}
}
obj.get.myApply({name: 'test2'}, [1, 2, 3]) // test2,1,2 // 我们发现与call唯一的不同就是入参,call使用rest 参数,将多余的参数整合成argument形式,而apply入参直接是数组

模拟实现bind

Function.prototype.myBind = function(thisArg, ...argumentArr){
if(typeof this !== 'function') {
throw new TypeError(`${this} is not function`)
};
if(thisArg === undefined || thisArg === null){
thisArg = window;
}
var self = this
var bindfn = function(){
return self.call(thisArg, ...argumentArr)
}
bindfn.prototype = self.prototype
return bindfn
} var obj = {
name:'test1',
get(data1, data2){
console.log(this.name, data1, data2)
}
}
const fn = obj.get.myBind({name: 'test2'}, 1, 2, 3)
fn() // test2,1,2 // 相比于前两个bind会有不一样,bind使用到了闭包,
// 我们之前知道函数执行this是指向window,但是这里我们执行却指向了我们的目标对象,实现这样的方式就是闭包的原因

如果我们没有赋值操作执行var self = this,而是直接使用this执行的话

this.call(thisArg, ...argumentArr)

这个时候this是指向window的,这个时候会报this.call is not a function。当我们进行赋值给self ,那么这个时候self 就形成了返回的函数fn的专属背包而不被销毁,每当我们执行fn的时候取到的this都是obj.get方法

手把手教你实现三种绑定方式(call、apply、bind)的更多相关文章

  1. v-bind绑定属性样式——class的三种绑定方式

    1.布尔值的绑定方式 <div id="demo"> <span v-bind:class="{‘class-a‘:isA ,‘class-b‘:isB ...

  2. js this详解,事件的三种绑定方式

    this,当前触发事件的标签 在绑定事件中的三种用法: a. 直接HTML中的标签里绑定 onclick="fun1()"; b. 先获取Dom对象,然后利用dom对象在js里绑定 ...

  3. Dom事件的三种绑定方式

    1.事件 2.  onclick, onblur, onfocus, 需求:请写出一个行为,样式,结构,相分离的页面.   JS,   CSS,  HTML, 示例1,行为结构样式粘到一起的页面: & ...

  4. Binding 中 Elementname,Source,RelativeSource 三种绑定的方式

    在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到过的问题做下汇总记录和理解. 1. so ...

  5. JavaScript三种绑定事件的方式

    JavaScript三种绑定事件的方式: 1. <div id="btn" onclick="clickone()"></div> // ...

  6. AutoLayout的三种设置方式之——NSLayoutConstraint代码篇

    AutoLayout是从IOS 6开始苹果引入来取代autoresizing的新的布局技术,该技术有三种设置方式,等下我来为大家一一叙述一下. 在说三种设置方式前,我们先简单的说一下autolayou ...

  7. JavaScript 三种绑定事件方式之间的区别

    JavaScript三种绑定事件的方式: 1. <div id="btn" onclick="clickone()"></div> // ...

  8. Asp.Net中的三种分页方式

    Asp.Net中的三种分页方式 通常分页有3种方法,分别是asp.net自带的数据显示空间如GridView等自带的分页,第三方分页控件如aspnetpager,存储过程分页等. 第一种:使用Grid ...

  9. Service组件 总结 + 绑定理Service三种实现方式 Messager + Binder + AIDL

    在Android中进程按优先级可以分为五类,优先级从高到低排列: - 前台进程 该进程包含正在与用户进行交互的界面组件,比如一个Activity - 可视进程 该进程中的组件虽然没有和用户交互,但是仍 ...

随机推荐

  1. Eureka原理剖析

    Eureka作为微服务中的注册中心,为微服务集群间各个服务进行调用提供寻址的功能,有了它集群间的服务只需要指定服务名称就可以了,无需再去关心服务具体部署的服务器IP,即可正常调用.下面来对其中我们开发 ...

  2. HTML / CSS技巧 – 可滚动的 tbody(漂亮表格)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. PHP正则匹配各种匹配方法

    平时做网站经常要用正则表达式,下面是一些讲解和例子,仅供大家参考和修改使用: 匹配数字 "^\d+$" //非负整数(正整数 + 0) "[1][1-9][0-9]$&q ...

  4. 【原创】Centos8安装ansible

    1.安装步骤 # 安装epel扩展源 dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rp ...

  5. hdu2492 数状数组或者线段树

    题意:      给你一些人,每个人有自己的攻击力,输入的顺序就是每个人的顺序,他们之间互相比赛,两个人比赛的条件是必须在他们两个位置之间找到一个人当裁判,这个裁判的攻击力必须在他们两个人之间,问你最 ...

  6. Shodan的使用

    目录 Shodan Shodan工作原理 Shodan的使用 使用搜索过滤 Kali中安装 Shodan Kali中Shodan的使用 Shodan Shodan 是一个搜索引擎,但它与 Google ...

  7. POJ3762 时间段用k次

    题意:       有n个任务,每个任务有自己的开始时间和结束时间,还有完成这个任务能获得的价值,然后每一天的同一个时刻只能执行一个任务,每个任务必须连续执行完成,最多可以工作m天,问这m天能获得的最 ...

  8. 不融资、不上市、不快马圈地…“佛系”ZOHO的中国生意经

    来源:钛媒体 作者:秦聪慧 "技术比肩SAP.直追微软的这家25岁"非典型"国际大厂会继续佛系下去吗? ZOHO研发中心大楼 在中国,有家相对低调的"舶来&qu ...

  9. Django(31)模板中常用的过滤器

    模版常用过滤器 在模版中,有时候需要对一些数据进行处理以后才能使用.一般在Python中我们是通过函数的形式来完成的.而在模版中,则是通过过滤器来实现的.过滤器使用的是|来使用. add 将传进来的参 ...

  10. [DB] Zookeeper

    介绍 相当于"数据库",类似linux.hdfs的属性文件结构 分布式协调框架,实现HA(High Availability) 分布式锁管理框架 保证数据在zookeeper集群之 ...