关于绑定首先要说下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. Blog总结02(4~6次作业总结)

    Blog总结02(4~6次作业总结) 1.前言 (1)题目集04共有三道题目,第一题难度较大,第二题和第三题难度适中,第一题考察的知识点是 Java 中的字符串处理类以及正则表达式对输入字符串数据进行 ...

  2. yapi简介,安装及使用

    简介 ​ YApi 是高效.易用.功能强大的 api 管理平台,旨在为开发.产品.测试人员提供更优雅的接口管理服务.可以帮助开发者轻松创建.发布.维护 API,YApi 还为用户提供了优秀的交互体验, ...

  3. Scoring System

    ‍Build a scoring system , give the score by referee , and entering the score in system , then take o ...

  4. thinkphp 连接多个数据库(tp5.1为例)

    1.config目录下添加数据库配置,内容跟原数据库配置一样就可以(数据库名改成连接的第二个数据库名) 2.连接部分代码: $db = Db::connect(config('database2.') ...

  5. 前端用网址生成二维码(jquery)

    1.加载jquery.qrcode.min.js 2.html部分: 3.js部分:url为生成二维码的网址 附: jquery.qrcode.min.js下载 链接:https://pan.baid ...

  6. 软件测试中的测试用例Test Case原来是这么回事!

    如果你去找一份功能测试的工作,在软件测试工程师面试过程中,有一些面试官会来一两个非常简单的问题 什么是Test Case?你是如何去写Test Case的? 我们先来看一下测试用例的介绍 什么是测试用 ...

  7. MySQL DDL详情揭露

    前言: MySQL中DDL语句,即数据定义语言,用于创建.删除.修改.库或表结构,对数据库或表的结构操作.常见的有create,alter,drop等.这类语句通常会耗费很大代价,特别是对于大表做表结 ...

  8. 2020.12.20vj补题

    A - Insomnia cure 题意:一共s只龙,每隔k,l,m,n只龙就会受伤,问这s只龙有多少龙是受伤的 思路:看起来题目范围并不是很多,直接进行循环判断 代码: 1 #include< ...

  9. [敏杰开发]Beta阶段测试报告

    [敏杰开发]Beta阶段测试报告 这是一篇软工课程博客 项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 作业要求 Beta阶段测试报告 我们在这个课程的目标是 测试项目 这个作业在哪个 ...

  10. Mybatis-plus在原有的select查询语句中动态追加查询条件

    一.适用场景 1.使用了xml形式的mapper.2.不想在select查询中大量使用<if>标签来判断条件是否存在而加入条件. 二.步骤 1.自定义wrapper继承QueryWrapp ...