javascript函数中的this的四种绑定形式

一谈到this,很多让人晕晕乎乎的抽象概念就跑出来了,这里我就只说最核心的一点——函数中的this总指向调用它的对象,接下来的故事都将围绕这一点展开。 【故事】有一个年轻人叫”迪斯”(this),有一天,迪斯不小心穿越到一个叫 “伽瓦斯克利”(javascript)的 异世界,此时此刻迪斯身无分文, 他首先要做的事情就是——找到他的住宿的地方——调用函数的对象 javascript函数中的this的四种绑定形式

 

立即学习“Java免费学习笔记(深入)”;

回到顶部javascript函数中的this的四种绑定形式

this的默认绑定

 

立即学习“Java免费学习笔记(深入)”;

【故事——线路1】如果迪斯(this)直到天黑前都没有找到能收留自己的住所,他眼看就要过上非洲难民的生活, 这时候,一位乐善好施的魔法师村长——window救世主一般地出现了:先住在我家吧! javascript函数中的this的四种绑定形式

 

立即学习“Java免费学习笔记(深入)”;

【正文】当一个函数没有明确的调用对象的时候,也就是单纯作为独立函数调用的时候,将对函数的this使用默认绑定:绑定到全局的window对象

function fire () {     console.log(this === window)}fire(); // 输出true

登录后复制

 

立即学习“Java免费学习笔记(深入)”;

上面的例子我相信对大多数人都很简单,但有的时候我们把例子变一下就会具有迷惑性:复制代码

