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

我们都知道:

函数调用时this指向window

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

看下面得例子:

  1. // 1
  2. function test(){
  3. const name = 'test1';
  4. console.log(this.name)
  5. }
  6. constname = 'test2'
  7. test() // test2
  8. // 当前函数调用指向了window,所以打印的为test2
  9.  
  10. // 2
  11. var obj = {
  12. name:'test1',
  13. get(){
  14. console.log(this.name)
  15. }
  16. }
  17. var name = 'test2';
  18. obj.get() // test1
  19. // 当前通过对象调用。this指向obj,打印test1
  20.  
  21. // 3
  22. var obj = {
  23. name:'test1',
  24. get(){
  25. console.log(this.name)
  26. }
  27. }
  28. var name = 'test2';
  29. var fn = obj.get;
  30. fn() // test2
  31. // 将obj.get作为值赋值给fn,执行fn,这时候相当于通过函数执行,this重新指向

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

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

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

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

模拟实现call

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

模拟实现apply

  1. Function.prototype.myApply = function(thisArg, argumentArr){
  2. if(typeof this !== 'function') {
  3. throw new TypeError(`${this} is not function`)
  4. };
  5. if(thisArg === undefined || thisArg === null){
  6. thisArg = window;
  7. }
  8. if(argumentArr === undefined || argumentArr === null){
  9. argumentArr = []
  10. }
  11. var obj = Object.create(thisArg)
  12. obj['fn'] = this;
  13. var result = obj['fn'](...argumentArr)
  14. delete obj['fn'];
  15. return result
  16. }
  17.  
  18. var obj = {
  19. name:'test1',
  20. get(data1, data2){
  21. console.log(this.name, data1, data2)
  22. }
  23. }
  24. obj.get.myApply({name: 'test2'}, [1, 2, 3]) // test2,1,2
  25.  
  26. // 我们发现与call唯一的不同就是入参,call使用rest 参数,将多余的参数整合成argument形式,而apply入参直接是数组

模拟实现bind

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

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

  1. 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. ListBox控件简单的数据绑定

    <ListBox Margin="17,8,15,26" Name="ListBoxName" ItemsSource="{Binding Ta ...

  2. system分区解锁

    前言 获取root权限,解锁system 步骤 手机设置 设置--更多设置--开发者选项--USB调试给打开 电脑操作 打开cmd adb devices 执行命令 adb root &&am ...

  3. featureCarousel.js 3d轮播图插件

    jQuery Feature Carousel 插件是国外的一比较优秀的旋转木马图片插件. 点击这里进入原文. 插件特点: 1.处理div的3d旋转木马效果. 2.支持一个中心,2个侧面的功能 3.中 ...

  4. 【SpringMVC配置失效】Springboot2.x拦截器配置不无生效

    一.环境 maven springboot版本2.x <parent> <groupId>org.springframework.boot</groupId> &l ...

  5. 常用的STL

    map      容器和数组一样,不过比较活用,相当于直接离散化数组 map<int ,int>mp 一维int map<string ,string>mp 一维 str ma ...

  6. The 2014 ACM-ICPC Asia Mudanjiang Regional First Round C

    题意:       这个是The 2014 ACM-ICPC Asia Mudanjiang Regional First Round 的C题,这个题目当时自己想的很复杂,想的是优先队列广搜,然后再在 ...

  7. 解决在Vim中鼠标右键不能粘贴问题

    最近维护一台服务器,使用putty登录后,用vim时,鼠标右键不能 粘贴而是进入了visual模式.网上查找一番找到了解决方法: 方 法一:在普通模式下键入" :set mouse-=a&q ...

  8. PowerShell-4.API调用以及DLL调用

    PowerShell可以直接调用API,So...这东西完全和cmd不是一回事了... 调用API的时候几乎和C#一样(注意堆栈平衡): 调用MessageBox: $iii = Add-Type - ...

  9. nodejs-安装/helloworld/npm

    安装---------------------------------------------------------------- http://nodejs.cn/download/ 完成之后确定 ...

  10. StreamReader & StreamWriter

    这节讲StreamReader & StreamWriter,这两个类用于操作字符或者字符串,它将流的操作封装在了底层,相对来说用法比较简单,但是它不支持Seek()方法. 先看一下代码: F ...