js中bind()使用详情

2023-05-16

前言

最近在在搞React的时候有用到bind()的时候,因为他的用法其实我还一直不是特别的清楚,所以今天我把bind()他的用法和我遇到的结合起来这样来写一个博客,这样应该可以加深自己的印象同时可以来跟好的来解析bind的使用方法

1.那么我们先来介绍一下bind()

Function.prototype.bind()

   bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()中的第一个参数的值,例如:f.bind(obj),实际上可以理解为obj.f(),这时f函数体内的this自然指向的是obj;

这个可能大家都很明白了,那么我们可以来看下下面的这个例子

  var a = {
    b: function() {
      var func = function() {
        console.log(this.c);
      }
      func();
    },
    c: 'hello'
  }
  a.b(); 
  console.log(a.c); 

那么答案是什么呢?undefined和hello,大家可以打印看下,这个就是因为fun()这个函数执行的时候他的函数上下文为window,而a.b()的这个函数的执行的时候函数上下文this为a对象是什么意思呢?

  var a = {
    b: function() {
      console.log(this.c); //hello  
      var func = function() {
        console.log(this.c); //undefined
      }
      func();
    },
    c: 'hello'
  }
  a.b(); 
  

看了上面的例子和console.log()的结果大家应该是知道了这个函数上下文大概是这么一回事了把?什么还是不会好把看这里,这里有关于this指向的问题的解析那么问题来了当我们希望func()他的输出的值就是为hrllo怎么办

方法一:改变this的值

  var a = {
    b: function() {
      var _this = this; // 通过赋值的方式将this赋值给that
      var func = function() {
        console.log(_this.c);
      }
      func();
    },
    c: 'hello'
  }
  a.b(); // hello
  console.log(a.c); // hello

方法二:绑定this的值发生改变

// 使用bind方法一
  var a = {
    b: function() {
      var func = function() {
        console.log(this.c);
      }.bind(this);
      func();
    },
    c: 'hello'
  }
  a.b(); // hello
  console.log(a.c); // hello

// 使用bind方法二
  var a = {
    b: function() {
      var func = function() {
        console.log(this.c);
      }
      func.bind(this)();
    },
    c: 'hello'
  }
  a.b(); // hello
  console.log(a.c); // hello

这里我们以a.b()的形式去执行a对象中的b这个函数,是经过对象a的所以当我们来执行a对象中b函数的时候找this就会先找到a对象所以在a对象中的b这个函数中的this为a对象,所以这个时候bind,绑定的this也就是为a对象了

    c = 10;
    var a = {
      b: function () {
        console.log(this);
        var func = function () {
          console.log(this.c);
        }.bind(this);
        func();
      },
      c: 'hello'
    }
    var d = a.b;
    d();

这里我们以d()的形式去执行a对象中的b这个函数吗,因为d()的执行的时候由于没人应用this默认为window,所以在a对象中的b这个函数中的this为window,所以不这个时候bind,绑定的this也就是为window了

bind()的原生实现分步解析

1:通过call,吧arguments生成一个真正的数组

Array.prototype.slice.call(arguments)是用来将参数由类数组转换为真正的数组;
[].slice.call(arguments)是用来将参数由类数组转换为真正的数组;

上面两中方法的结果一样

解析:其实就是arguments他是一个类数组(对象)他没slice的方法 ,通过上面的Array.prototype.slice写法可以让他添加slice的方法,为什么可以呢?

slice()没参数默认从key0到最后一项,浅拷贝,不影响原数组

因为其实arguments也是一个对象,就相当与是在arguments中执行了slice()函数那么不要参数的情况下就是根据key下标会返回一个完整的数组从而达到了生成了一个新的数组的效果,arguments对象中是有length属性和0.1.2.这样的属性的而slice就是会根据这些0.1.2的这些key(也叫属性值的东西)放回成为一个数组

原生bing实现

    Function.prototype.myBind = function () {
      if (typeof this !== 'function') throw 'caller must be a function'
      let self = this // 这里是关键 用来和new出来的比较原型来判断是否为new出来的  当前函数对象
      let context = arguments[0]
      let args = Array.prototype.slice.call(arguments, 1) // 旧:参数
      let fn = function () {
        let fnArgs = Array.prototype.slice.call(arguments) // 新:参数
        // bind 函数的参数 + 延迟函数的参数
        // 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
        self.apply(this instanceof self ? this : context, args.concat(fnArgs))
      }
      fn.prototype = Object.create(self.prototype) // 维护原型
      return fn
    }

