当前位置: 首页 > 编程日记 > 正文

浅谈 javascript 中的this绑定问题

javascript语言是在运行时前即进行编译的,而this的绑定也是在运行时进行绑定的。也就是说,this实际上是在函数被调用时候发生绑定的,它指向什么完全取决于函数在哪里被调用。

1.默认绑定

例如直接在全局作用域下声明:

var a=2;
console.log(this.a);
  • 在全局作用域下声明的变量或者函数等,都会作为window对象的属性。
  • 这个时候,默认this是绑定到全局作用域下的window对象,如果你去console.log(this);你会发现,你打印出来的是window,尽管你没有声明this就是window,但是js进行了默认绑定。
以至于你运行以下的代码片段:
function foo(){
console.log(this.a);
}
var a=2;
foo();
浏览器控制台打印出来的是 2 ;

2.隐式绑定

当函数引用有上下文对象时,在函数调用时,会进行隐式绑定。这么说肯定很抽象,还是举例说明吧。
var a=4;
function foo(){
console.log(this.a);
}
var obj={a:2,foo:foo
}
foo();
obj.foo();
两次会打印出来什么呢?猜一下?
  • foo()会打印出来4,obj.foo()会打印出来2
  • 第一个foo() 使用了默认绑定,this绑定到了全局对象window,打印 this.a 就是打印window.a;
  • 第二个foo()外层的foo函数引用作为obj.foo的属性值,通过obj进行调用,此时的obj就是这个函数引用的上下文对象,this会隐式绑定到obj这个对象上。此时打印的this.a就是obj.a了。

3.显式绑定

在上面两种绑定中,我们都没有去明确地进行强制绑定,而是使用了默认规则的绑定,那么如果我们想要在调用某个函数时特定地改变this的绑定,这个时候就可以用显式绑定了。

还是上代码,然后进行分析。

var a=4;
function foo(){
console.log(this.a);
}
var obj={a:2,foo:foo
}
var foo1=foo.bind(obj);
foo();
foo.call(obj);
foo.apply(obj);
foo.call(window);
foo1();
按照顺序打印出的是 4 ,2 ,2, 4,2
  • 第一次打印了4 使用了默认绑定,foo函数的this绑定到了window。
  • 第二次打印了2 使用了call函数,显式地将foo函数的this绑定到obj对象。
  • 第三次打印了2 apply方法的效果跟call方法一样。
  • 第四次打印了4 call方法显示地将foo函数的this绑定到了obj对象,效果跟默认绑定一样了。
  • 第五次打印了2,bind方法显示地将foo函数的this绑定到了obj,并且返回了一个硬编码后的新函数,赋值给foo1变量进行调用,硬编码就是新函数内部this直接绑定到了指定的对象,也就是obj。

4.new 绑定

使用new方式进行调用函数时,会发生构造函数的调用。怎么解释呢,还是直接上代码加分析。
function foo(a){this.a=a;
}
foo(3);
var test=new foo(2);
console.log(a);
console.log(test.a);
打印出来的是 3 ,2
  • foo函数只是一个普通的函数,直接调用foo(3)只是作为普通函数的调用,会使用默认绑定将this绑定到window上,对window.a也就会全局变量a进行赋值,所以打印出来的是3;
  • foo函数,进行构造调用,this绑定到test对象,故而this.a作为test对象的属性并进行传参赋值。打印出来的test就是{a:2},this.a就是2了。
先上图,然后根据文字阅读

图片描述

使用new 调用函数之后,该foo函数才作为构造函数进行调用,构造一个全新的对象赋值给test,而test对象的_proto_
指向了test的prototype对象,test的prototype对象有一个属性constructor,指向test的构造函数foo,这个就是javascript的原型链,也是javascript的特性。对于test对象调用的方法以及属性,会先在test对象进行寻找,如果找到的话,就直接进行调用,寻找停止。如果寻找不到,顺着原型链,在test对象的prototype对象寻找,如果找到的话,进行调用,寻找停止,如果还是找不到,会在prototype对象的原型上进行寻找,这个时候_proto_指向了Object的prototype对象,Object的prototype的constructor指向了Object()本身,而一些Obejct的函数如toString等等就是在这个原型上进行调用的,这个时候如果还是找不到需要属性或者方法,那么就是语法错误,未定义了。因为Object的prototype的_proto_指向是null了,也就没有任何对象属性以及方法了。

不是说程序员可以new 很多个对象嘛,但是new出来的对象 原型最终结果却是指向了 空(null),所以还是自己动手丰衣足食吧,哈哈。

一般情况下,使用new函数之后构造的对象,会优先将函数调用到的this绑定到这个对象,如果函数没有返回其它对象,会自动调用返回这个新对象。

总结:

