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

详解 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不再是坑~

面向企业:Google发布iOS版Google Admin应用 Github推出Education平台 师生免费享有微账号 平板的市场依然巨大:应用更丰富,Phablet设备存局限 免费的PCB数据3D转换工具 OBD++ XVL Converter Hadoop Namenode以regular方式启动代码流程分析 走进支撑过8亿用户的Yahoo!数据中心 Napier,一个引领Rackspace14年老兵功成身退 Twitter最新测试版被指仿Facebook的界面设计 成功求职者的自述:如何向应聘企业展示自身价值? 仅用移动开发服务:一分钱不花,开发native应用 苹果员工爆辞职内幕 Windows Phone 8.1被曝光信息汇总 Phaser:开源的HTML5 2D游戏开发框架 HTML5调查:做的好,收入不比iOS差 汽车巨人福特让“数据”说话 基调数据解读2014网购行业的3大变化 测测:用百度Clouda占卜移动互联网 微软的无奈:或允许Android应用运行于Windows平台 如何选择适合自己的编程语言 Google Now新增语音命令:生活简单一点,让爱更近一点 千万美金收购案:GetJar是一家怎样的公司 传苹果与时代华纳等公司合作,推新一代Apple TV 追本溯源 解析“大数据生态环境”发展现状 为Hadoop存储层增加对OpenStack Swift的支持 详解并行逻辑回归 在AWS上使用GPU实现分布式神经网络 大数据时代,看“小数据”如何支持决策 22人15天研发 微信红包系统发起“珍珠港偷袭”的背后 开发产品防脱节,DevOps来帮忙 手游福音:官方中文版Unity用户手册免费发布 支持多平台!2D和3D游戏引擎Godot宣布开源 请问:如何通过JAVA程序访问Web页面? Win2000的最小安装需要多少容量?快抢分啦! 如何将一个table从原来的tablespace移到另一个tablespace 计算一个月有几周,星期一为第一天,相关语句 骆驼您好,刚才没看到你的回贴的时候,那个贴我已经结贴了,我还有问题请教,请进,多谢。 请问哪里有VTune Profiler下载?据说它能分析VC代码中各函数所占用的开销 请问如何在ftp上收发xml文件。。。请具体点告诉我或贴源码或贴相关文章地址 文件解析 VC的OPENGL编程显示提示框时,显示内容是以前绘图的,不是最新绘图的,怎么办? 请问为什么create table bbb as select * from aaa ,aaa上面的缺省值还有索引都掉了呢? 如何在数据库里存文本文件? 用什么工具可以查看内存是否有泄露, Win2000上是什么, Win98上是什么 为什么用oledbadapter不能更新数据库阿? 软件陷阱问题 请问哪里有VTune Profiler下载?据说它能分析VC代码中各函数所占用的开销 在weblogic7.0上面jsp文件运行问题 请教关于打印遇到的问题 谁能个--报表例子(水晶报表。vb.net)--报表的数据源要是动态生成的。 利用WMI管理WINDOWS 请教:如何在chm帮助文件中执行应用程序。谢谢 Weblogic+Mysql的Jsp/Java程序的数据库该怎样连接?? 在java代码中引用php的变量?请问如何写? tclientdataset问题 急!!!!VFP触发器取值问题 怎么样才能卸载REDHAT8.0下的XMMS,而装7.3下的XMMS? 请教一个有关于对话框上控件重画的问题!谢谢! 有谁知道上海高程查分方法?急!!! 请教OleDbDataReader的用法 请教一个有关于对话框上控件重画的问题!谢谢! 请教一个简单问题,显示图形滞后的问题,有人回答过,但不正确。谢谢 大家有没有见过IIS不支持数据库的? 1700--2100 之间的手机,请大家帮我推荐一下,在NOKIA,MOTOROLA,厦新,波导……中选择!! 请问谁有?divx的资料?能提供下载也行! 请问如何把从数据库中读出来的数据显示在在线编辑器里? 请教:log,乘方(pow(x, y))运算用C语言如何实现? 如何在Domino designer中添加图像资源,在线等候 所有分求asp2dll破解版,急!在线等待!! zhwdan 还是朋友!多谢你了!快来看看啊! 多文档程序,怎样在选择某一菜单命令时使窗口最大化且不能改变大小,而不是在PreCreateWindow函数中设定?在线等待 LINUX 好多问题呀! 给高分 html文件在Unix系统下有大小写之分吗??我只知道他对CGI有大小写之分。在线等待。 在线等待 怎样使单文档程序中间凹下去的部分 变成 不是凹下的,使得整个界面看上去是一个平面的~~~谢谢~~~ 存储过程怪问题 哪个更划算? 关于delphi的ISAPI开发 用标准的C++怎么样才能调用Win系统API? 一点看法 自动运行的程序!!! 月薪2000加提成,怎么样? 请各位兄弟帮个忙 “导师考核”首轮战毕姚贝娜赢了PK却好声音录制第二场导师考核 王力宏助阵吴青峰首当导师不愿妖娆:我要拿出专业小S杨丞琳为抢镜不顾形象搔首弄姿太夸坛南湾沙滩惊现"蓝眼泪&q刘璇王弢毛里求斯提前拍摄婚纱照微电影《我的哥哥是逃犯》8月全媒体上中国好声音第一季学员私下聚会照片曝光《兰陵王》林依晨冯绍峰搞笑拍摄花絮照龙丹妮首谈快男收视落后好声音:我是很龙丹妮首谈快男收视落后好声音:我是很那英“小二班”14进7人选落定 最后芙蓉姐姐京剧造型 性感露肩称最美花旦游戏嫩模歪歪街头摆拍 白衣飘飘纯比奶泰国白龙王病逝 揭白龙王神奇的一生《好声音》姚贝娜若冠军失手必是死于早《好声音》姚贝娜若冠军失手必是死于早“沈阳好声音”萱萱谈导师那英:她特别孙俪邓超穿情侣装微博打趣秀恩爱华语电影传媒大奖红毯 Angelab好声音“导师考核”结束录制梦想导师类明日提示日本客机降落时险撞汽车微·音广州可放开非中心城区限购每日一句波波维奇:马刺没人能阻止哈登和威少驾考垄断 催生腐败网上报名20日截止顺德彩民刮中10万元做创业金【讲座】京明高尔夫球场已被拆除布莱尔称卡梅伦若获得连任 将给英国带平安银行冠名美巡中国赛广铁3日至6日运客508万人次双雄之争,戏肉还在后面佛山龙狮篮球培训昨进校园佛山龙狮篮球培训昨进校园英政府警告严防“超级细菌”个人缴工资4% 退休后按月领肯尼亚越境空袭“青年党”帕金森,离你有多近?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