关键点

1.bing是影响不到new构造函数过程中this为新构造出来的那个对象的定义

当一个绑定函数是用来构建一个值的,原来提供的 this 就会被忽略。 ---MDN

代码:this instanceof self

this:对myBing出来的函数所用者的指向

self:使用myBing()的那个函数

instanceof:用来检查构造函数的prototype属性是否出现在某一个实例对象的原型链上

代码: fn.prototype = Object.create(self.prototype) // 维护原型,用来满足instanceof的条件(下面分析)

2.由于返回的是新定义出来的函数,所以原型要记得绑定 

3.Object.create()  专门用来绑定__proto__的

分析

这里帮忙分析下子在用new流程的时候为什么要---(this instanceof self)

var YAxisPoint = Point.MyBind(null, 0/*x*/);

var axisPoint = new YAxisPoint(5);

我们以上面代码为例子,所以可以得出

1. self:Point 函数

我们使用关键词new的时候在执行YAxisPoint函数,那么YAxisPoint 函数中的this就是我们new出来的实例了

2..this = 新出来的实例对象

由于this等于新new出来的实例其实this instanceof self不应该为true的,因为新创建的函数和引用myBind的函数(self函数)完全无瓜葛

但是,fn.prototype = Object.create(self.prototype),导致fn构造函数new出来的实例指向的prototype和引用myBind的函数(self函数)的prototype是一样的,所以this instanceof self === true

意外的痛苦

apply和call实现

    Function.prototype.newApplyOrCall = function () {
      // 预防
      if (typeof this !== 'function') throw '请使用函数调用'
      let self = arguments[0] || window // 虽然是必填项但是在非严格模式,null undefined 会默认转为window
      let args = [...arguments].flat().slice(1)

      let fn = Symbol("_newApplyOrCallFn");
      self[fn] = this // 这里添加属性还是有点问题,并不可以完全删除
      // Reflect.deleteProperty(self, fn) // 删除属性
      const res = self[fn](...args)
      // delete self[fn]
      Reflect.deleteProperty(self, fn) // 删除属性
      return res
    }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

