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

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

首届中国软件工程标准高峰论坛:软件开发的新机遇与挑战 Verizon研究显示:中国成为2012年度网络间谍攻击的主要来源 Clang宣布全面支持C++11标准 北大陈钟:SEMAT—中国软件工程发展的新机遇 超华尔街预期:苹果第二财季营收为436亿美元 跨平台游戏引擎Spaceport已被Facebook收购 文科生开发GPU数据库 性能超传统数据库70倍 开发者赚了90亿:从苹果Q2财报,看iOS生态 备受开发者青睐的13款热门开源项目 Netflix赌赢《纸牌屋》背后的秘密武器:大数据分析 为什么:Google Glass只能运行Web应用? 对话Rackspace高级副总裁Jim Curry:我们没有"辜负"营销炒作 7个大数据流言——避免错误的Hadoop和云分析决策 Facebook vs. Google:撇开搜索,数据中心产业上的又一竞技 苹果将于6月10日召开WWDC 新版OS X和iOS或将面世 传Amazon今年秋季发布电视机顶盒设备 够快:不会3种以上语言的程序员不是好程序员 Cloud Foundry、Greenplum获通用电气1亿美元注资 微软推超强Android应用Switch to Windows Phone Unity CEO宣布:放弃支持Flash平台 为交房租做App:我第一年赚了7万美金 iOS越狱大神Comex加盟Google 曾错过苹果Offer 维基百科正式从MySQL迁移到MariaDB数据库 JavaScript MVC框架PK:Angular、Backbone、CanJS与Ember 大数据推广引领精准推广浪潮 ThoughtWorks负责人曾学海:数字渠道细分带来的架构演进 你画我猜2 : Draw Something 2正式发布 云中游科技CEO张帆:畅谈“找你妹”的自营销 Oracle当心,MySQL原始团队已重整旗鼓! 优秀的Meteor学习资源 ThoughtWorks美女分析师:如何规划企业在线数字渠道战略? 客户端数据备份问题 网页的定时问? Microsoft.Web.UI.WebControls.dll的中文资料! label中如何显示多行 为什么这么久了排行榜上的分类排行还没有整理出来? 十万火急!!!!!!! 远程控制问题 求助高手:连接数据库时出现ORA-01031:insufficient privileges,如何解决? asp怎么写找回密码的程序 请帮帮我 划分某个端口为多个VLAN的问题 简单问题? 在服务端对HTML元素该如何进行操作? 帮我看一下! 紧急求:闪烁功能的源代码 软件过程之一————开发过程 如何在水晶报表中利用在程序中生成的dataset来制作报表!!!!!!!!!! 请教C PLUS PLUS 如何运行其他exe程序,请大家... 求助 在哪里可以下载比较经典的C++书籍? ★关于“全选”的问题!★ 关于中文显示的问题 !!!!!! 如何用SQLBulkoprations向表中加入数据,此时应如何设置游标??加急,在线等!! 急:treeview显示成一行文本 最简单的方法是?(问题简单,过来看看) 本人想考个SCJP认证,大家觉得如何???用处大吗??在找工作的过程中? 请教:对话框上的滚动条怎么使用?我设置了,然后将窗体大小缩小(于是对话框有一部分看不见了),可是单击滚动条,不起作用,怎么办?急, 问一个数据库公式的问题! 一个IP发布两个网站的问题(在线等待) 怎样改变资源文件里字体的颜色???菜单里的字体颜色我不会改?有专家指点吗? Python 网络教室采用多播好还是广播好? 下载的问题! 如何新建一个文件夹? 将html文件存放在备注字段中,然后再输出可以吗? 如何控制一个文本框的内容随另一个文本框的内容变化而同步变化? 一个关于窗口的小问题!!!小弟初学DELPHI请多多指教!! 求助 excel导入数据时出错.高手进 请问role是干嘛的? 自动生成图片 datawind如何与window联系起来啊 存储过程同时调用和数据库异地备份问题? 在xsl中如何调用javascript 误删系统盘,救命!!! 请问ACCP和高程考试相比哪个更有份量? 求LeapFTP V2.7.3.600的注册码 5月6日我来CSDN的二周年,散分,纪念。。。。 listbox (湖南)今年非典搞得这样,会耽误报高程吗?今年有人报了吗?怎样报的? 记者手记:罗汉松——日本苗木之乡的摇中国帮助我们圆了“公路梦”格外交部:俄未被列入总统就职典礼受邀泰部署5000警察应对民主党发起反特韩国海域沉船事故一失踪中国籍船员遗体中国政府向柬埔寨提供洪灾捐款加纳抓捕43名涉嫌非法采金中国公民中方要求美方对其驻华使领馆设监听点报中国网媒业界人士呼吁“清朗网络空间”商务部:对欧盟太阳能级多晶硅双反调查温州电镀基地成立业委会 自治投票管住浙江男子纵容亲弟高速练车 赔了弟弟又斯诺登莫斯科生活照曝光 休闲打扮未戴欧元区10月份通胀率降至四年来最低尼日尔沙漠一移民车抛锚 现场发现92律师称斯诺登将从11月起在俄大型网站外交部:“10·28”暴力恐怖袭击是尼日尔沙漠车抛锚 90移民干渴而死日媒:安倍将于11月中旬出访柬埔寨和商务部发布欧盟太阳能级多晶硅“双反”11月1日起 杭州地铁1号线周末末班闷热雨季 怎样护肤更清爽?全麦越蔓莓饼干新视野号将飞越冥王星:进入未知世界芥兰菜炒卤牛肉应书岭新公司1.19亿借壳塞尔瑟斯登一圈二铁?三分频?千元?天天动听T2未来十大疯狂科技:时间旅行或成真麻辣豆皮《智龙迷城》大型更新将于6月18日开大蒜大肠炒年糕选择“止损”还是“捂股” 让这8个标当电源配件巨头打造耳机,品胜HD30小米/荣耀/魅族/360/联想6.1抹茶戚风蛋糕套牢后必须第一时间反应的四件事圣诞刷卡放大招 \"碰触即付\"智轻松跨过人生的六道坎腊肠炒荷兰豆朱大可:“末日情结”里的中国生态椰蓉蛋黄排包晕车七大克星 让你美美的享受旅程
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