说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

详解 JavaScript 中的 this

HTML文档下载 WORD文档下载 PDF文档下载
JavaScript中的this总是让人迷惑,应该是js众所周知的坑之一。 个人也觉得js中的this不是一个好的设计,由于this晚绑定的特性,它可以是全局对象,当前对象,或者…有人甚至因为坑大而不用this。

其实如果完全掌握了this的工作原理,自然就不会走进这些坑。来看下以下这些情况中的this分别会指向什么:

1.全局代码中的this

alert(x);// 全局变量x值为2

全局范围内的this将会指向全局对象,在浏览器中即使window。

2.作为单纯的函数调用

function fooCoder(x) {this.x = x;}fooCoder(2);alert(x);// 全局变量x值为2

这里this指向了全局对象,即window。在严格模式中,则是undefined。

3.作为对象的方法调用

var name = "clever coder";var person = {name : "foocoder",hello : function(sth){console.log(this.name + " says " + sth);}}person.hello("hello world");

输出 foocoder says hello world。this指向person对象,即当前对象。

4.作为构造函数

new FooCoder();
函数内部的this指向新创建的对象。

5.内部函数

var name = "clever coder";var person = {name : "foocoder",hello : function(sth){var sayhello = function(sth) {console.log(this.name + " says " + sth);};sayhello(}person.hello("hello world");//clever coder says hello world

在内部函数中,this没有按预想的绑定到外层函数对象上,而是绑定到了全局对象。这里普遍被认为是JavaScript语言的设计错误,因为没有人想让内部函数中的this指向全局对象。一般的处理方式是将this作为变量保存下来,一般约定为that或者self:

var name = "clever coder";var person = {name : "foocoder",hello : function(sth){var that = this;var sayhello = function(sth) {console.log(that.name + " says " + sth);};sayhello(sth);}}person.hello("hello world");//foocoder says hello world

6.使用call和apply设置this

person.hello.call(person, "world");
apply和call类似,只是后面的参数是通过一个数组传入,而不是分开传入。两者的方法定义:

call( thisArg [,arg1,arg2,… ] );  // 参数列表,arg1,arg2,...apply(thisArg [,argArray] );     // 参数数组,argArray

两者都是将某个函数绑定到某个具体对象上使用,自然此时的this会被显式的设置为第一个参数。

简单地总结

简单地总结以上几点,可以发现,其实只有第六点是让人疑惑的。

其实就可以总结为以下几点:

  1. 当函数作为对象的方法调用时,this指向该对象。
  2. 当函数作为淡出函数调用时,this指向全局对象(严格模式时,为undefined)
  3. 构造函数中的this指向新创建的对象
  4. 嵌套函数中的this不会继承上层函数的this,如果需要,可以用一个变量保存上层函数的this。

再总结的简单点,如果在函数中使用了this,只有在该函数直接被某对象调用时,该this才指向该对象。

obj.foocoder();foocoder.call(obj, ...);foocoder.apply(obj, …);

更进一步

我们可能经常会写这样的代码:

$("#some-ele").click = obj.handler;
如果在handler中用了this,this会绑定在obj上么?显然不是,赋值以后,函数是在回调中执行的,this会绑定到$(“#some-div”)元素上。这就需要理解函数的执行环境。本文不打算长篇赘述函数的执行环境,可以参考《javascript高级程序设计》中对执行环境和作用域链的相关介绍。这里要指出的时,理解js函数的执行环境,会更好地理解this。

那我们如何能解决回调函数绑定的问题?ES5中引入了一个新的方法,bind():

fun.bind(thisArg[, arg1[, arg2[, ...]]])thisArg

当绑定函数被调用时,该参数会作为原函数运行时的this指向.当使用new 操作符调用绑定函数时,该参数无效.

arg1, arg2, ...
当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数.

该方法创建一个新函数,称为绑定函数,绑定函数会以创建它时传入bind方法的第一个参数作为this,传入bind方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数.

显然bind方法可以很好地解决上述问题。

$("#some-ele").click(person.hello.bind(person));//相应元素被点击时,输出foocoder says hello world

其实该方法也很容易模拟,我们看下Prototype.js中bind方法的源码:

Function.prototype.bind = function(){  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();  return function(){    return fn.apply(object,      args.concat(Array.prototype.slice.call(arguments)));  };};

明白了么?

相信看完全文以后,this不再是坑~

Android开发进阶之NIO非阻塞包(七) Android开发进阶之NIO非阻塞包(六) Android开发进阶之NIO非阻塞包(五) Android开发进阶之NIO非阻塞包(四) Android开发进阶之NIO非阻塞包(三) Android开发进阶之NIO非阻塞包(二) Android开发进阶之NIO非阻塞包(一) Android开发进阶教程系列(一)目录篇 Android开发调试工具TraceView多图演示 Android JNI实例代码(二) Android JNI实例代码(一) Android JNI开发高级篇 Android NDK开发技巧二 Android JNI开发进阶篇 Android JNI开发提高篇 Android JNI开发入门篇 Android NDK开发技巧一 Android数据库ContentProvider封装原理 Android Permission列表,ADT 0.9.9 bug Android Theme和Styles内部定义解析 Android平台下图表绘制相关方法 Activity类的runOnUiThread方法你用过吗 Android上鲜为人知的UI控件介绍和使用 获取Android手机上的图片和视频缩略图 Android JSON解析示例代码 Android ANR介绍与避免 Windows Phone 7 SDK完善度不如Android m3 Android中使用定时器TimerTask类介绍 控制Android LED灯颜色代码 Android应用Icon大小在不同分辨率下定义 Android控件美化Shape你会用吗? win2000 VPN方式的网络的实现。 datagrid控件的数据绑定问题. 请高手教我如何搭redflag linux下JAVA开发环境,急,另给分 如何删除一个字符串的前10个字符? 资料档案库是用来干嘛的? 用EJB做后台的参数传递。高分请教! 在ASP中对数据库操作是否可以用事务提交啊? TOMCAT+SQLSERVER连接池配置问题~~高分请教~ 请教!!!如何在IntraWeb控制IE? 如何远程对局域网内的某一台计算机(假设其计算机名为comm1)实施关机操作? 为什么连不上CVS服务器? 如何用ASP读取XML中节点的属性值? 如何使用jspsmartupload 一个简单问题请进来look一下 我所知道的论坛常用语,自己以为算得上的可以往上加啊! 如何自画窗体或者PANEL,让小图象在上面排列,然后再根据顺序,一次改变小图象呢? asp.net 上传图片问题? xml中怎么取得这个值呀? 请大家给介绍一本学VC++.NET的书!谢谢 有谁用过solpartwebcontrols.dll控件来建立菜单的,请进! pcanywhere联机方式 高手请进,关于MFC的消息映射。 问一个可能是低级的问题:嵌在网页中的Windows Control能不能打印 请教:我用一个COMBOBOX作为存放表字段名,如何SELECT搜索满足条件 “三个代表”具体是指什么,希望各位JJGGMM帮忙解释一下了,谢谢!(90度鞠躬!!!!~~) 如何将装入到graphi字段的图片压缩?? 看过windows程序设计的朋友请进来 asp调用存储过程问题请教!!!!急!!!! IIS不能使用了该怎么解决? 请教C#问题(1)?? Oracle Intermedia Text支不支持中文的模糊查询 我是ORACLE菜鸟,现有一SQL语句(SQL Server语法),想转换成ORACLE语法,请指点 数据库连接问题??????????? 大虾,请看这里看看? vb中字符串中怎么输入双引号(")或单引号(')? 大家帮忙看看为什么这段代码不工作? ████ 这个帖子骂人,请斑竹秉公处理!!!!!!!████ 怎么样让时间加一个差值; 在另一个类中,怎样给Radio或Combobox赋值 ~~~~向各位高人请教三层线程模型,分可以另开贴加。 new出来的idicmpclient的onreply事件怎么响应? 那位大虾帮我看一下这断代码(JSP高分请教) 帮帮忙啦,哪位同志用过mscomm控件做点对点拨号通讯的 AspRunner是个不错的辅助编写ASP页面的工具,请问哪里有破解下载的啊?谢谢了! 在vc#中如何删除目录下的所有文件? 急 关于分级菜单 求救,如何在注册表中得到一个硬件设备(如猫)的驱动文件名称? 一个难题,希望高手能解决,急切等待! 关于网络状况测试的问题 找一款手机游戏是关于宇宙的一个星系的诞生与毁灭可以发射彗星太阳风暴增加行星元素含量从而升级,有文明 1太阳对地球及人类影响最大的是 A 太阳辐射 B黑子 C耀斑 D太阳风 2 下列与太阳辐射有关的是 A高纬度地区出现极光 B地球内部温度不断升高 C煤、石油、天然气可以提供能量 D磁暴 使磁针不能 什么叫做第四者 什么是第四者啊?现在的新名词也太多了吧~第四者到底是什么身份啊,应该不是小三那种身份的吧? 用发酵罐微载体悬浮培养时,微载体为何要硅化处理? 《分别的时候》 秦文君 1.本文写了小孩与母亲“分别”的一些事情,请分别依次予以概括.(4分)2.“这个失意的小孩把想索要又想付出的种种情感都一股脑儿掏了出来,交在我手上.”这里的 分别的时候秦文君阅读答案 分别的时候阅读答案 分别的时候 kuaiyidian 太阳风到达地球时,受什么的作用,偏向什么上空,是大气电离,产生发光现象,这就是什么. 埃及前总统穆尔西即将受审 罪名成立或法国前部长称法国总统奥朗德头号问题是韩国总统朴槿惠巴黎会见联合国教科文组阿富汗总统批评美无人机炸死巴塔头目时日本一司机醉酒驾车连撞5名女中学生后英国三百余名议员被指仍挪公款用于日常埃及前总统穆尔西即将受审 罪名成立或印度将发射火星探测器 舆论对印度太空印尼组织攻击澳大利亚百家网站 抗议澳杨洁篪会见英国客人新加坡用不粘漆对付小广告餐饮油烟污染治理纳入大气治理范围加快房地产税立法 适时推进改革印度14岁“女泰山”能用部落语和大象标题导航failed: 新生代品质先锋中级车再鼓干劲 创新工作努力让“北改”改得消失的“地软”组图:外媒聚焦三中全会《决定》标题导航中共中央关于全面深化改革吉林将出台大气污染防治细则 5年可吸
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