js中bind()使用详情 的相关文章

  • Spring LDAP - 绑定成功连接

    我正在尝试使用 Spring LDAP 和 Spring 安全性进行身份验证 然后查询我们的公司 LDAP 我设法使身份验证工作 但当我尝试运行搜索时 我总是遇到以下异常 为了执行此操作 必须在连接上成功完成绑定 经过大量研究后 我有一个理
  • std::bind 绑定函数

    我无法检测到为什么这不能编译 我有一些返回 a 的 lambda 函数std function基于一些论点 我已将问题范围缩小到此代码片段 它不使用 lambda 但完美地重现了我的错误 include
  • 使用 std::bind 时从 std::function 获取函数指针

    我正在尝试使用std function和这个结合std bind 但我遇到了一些问题 这有效 include
  • 以编程方式删除焦点?

    我有一个 jquery ui 对话框 其中包含动态加载的选项卡 JSON 内容 由于复杂性 我无法真正发布小提琴或相关代码 代码太多 发生的情况是 当对话框打开时 您可以通过选项卡浏览对话框中的元素 直到第一个选项卡 之后 您将无法通过 T
  • 启动 docker 守护进程监听特定端口的正确方法

    我是 Docker 新手 希望以守护进程模式启动它 监听特定的 IP 地址和端口 在里面文档 https docs docker com reference commandline daemon 据说这可以通过写来完成sudo usr bi
  • 未捕获的类型错误:对象 [object Object] 没有方法“on”

    谁能帮我解决这个问题 当我使用最新 或较新 版本的 jQuery 时 下面的小脚本可以正常工作 但是 当我使用旧版本的 jQuery 时 我的脚本显示on函数不存在 这是我的脚本 不适用于旧版本的 jQuery document ready
  • “调用/应用”和“绑定”之间有什么区别[重复]

    这个问题在这里已经有答案了 var obj x 81 getX function console log this x var getX obj getX bind obj use obj as this getX 81 var getX
  • 如何绑定未绑定的方法而不调用它?

    在Python中 有没有一种方法可以绑定未绑定的方法而不调用它 我正在编写一个 wxPython 程序 对于某个类 我决定将所有按钮的数据分组在一起作为类级元组列表 如下所示 class MyWidget wx Window buttons
  • 禁用点击事件处理程序一段时间

    我已经看过类似的问题 但提供的答案涉及按钮而不是 div 元素 当我单击带有 id 的 div 元素时click 单击事件处理程序被禁用unbind 并设置一个 2 秒的计时器 2 秒后 应再次启用单击事件处理程序bind 问题是单击事件处
  • 在 ASP.NET 中将对象数组的 List 绑定到 ListView

    我正在绞尽脑汁去解决一个问题 我有一个方法返回一个List
  • std::绑定到std::函数?

    我使用这个得到一个编译错误 std vector
  • 在 gnuplot 5 中捕获超文本值

    我确实喜欢 gnuplot 5 中新的超文本功能 但我仍然缺少一些东西 我不仅希望悬停在某个点附近来阅读一些隐藏的文本 而且我还希望能够捕获超文本 如果这个超文本是一个鼠标变量 就像 MOUSE X 和 MOUSE Y 一样 捕获它将是一个
  • 如何将 AngularJS 变量传递给 Javascript?

    我正在构建一个带有模态窗口的 AngularJS Web 应用程序 在模态窗口中 我可以显示 JQuery Flot 实时图表 类似于 http people iola dk olau flot examples realtime html
  • Javascript的Bind实现?

    Since bind不是跨浏览器 old ones 函数 有一个填充函数 摘自约翰 雷西格的书 1 Function prototype bind function 2 3 var fn this 4 args Array prototyp
  • 无法组合 X <字符> 和 X <双精度>

    我正在尝试使用以下命令将各种 csv 文件合并到一个数据框中 df lt list files path C Users pattern csv full names TRUE gt lapply read csv gt bind rows
  • 绑定地址和MySQL服务器[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我在尝试配置 MySQL 服务器时遇到了绑定地址 我为什么要配置绑定地址的详细信息在下面的链接中 多个主机名和多个权限 https sta
  • SQL Server:如何将固定值绑定到列?

    假设我定义了一个 char 列类型 我想严格限制它的值 例如 黑 白 红 蓝 我怎样才能做到这一点 据我所知 这在 Access 中很容易 P 如果只有几个允许的值 那么您可以使用CHECK约束 http msdn microsoft co
  • 使用 jQuery 将播放/暂停/结束功能绑定到 HTML5 视频

    我正在尝试绑定play pause and ended使用 jQuery 的事件但有一个问题 当我右键单击视频并选择播放或暂停时 图标会正确更改 当我单击播放按钮时 它会更改为暂停 但如果我单击暂停按钮继续播放视频 它不会更改为再次播放 谁
  • jQuery 中使用 bind() 和each() 分配事件处理程序的区别?

    有人可以告诉我使用bind 分配事件处理程序有什么区别吗 function someElement bind mouseover function e this css change color bind mouseout function
  • 使用文本框搜索 datagridview 中的列 (vb.net)

    如何使用文本框搜索 datagridview 中的列 我正在使用 vb net 2010 我有一个带有数据源的 Datagridview 下面是我用于填充 datagridview 的代码 网格视图将有 4 列 Private Sub Lo

随机推荐

  • 关于offsetLeft和offsetTop的兼容性问题

    不试一下怎么知道自己不可以 xff1f 首先我们要看下offsetLeft和offsetTop他们两的API的作用 xff1b 元素相对于offsetParent的左边距和上边距 xff08 为什么没有bottom xff0c right呢
  • js深度拷贝和浅度拷贝的深入理解

    首先我们来说说什么是拷贝 xff1a 就是复制的同时加上了传值 然后问题就来了什么是有深度的什么是浅度的 xff0c 在想要了解我们这个问题之前我们先来了解一下下面的一个知识点 基本类型传递 xff0c 引用类型传递 首先我们来看下基本类型
  • npm的基本使用

    npm的下载 npm的下载其实就是把node js 百度下node官网 下载好了那么npm就附带下载好了 检查是否下载好 window 43 r 后输入cmd打开终端 xff0c 在终端中输入node v xff1b npm v 他们会输出
  • 从 (a==1&&a==2&&a==3) 成立中看javascript的隐式类型转换

    几天上班看到一个题目就是 if a 61 61 1 amp amp a 61 61 2 amp amp a 61 61 3 console log 34 a等于什么才会输出这一句话呢 xff1f 34 当a为什么的时候输出 xff1a a等
  • Bootstrap实用功能总结

    导航栏 xff1a navbar 导航栏容器可以包含以下几个常用组成 xff1a 1 品牌LOGO xff08 navbar brand xff09 2 导航菜单 xff08 navbar nav xff09 3 导航文本 xff08 na
  • 微信小程序的AJAX初次体验

    GET请求 微信小程序用GET传送数据 微信小程序通过 wx request发送ajax请求 wx request url app globalData pubSiteUrl 43 39 user information get infor
  • vue总结系列 ------ 组件之间的传值

    原因 半年前开始学Vue学到了今天 xff0c 也没有机会好好整理一下自己的知识点 xff0c 因为上公司的项目不是依赖于Vue xff0c 还是在用JQ 和文件之间来传递代码 xff0c 所以其实在对vue的学习成面上来讲对我的帮助并不大
  • vue总结系列 --- 插槽slot

    前因 这个是我这个系列的第二篇 这一篇文章我也修改过三次 xff08 2019 9 10 xff09 我是想以vue官方文档为基础 xff0c 来进行理解 xff0c 有人说有官方文档 xff0c 还要写自己的文章干嘛 xff0c 我的用意
  • vue总结系列 --- 生命周期

    前言 在总结其他的时候发现还是应该先复习vue的生命周期 xff0c 所以就先把生命周期先复习完了 经过一系列的视频 xff0c 文档我把我的总结写一下生命周期分为3个阶段 xff1a 创建 xff0c 更新 xff0c 和销毁 我们看图说
  • vue总结系列 ---- 响应式原理

    检测变化 vue是数据驱动的视图框架DOM是通过数据映射的 xff0c 只有数据改变 xff0c DOM才改变 那么数据是怎么来的呢 xff1f 1 来自父元素的属性 xff08 prop xff09 2 来自组件的自身状态 xff08 d
  • Object.defineProperty()的学习了解

    背景 最近在总结vue系列的时候是看到响应原理的时候 看到一个新的知识点也就是我们的标题Object defineProperty 的时候 xff0c 好了话不多说 xff0c 我们来看看这个是怎么使用的 开始 strong Object
  • vue总结系列 ----- 单向数据流

    可能很多人都以为vue的双向绑定其实是错误的 xff0c vue真正的是单向数据流 xff0c vue的双向绑定只不过是语法糖 我的理解是 xff1a model层 xff1a data对象中的数据 xff0c 或后台传过来的数据 view
  • vue总结系列 ---- 在组件上的v-model单向数据流

    背景 目前是在复习vue原理的过程中 xff0c 前端负责人知道我最近在复习vue xff0c 跟我说要我看组件上的v model 我一听本来是不想放在心上的 xff0c 刚好那天晚上没什么事干想看一下 xff0c 毕竟负责人 xff0c
  • ES6 函数扩展

    参数默认值 也就是说现在ES6对函数中的参数添加了默认值 我们在ES5种的处理 function Fn a b b 61 b 34 nodeing 34 return a 43 b console log Fn 34 hello 34 这样
  • ES6 对象扩展

    对象简写 对象中又分了属性和方法的简写 在es5中 xff0c 有这样一种写法 var name 61 34 xiaoqiang 34 var age 61 12 var obj 61 name name age age 在es6中 xff
  • Bootstrap基础学习笔记

    网格系统 row定义一行 col均分列数 xff0c 最多一行12列 每列左右间隙各15px col 1到12 定义在所有屏幕下的列宽 col sm md lg xl 1到12 定义在指定屏幕下该列占据的列宽 xff0c sm 屏幕 gt
  • ES6 Symbol用法

    Symbol用法 什么是Symbol Symbol是es6中一种新增加的数据类型 xff0c 它表示独一无二的值 es5中我们把数据类型分为基本数据类型 xff08 字符串 数字 布尔 undefined null xff09 和引用数据类
  • img标签中的src在绝对引用的时候的问题

    昨天晚上我一个朋友目前在培训 xff0c 他在群里问了下img标签如何绝对路径引用 xff0c 我当时就笑了这个就是培训机构的老师 xff0c 就大概看了一下就告诉我朋友那里错了 xff0c 但是却出来不 xff0c 我就想自己写一个dem
  • 在vue-cli中使用vue-router的学习笔记

    以前不会vue cli的时候学过router xff0c 当时的写法和在vue cli中的写法还是有一些不一样的 xff0c 但是我以后应该还是会用vue的单文件写小程序啊什么的所以我就吧我学习的过程全部记录下来 router创建 那么问题
  • js中bind()使用详情

    前言 最近在在搞React的时候有用到bind 的时候 xff0c 因为他的用法其实我还一直不是特别的清楚 xff0c 所以今天我把bind 他的用法和我遇到的结合起来这样来写一个博客 xff0c 这样应该可以加深自己的印象同时可以来跟好的