学习起因:
在之前的JavaScript学习中,this,call,apply总是让我感到迷惑,但是他们的运用又非常的广泛。遂专门花了一天,来弄懂JavaScript的this,call,apply。
中途参考的书籍也很多,以《JavaScript设计模式与开发实践》为主,《JavaScript高级程序设计》、《你不知道的JavaScript》为辅。这三本书对我理解this,call,apply都起了很大的帮助。
this
首先,我们先讲述this。
在《JavaScript设计模式与开发实践》关于this的描述中,我认为有一句话切中了this的核心要点。那就是:
JavaScript的this总是指向一个对象
具体到实际应用中,this的指向又可以分为以下四种:
- 作为对象的方法调用
- 作为普通函数调用
- 构造器调用
- apply和call调用
接下来我们去剖析前3点,至于第4点的apply和call调用,会在call和apply部分详细讲解。
1.作为对象的方法调用
说明:作为对象方法调用时,this指向该对象。
举例:
/** * 1.作为对象的方法调用 * * 作为对象方法调用时,this指向该对象。 */ var obj = { a: 1, getA: function() { console.log(this === obj); console.log(this.a); } }; obj.getA(); // true , 1
2.作为普通函数调用
说明:作为普通函数调用时,this总是指向全局对象(浏览器中是window)。
举例:
/** * 2.作为普通函数调用 * * 不作为对象属性调用时,this必须指向一个对象。那就是全局对象。 */ window.name = 'globalName'; var getName = function() { console.log(this.name); }; getName(); // 'globalName' var myObject = { name: "ObjectName", getName: function() { console.log(this.name) } }; myObject.getName(); // 'ObjectName' // 这里实质上是把function() {console.log(this.name)} // 这句话赋值给了theName。thisName在全局对象中调用,自然读取的是全局对象的name值 var theName = myObject.getName; theName(); // 'globalName'
3.构造器调用
说明:作为构造器调用时,this指向返回的这个对象。
举例:
/** * 3.作为构造器调用 * * 作为构造器调用时,this指向返回的这个对象。 */ var myClass = function() { this.name = "Lxxyx"; }; var obj = new myClass(); console.log(obj.name); // Lxxyx console.log(obj) // myClass {name: "Lxxyx"}
但是如果构造函数中手动指定了return其它对象,那么this将不起作用。
如果return的是别的数据类型,则没有问题。
var myClass = function() { this.name = "Lxxyx"; // 加入return时,则返回的是别的对象。this不起作用。 return { name:"ReturnOthers" } }; var obj = new myClass(); console.log(obj.name); // ReturnOthers
4.Call和Apply
Call和Apply的用途一样。都是用来指定函数体内this的指向。
Call和Apply的区别
Call:第一个参数为this的指向,要传给函数的参数得一个一个的输入。
Apply:第一个参数为this的指向,第二个参数为数组,一次性把所有参数传入。
如果第一个参数为null,则this指向调用的本身。
1.改变this指向
说明:这是call和apply最常用的用途了。用于改变函数体内this的指向。
举例:
var name = "GlobalName" var func = function() { console.log(this.name) }; func(); // "GlobalName" var obj = { name: "Lxxyx", getName: function() { console.log(this.name) } }; obj.getName.apply(window) // "GlobalName" 将this指向window func.apply(obj) // "Lxxyx" 将this指向obj
2.借用其它对象的方法
这儿,我们先以一个立即执行匿名函数做开头:
(function(a, b) { console.log(arguments) // 1,2 // 调用Array的原型方法 Array.prototype.push.call(arguments, 3); console.log(arguments) // 1,2,3 })(1,2)
函数具有arguments属性,而arguments是一个类数组。
但是arguments是不能直接调用数组的方法的,所以我们要用call或者apply来调用Array对象的原型方法。
原理也很容易理解,比如刚才调用的是push方法,而push方法在谷歌的v8引擎中,源代码是这样的:
function ArrayPush() { var n = TO_UINT32(this.length); // 被push对象的长度 var m = % _ArgumentsLength(); // push的参数个数 for (var i = 0; i < m; i++) { this[i + n] = % _Arguments(i); // 复制元素 } this.length = n + m; //修正length属性 return this.length; }
它只与this有关,所以只要是类数组对象,都可以调用相关方法去处理。
这部分内容比较复杂,再加上自己水平也不太够。所以推荐有条件的同学去购买相关书籍,或者等我的后续博客文章。
感想
通过对这部分的学习,算是加深了对JavaScript的理解。最直观的表现就是,去看一些优秀框架的源代码时,不再是被this,call,apply,bind绕的晕乎乎的。还是很开心的~
下一段时间,准备深入探索一下日常学习和使用的CSS。毕竟JavaScript学了,HTML和CSS也不能落下。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。