只有对于this绑定的情况有了基本的了解,才能在编写代码时候,避免产生由于绑定带来的未知bug。如果你在调用某个框架插件或者绑定事件的时候,发现this不好用了,有可能是你的this使用绑定错了,打印下console.log(this)在控制台看一看,也许就发现问题了。

如果在阅读中遇到什么问题,欢迎评论以及留言。同时欢迎我的博客陈建光的博客

欢迎评论以及留言,同时欢迎关注我的博客定时不断地更新我的文章 陈建光的博客

相关文章:

Centos用yum安装X Winodw

安装Centos 5.6系统的时候我没有先装任何组件,现在用X Window,需要再安装X Window,就可以启动图形界面了,但是默认的图形界面是很简陋的界面,可以根据需要再安装GNOME或KDE桌面环境安装X图形界面#可查询哪些组件是否已…

玩具javascript:cookie管理

2019独角兽企业重金招聘Python工程师标准>>> ;(function(window, undefined){var CookieUtil window.CookieUtil window.CookieUtil || {};var doc window.document;// 读取名称为name的Cookie信息CookieUtil.read function(name){// 暂无Cookieif(doc.cookie.l…

详解 Pandas 与 Lambda 结合进行高效数据分析

作者 | 俊欣来源 | 关于数据分析与可视化这篇文章小编来讲讲lambda方法以及它在pandas模块当中的运用,熟练掌握可以极大地提高数据分析与挖掘的效率导入模块与读取数据我们第一步需要导入模块以及数据集import pandas as pddf pd.read_csv("IMDB-Movie-Data.c…

前端工程师成长之多读好书

1 引言 乱七八糟的书看了很多,有一本讲JavaScript的印象特别深开篇说的是"JavaScript是Java的脚本语言",但还是看完了,最后忘了书名。 下面列的这些都是看过后至少记得起书名的,也有部分是经常看的书,一起列…

linux下配置vnc的方法

网上这样的文章很多了,好多前辈们都把自己的经验配置共享出来,受益匪浅,现在整理一下。 下面摘录的两篇文章各有侧重,结合起来可以配置的比较完善了。总结一下,只需要四步:step1 在当前linux系统用户us…

用 Python 画圣诞树的 N 种玩法

作者 | 写代码的明哥来源 | Pyhton编程时光马上就是圣诞节了,先提前祝大家圣诞快乐!今天来给大家分享一波如何使用 Python 来画一颗圣诞节树,包含多种版本,从平民版到豪华版,像极了一个程度员从入门到高级秃头程序员的…

ORM武器:NHibernate(三)五个步骤+简单对象CRUD+HQL

前面的两篇文章中。我们对NHibernate已经做了大致了解 《ORM利器:NHibernate(一)简单介绍》Nhibernate的作用:攻克了对象和数据库的转化问题 《ORM利器:NHibernate(二)使用CodeSmith高速生成映射…

Linux学习笔记8——bash基本概念

一个操作系统的组成中,shell是与用户最接近的部分shell:外壳,也是一种程序GUI:Gnome,KDE,XfaceCLI:sh,csh,ksh,bash,tcsh,zshLinux中大多使用bash…

UIScrollView offset in UINavigationController

转:UIScrollView offset in UINavigationController 通过设置viewCtronller的 self.automaticallyAdjustsScrollViewInsets NO; 禁用苹果scrollview提供的自适应功能。 延伸阅读:https://developer.apple.com/library/ios/documentation/UserExperience…

AI 通过眼睛的反光度,来识别是否 Deepfake 换脸

编译 | 禾木木 出品 | AI科技大本营(ID:rgznai100) Deepfake 是一种 AI换脸工具,现被滥用,从虚假宣传活动到插入一些违法内容,并且篡改后的图像是难以被检测到的。 一种新的 AI 工具提供了一项令人惊讶的简单方法来发现…

[异常笔记] spring boot 启动-2018040201

异常 1、编码引发异常 00:59:49.311 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Included patterns for restart : [] 00:59:49.318 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Excluded patterns for re…

maven基础概念学习1

2019独角兽企业重金招聘Python工程师标准>>> 1.maven是什么? 百度百科: Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。 2.maven的作用? 构建、文档…

php session 二位数组

最普通的用法:一个变量名 $_SESSION[user] 0;echo $_SESSION[user]; 使用数组: $_SESSION[user][a] 1;$_SESSION[user][b] 2;echo $_SESSION[user][a];echo $_SESSION[user][b]; 这样的好处是可以分组可以 $_SESSION[admin][a] 11;$_SESSION[admin][…

「屋漏偏逢连夜雨」,Log4j 漏洞还没忙完,新的又来了

整理 | 郑丽媛、禾木木 出品 | CSDN 这几天,Apache Log4j 2 绝对是众多 Java 程序员提到的高频词之一:由于 Apache Log4j 2 引发的严重安全漏洞,令一大批安全人员深夜修 Bug、打补丁。此次漏洞更是因为其触发简单、攻击难度低、影响人群广泛等…

利用gevent实现异步执行任务

import gevent def task(pid):gevent.sleep(2)print ("task %s done"%pid)def asynchronous():threads [gevent.spawn(task,i) for i in xrange(5)]gevent.joinall(threads)if __name__ __main__:print ("asynchronous")asynchronous()执行结果&#xff…

清理SQL多余登录信息

服务器列表、登陆帐户、密码等信息都记录在 %AppData%\Microsoft\Microsoft SQL Server\100\Tools\Shell\SqlStudio.bin (2008)%AppData%\Microsoft\Microsoft SQL Server\90\Tools\Shell\mru.dat(2005)直接删除后重新启动 SSMS …

AI 真的能够理解人类语言吗?

作者 | Melanie Mitchell 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 2011年,IBM 的人工智能系统沃森参加综艺节目《危险边缘》,并获得了冠军,当时他们宣称:“沃森能够理解自然语言的所有歧义和复杂…

【贪心】Google Code Jam Round 1A 2018 Waffle Choppers

题意:给你一个矩阵,有些点是黑的,让你横切h刀,纵切v刀,问你是否能让切出的所有子矩阵的黑点数量相等。 设黑点总数为sum,sum必须能整除(h1),进而sum/(h1)必须能整除(v1)。 先考虑横行&#xff0…

友盟数据—值得手游创业者关注的玩家数据

友盟数据—值得手游创业者关注的玩家数据 你知道“辣妈”是什么游戏的忠诚玩家吗?你知道“大龄玩家”都喜好怎样的游戏?你知道哪类玩家最“多金”?2015年,不仅宅男、宅女们爱玩游戏,辣妈和奶爸们也成了手游行业的主力军…

这个 AI 模型火上 GitHub 热榜第一,在线修复照片

编译 | 禾木木出品 | AI科技大本营(ID:rgznai100)AI 正在对照片编辑产生重大的影响,但结果是还存在很大分歧。支持者说,人工智能释放了新的艺术历年,减少了创作者花在单调工作上的时间。然而,批评者认为这些…

【我的Android进阶之旅】解决SDK升级到27.0.3遇到的GLIBC_2.14 not found、no acceptable C compiler found in $PATH等问题...

一、问题一:Failed to find Build Tools revision 27.0.3 1.1、问题描述 最近公司的Android项目都要进行SDK升级,目前在本地编译的时候将SDK升级到了27.0.3,本地运行正常,然后在jenkins服务器上跑的时候就会出现异常。异常如下所示…

解析大型.NET ERP系统 设计异常处理模块

异常处理模块是大型系统必备的一个组件,精心设计的异常处理模块可提高系统的健壮性。下面从我理解的角度,谈谈异常处理的方方面面。我的设计仅仅限定于Windows Forms,供参考。 1 定义异常类型 .NET 框架定义很多异常类型,ERP系统中…

内含福利|CSDN 携手字节跳动:云原生Meetup北京站报名热烈启动,1月8日见!

伴随云原生技术的成熟与落地,越来越多框架、中间件等开源项目相继涌现,帮助开发者和企业有效解决业务问题。2022年1月8日,CSDN携手字节跳动基础架构,将在北京举办第四场云原生线下Meetup。在这里,您可以与众多开源技术…

用Thymeleaf在前台下拉列表取值

转自:https://blog.csdn.net/u013600907/article/details/76165748转载于:https://www.cnblogs.com/sharpest/p/8875698.html

PHP使用JSON

JSON 基础 简 单地说,JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从 Web 客户机传递给服务器端程序。这个字符串看起来有点儿古怪(稍后会看…

(原创)Python文件与文件系统系列(5)——stat模块

stat模块中定义了许多的常量和函数,可以帮助解释 os.stat()、os.fstat()、os.lstat()等函数返回的 st_result 类型的对象。 通常使用 os.path.is*() 这类函数来测试一个文件的类型,这些方法对同一个文件进行多次测试时,stat()系统调用都是不可…

Azure Neural TTS能让AI语音自然逼真到什么程度?

摘要:微软Azure Neural TTS让AI语音像真人一样富有感情,自然逼真。 Neural TTS(神经网络文本转语音)是微软Azure认知服务的强大语音合成功能,自推出以来,已被广泛应用于从语音助手、新闻阅读到有声读物创作…

ReentrantLock与synchronized

1、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,如果使用 synchronized ,如…

EXT按钮事件

在EXT中,当我们要为按钮点击添加处理function的时候,可以看到一般人的实现分成2类:1.使用onClick: function xx()2.使用handler: function xx()完成后,我们会发现,无论用哪一种实现,再点击按钮时都能触发xx…

浅谈HTTP中Get与Post的区别

Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而H…