function fire () {  // 我是被定义在函数内部的函数哦!     function innerFire() {  console.log(this === window)      }     innerFire(); // 独立函数调用}fire(); // 输出true

登录后复制复制代码

 

立即学习“Java免费学习笔记(深入)”;

 函数 innerFire在一个外部函数fire里面声明且调用,那么它的this是指向谁呢? 仍然是window 许多人可能会顾虑于fire函数的作用域对innerFire的影响,但我们只要抓住我们的理论武器——没有明确的调用对象的时候,将对函数的this使用默认绑定:绑定到全局的window对象,便可得正确的答案了 下面这个加强版的例子也是同样的输出true复制代码

var obj = {   fire: function () {       function innerFire() {          console.log(this === window)        }        innerFire();   // 独立函数调用     }}obj.fire(); //输出 true

登录后复制复制代码

 

立即学习“Java免费学习笔记(深入)”;

【注意】在这个例子中, obj.fire()的调用实际上使用到了this的隐式绑定,这就是下面我要讲的内容,这个例子我接下来还会继续讲解 【总结】 凡事函数作为独立函数调用,无论它的位置在哪里,它的行为表现,都和直接在全局环境中调用无异 回到顶部javascript函数中的this的四种绑定形式

this的隐式绑定

【故事——线路2】 迪斯(this)穿越来异世界“伽瓦斯克利”(javascript)的时候,刚好身上带了一些钱,于是他找到一个旅馆住宿了下来   javascript函数中的this的四种绑定形式

 

立即学习“Java免费学习笔记(深入)”;

当函数被一个对象“包含”的时候,我们称函数的this被隐式绑定到这个对象里面了,这时候,通过this可以直接访问所绑定的对象里面的其他属性,比如下面的a属性 复制代码

var obj = {     a: 1,      fire: function () {           console.log(this.a)        }}obj.fire(); // 输出1

登录后复制复制代码

 

立即学习“Java免费学习笔记(深入)”;

 现在我们需要对平常司空见惯的的代码操作做一些更深的思考,首先,下面的这两段代码达到的效果是相同的:复制代码

// 我是第一段代码function fire () {      console.log(this.a)}  var obj = {      a: 1,      fire: fire  }obj.fire(); // 输出1 // 我是第二段代码var obj = {        a: 1,        fire: function () {             console.log(this.a)         }}obj.fire(); // 输出1

登录后复制复制代码

 

立即学习“Java免费学习笔记(深入)”;

 fire函数并不会因为它被定义在obj对象的内部和外部而有任何区别,也就是说在上述隐式绑定的两种形式下,fire通过this还是可以访问到obj内的a属性,这告诉我们: 1.  this是动态绑定的,或者说是在代码运行期绑定而不是在书写期2.  函数于对象的独立性, this的传递丢失问题 (下面的描述可能带有个人的情感倾向而显得不太严谨,但这是因为我希望阅读者尽可能地理解我想表达的意思)javascript函数中的this的四种绑定形式

隐式绑定下,作为对象属性的函数,对于对象来说是独立的

 基于this动态绑定的特点,写在对象内部,作为对象属性的函数,对于这个对象来说是独立的。(函数并不被这个外部对象所“完全拥有”) 我想表达的意思是:在上文中,函数虽然被定义在对象的内部中,但它和“在对象外部声明函数,然后在对象内部通过属性名称的方式取得函数的引用”,这两种方式在性质上是等价的(而不仅仅是效果上) 定义在对象内部的函数只是“恰好可以被这个对象调用”而已,而不是“生来就是为这个对象所调用的” 借用下面的隐式绑定中的this传递丢失问题来说明:复制代码

var obj = {      a: 1,    // a是定义在对象obj中的属性   1      fire: function () {   console.log(this.a)        }      } var a = 2;  // a是定义在全局环境中的变量    2var fireInGrobal = obj.fire;  fireInGrobal(); //  输出 2

登录后复制复制代码

 

立即学习“Java免费学习笔记(深入)”;

 上面这段简单代码的有趣之处在于: 这个于obj中的fire函数的引用( fireInGrobal)在调用的时候,行为表现(输出)完全看不出来它就是在obj内部定义的,其原因在于:我们隐式绑定的this丢失了!! 从而 fireInGrobal调用的时候取得的this不是obj,而是window 上面的例子稍微变个形式就会变成一个可能困扰我们的bug: 复制代码

var a = 2;var obj = {    a: 1,    // a是定义在对象obj中的属性    fire: function () {          console.log(this.a)     }}  function otherFire (fn) {     fn();}  otherFire(obj.fire); // 输出2

登录后复制复制代码

 

立即学习“Java免费学习笔记(深入)”;

 在上面,我们的关键角色是otherFire函数,它接受一个函数引用作为参数,然后在内部直接调用,但它做的假设是参数fn仍然能够通过this去取得obj内部的a属性,但实际上, this对obj的绑定早已经丢失了,所以输出的是全局的a的值(2),而不是obj内部的a的值(1) javascript函数中的this的四种绑定形式

在一串对象属性链中,this绑定的是最内层的对象

在隐式绑定中,如果函数调用位置是在一串对象属性链中,this绑定的是最内层的对象。如下所示:复制代码

var obj = {      a: 1,      obj2: {           a: 2,           obj3: {                a:3,                getA: function () {                    console.log(this.a)                    }           }       }} obj.obj2.obj3.getA();  // 输出3

登录后复制复制代码

 

立即学习“Java免费学习笔记(深入)”;

this的显式绑定:(call和bind方法)

【故事——线路3】 迪斯(this)穿越来异世界“伽瓦斯克利”(javascript),经过努力的打拼,积累了一定的财富,于是他买下了自己的房子 javascript函数中的this的四种绑定形式

 

立即学习“Java免费学习笔记(深入)”;

上面我们提到了this的隐式绑定所存在的this绑定丢失的问题,也就是对于 “ fireInGrobal = obj.fire”fireInGrobal调用和obj.fire调用的结果是不同的,因为这个函数赋值的过程无法把fire所绑定的this也传递过去。这个时候,call函数就派上用场了

 

立即学习“Java免费学习笔记(深入)”;

call的基本使用方式: fn.call(object)fn是你调用的函数,object参数是你希望函数的this所绑定的对象。fn.call(object)的作用:1.即刻调用这个函数(fn)2.调用这个函数的时候函数的this指向object对象 例子:复制代码

var obj = {      a: 1,    // a是定义在对象obj中的属性      fire: function () {         console.log(this.a)      }} var a = 2;  // a是定义在全局环境中的变量  var fireInGrobal = obj.fire;fireInGrobal();   // 输出2fireInGrobal.call(obj); // 输出1

登录后复制复制代码

 

立即学习“Java免费学习笔记(深入)”;

 原本丢失了与obj绑定的this参数的fireInGrobal再次重新把this绑回到了obj 但是,我们其实不太喜欢这种每次调用都要依赖call的方式,我们更希望:能够一次性 返回一个this被永久绑定到obj的fireInGrobal函数,这样我们就不必每次调用fireInGrobal都要在尾巴上加上call那么麻烦了。 怎么办呢? 聪明的你一定能想到,在fireInGrobal.call(obj)外面包装一个函数不就可以了嘛!复制代码

var obj = {      a: 1,    // a是定义在对象obj中的属性      fire: function () {        console.log(this.a)      }} var a = 2;  // a是定义在全局环境中的变量  var fn = obj.fire;var fireInGrobal = function () {    fn.call(obj)   //硬绑定}       fireInGrobal(); // 输出1

登录后复制复制代码

 

立即学习“Java免费学习笔记(深入)”;

如果使用bind的话会更加简单

var fireInGrobal = function () {    fn.call(obj)   //硬绑定}

登录后复制

 

立即学习“Java免费学习笔记(深入)”;

可以简化为:

var fireInGrobal = fn.bind(obj);

登录后复制

 

立即学习“Java免费学习笔记(深入)”;

call和bind的区别是:在绑定this到对象参数的同时: 1.call将立即执行该函数2.bind不执行函数,只返回一个可供执行的函数 【其他】:至于apply,因为除了使用方法,它和call并没有太大差别,这里不加赘述 在这里,我把显式绑定和隐式绑定下,函数和“包含”函数的对象间的关系比作买房和租房的区别。 javascript函数中的this的四种绑定形式

 

立即学习“Java免费学习笔记(深入)”;

因为this的缘故 在隐式绑定下:函数和只是暂时住在“包含对象“的旅馆里面,可能过几天就又到另一家旅馆住了在显式绑定下:函数将取得在“包含对象“里的永久居住权,一直都会”住在这里“ 回到顶部javascript函数中的this的四种绑定形式

new绑定

【故事】 迪斯(this)组建了自己的家庭,并生下多个孩子(通过构造函数new了许多个对象)  javascript函数中的this的四种绑定形式

 

立即学习“Java免费学习笔记(深入)”;

执行new操作的时候,将创建一个新的对象,并且将构造函数的this指向所创建的新对象 复制代码

function foo (a) {     this.a = a;} var a1  = new foo (1);var a2  = new foo (2);var a3  = new foo (3);var a4  = new foo (4); console.log(a1.a); // 输出1console.log(a2.a); // 输出2console.log(a3.a); // 输出3console.log(a4.a); // 输出4

登录后复制

相关推荐:

JavaScript中的this规则及this对象用法实例

函数调用的不同方式及this的指向详解

js中this对象用法实例详解

以上就是javascript函数中的this的四种绑定形式 的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2786395.html

(0)
上一篇 2025年3月8日 17:44:06
下一篇 2025年3月8日 17:44:21

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • JS实现文字间歇循环滚动

    本文主要和大家介绍了js实现的文字间歇循环滚动效果,涉及javascript结合时间函数定时触发实现页面元素动态操作相关技巧,需要的朋友可以参考下,希望能帮助到大家。 具体代码如下: nbsp;html>  – 间歇循环滚动#box{…

    编程技术 2025年3月8日
    200
  • tween.js缓动补间动画算法详解

    本文主要和大家介绍了tween.js缓动补间动画示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能帮助到大家。 一、理解tween.js 如果看到上面的已经理解了,可以跳过下面的部分.下面为对Tween…

    编程技术 2025年3月8日
    200
  • nodejs和express搭建多人聊天室

    准备工作:新建一个文件夹 chatroom在终端输入以下命令,按照步骤npm(没装过的去官网安装下node和npm)会自动给你生成一个package.json文件 安装express和socket.io package.json文件如下: …

    2025年3月8日 编程技术
    200
  • NodeJS爬虫详解

    一、爬虫流程 我们最终的目标是实现爬取立马理财每日的销售额,并知道卖了哪些产品,每个产品又被哪些用户在什么时间点买的。首先,介绍下爬虫爬取的主要步骤: 1. 结构分析 我们要爬取页面的数据,第一步当然是要先分析清楚页面结构,要爬哪些页面,页…

    2025年3月8日
    200
  • js代理设计模式详解

    代理模式是常见的设计模式之一,是指不直接调用实际的对象,而是通过代理对象,来间接的调用实际的对象。 为什么要采用这种间接的形式来调用对象呢?一般是因为客户端不想直接访问实际的对象,或者访问实际的对象存在困难,因此通过一个代理对象来完成间接的…

    2025年3月8日
    200
  • JS内存管理实例讲解

    js有完善的内存处理机制,所以之前我们不用特别的去关注这块的实现。页面不快了,刷新一下就好了;浏览器卡顿,重启一下就ok。但是随着spa和移动app的流行,以及未来可能存在的pwa的实现,js内存可能成为新的内存瓶颈。 1.什么是内存泄漏 …

    2025年3月8日 编程技术
    200
  • 10个js常用函数

    1,对于cookie的操作,其中包括了设置、获取、删除cookie的操作。下面这个是我在公司的项目里面使用的工具库里的方法,测试就不测试了 // setCookie()// @About 设置cookiefunction setCookie…

    2025年3月8日
    200
  • JavaScript中循环类型总结分析

    在英语中,loop这个词指的是由弯曲的曲线所产生的形状。类似的概念,loop这个词已经被用于编程中。如果你看到下图,你就会清楚的知道指令的流动是如何在一个循环的动作中不断重复的。在编程中,循环的概念并不是什么新概念,它们常常在编码时使用。虽…

    2025年3月8日 编程技术
    200
  • JS/jQuery实现DIV延时几秒后消失或显示

    本文主要和大家介绍了js/jquery实现p延时几秒后消失或显示的方法,结合实例形式分析了javascript使用settimeout及jquery使用delay方法实现延迟显示功能的相关操作技巧,需要的朋友可以参考下,希望能帮助到大家。 …

    编程技术 2025年3月8日
    200
  • JS操作剪贴板代码分享

    javascript可以轻松操作客户端剪贴板内容,不过只适用ie5以上浏览器。javascript可以使用window.clipboarddata对象处理剪贴板内容。保存到剪贴板的方法setdata(param1, param2)。本文主要…

    编程技术 2025年3月8日
    200

发表回复

登录后才能评论