关闭

js中call与apply用法

标签: chromeclassClassfunctioninputprototype
36242人阅读 评论(7) 收藏 举报
分类:

前天去面试,有个gg问了一些js知识,其中有一道call与apply用法的题目,尽管在365天前用过call方法,但当时还是没能答上来,今天深入总结一下


call和apply,它们的作用都是将函数绑定到另外一个对象上去运行

两者的格式和参数定义:

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

apply(thisArg [,argArray] );                 // 参数数组,argArray

上面两个函数内部的this指针,都会被赋值为thisArg,这可实现将函数作为另外一个对象的方法运行的目的


一、call 的简单用法

首先,我们先看个简单的例子(call):

<!doctype html>

<html>
	<head>
		<title> call-apply </title>
	</head>

	<body>
		<input type="text" id="idTxt" value="input text">
		
		<script type="text/javascript">
			var value = "global var";
			
			function mFunc()
			{
				this.value = "member var";
			}
			
			function gFunc()
			{
				alert(this.value);
			}		
													
			window.gFunc();									// show gFunc, global var
			gFunc.call(window);								// show gFunc, global var
			gFunc.call(new mFunc());						// show mFunc, member var
			gFunc.call(document.getElementById('idTxt'));	// show element, input text
		</script>
		
		<script language="javascript">
			var func = new function()
			{
				this.a = "func";
			}
			
			var func2 = function(x)
			{
				var a = "func2";
				alert(this.a);				
				alert(x);
			}
			
			func2.call(func, "func2");						// show func and func2
		</script>
	</body>
</html>

然后,运行结果如下:

global var
global var
member var
input text
func
func2

测试环境:Google Chrome 10.0.648.45

最后,分析结果

1、全局对象window调用函数gFunc,this指向window对象,因此this.value为global var

2、函数gFunc调用call方法,this默认指向第一个参数window对象,因此this.value也为global var

3、函数gFunc调用call方法,this默认指向第一个参数new mFunc(),即mFunc的对象,因此this.value为mFunc的成员变量member var

4、函数gFunc调用call方法,this默认指向第一个参数input text控件,即id=‘idTxt’的控件,因此this.value为input控件的value值input text

5、函数func2调用call方法,this默认指向第一个参数func函数对象,因此this.value为this.a,即func

6、函数func2调用call方法,第二个参数属于函数对象func2的参数,因此alert(x)为第二个参数func2


二、call 继承用法与改进

js使用call模拟继承

测试代码:

<!doctype html>

<html>
	<head>
		<title> call - apply for inherit </title>
	</head>
	
	<body>
		<script type="text/javascript">
			function baseA()		// base Class A
			{
				this.member = "baseA member";
				this.showSelfA = function()
				{
					window.alert(this.member);
				}
			}
			
			function baseB()		// base Class B
			{
				this.member = "baseB member";
				this.showSelfB = function()
				{
					window.alert(this.member);
				}
			}
			
			function extendAB()		// Inherit Class from A and B
			{
				baseA.call(this);	// call for A
				baseB.call(this);	// call for B
			}
			
			window.onload = function()
			{
				var extend = new extendAB();	
				extend.showSelfA();		// show A
				extend.showSelfB();		// show B
			}
		</script>
	</body>
</html>
运行结果如下:

baseB member

baseB member

测试环境:Google Chrome 10.0.648.45

结果分析:

预期的结果,应该是输出 baseA member 和 baseB member,但实际输出却是 baseB member 和 baseB member

(已在IE9、8、6,Maxthon、Chrome、FF、Opera、Safari、360等浏览器测试过,结果都是后者:baseB member)

至此,机器是不会错的,这就需要我们深入分析

我们可能会很容易想到是this引起的,this两次都指向了baseB对象,但是推测真是这样吗?

为了探究实质,我们借助chrome浏览器的调试工具,下断点,进行调试,结果发现:


当调用extend.showSelfA();时,此时的this指向extendAB(并不是我们推测的两次都指向baseB对象

真实原因是extendAB对象的成员变量member在被baseB.call(this);实例化时,被baseB的成员member覆盖了,即extendAB的成员member由baseA member赋值成了baseB member

当然,我们也可以对上面baseA代码稍作修改,来验证我们调试分析的正确性:

function baseA() // base Class A
{
this.memberA = "baseA member";   // member改成memberA,以区分baseB中的member
this.showSelfA = function()
{
window.alert(this.memberA);    // 显示memberA
}
}

再次运行chrome等浏览器,结果如下:

baseA  member

baseB member

结果和我们的预期相同,同时chrome调试信息也验证了我们的正确性:




继承改进(prototype)

以上模拟继承方法,仔细分析不是最好的。

因为每次在函数(类)中定义了成员方法,都会导致实例有副本,因此可以借助prototype原型,进行改进

改进举例如下:

<!doctype html>

<html>
	<head>
		<title> call - apply for prototype </title>
	</head>
	
	<body>
		<script type="text/javascript">
			var Class = {
				create: function()				// create Function
				{
					return function()
					{
						this.initialize.apply(this, arguments);
					}
				}
			};
			
			var Person = Class.create();		// Create Class Person
			Person.prototype = {				// prototype initialize
				initialize: function(obj1, obj2)
				{
					this.obj1 = obj1;
					this.obj2 = obj2;
				},
				showSelf: function()
				{
					alert("obj: " + this.obj1 + " and " + this.obj2);
				}
			}
			
			// instance Class
			var person = new Person("man", "women");	// two params
			person.showSelf();							// show person
		</script>
	</body>
</html>
运行结果如下:
obj: man and women



20
0
查看评论

JS中的call()方法和apply()方法用法总结

JacvaScript中的call()方法和apply()方法, 1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法。 2. 相同点:这两个方法的作用是一样的。都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。
  • ganyingxie123456
  • ganyingxie123456
  • 2017-04-27 15:14
  • 12086

Js中的call方法

道听途说,一直以为Js是很弱智的,于是就没有学,直接进项目
  • whitewolf123
  • whitewolf123
  • 2014-06-10 17:29
  • 8041

JS的call方法的作用解释,简单易懂

先看看关于call()的官方解释,“调用一个对象的一个方法,以另一个对象替换当前对象。”,看了这样的解释,或许让你更摸不着头脑了。看例子: var x = "我是全局变量";    //定义全局变量x function a(){         //定义函数类结构a  ...
  • ywl570717586
  • ywl570717586
  • 2016-09-27 15:49
  • 5550

js中call和apply(函数的上下文调用模式)详解

上下文调用综述:     //上下文模式:根据用户传递的参数,指定了函数内部不同的this的值     //核心:以call/apply方法来调用某个函数     //call/apply方法定义在哪里?Funct...
  • ITzhongzi
  • ITzhongzi
  • 2017-03-09 09:11
  • 853

js的call() ,apply() 两种方法的区别和用法,最白话文的解释,让枯燥滚粗!

背景:今天群里有 妹子(我就不指名道姓喽)说:百度了一圈calll()函数和apply()函数,感觉还是糊里糊涂然后群里热闹了,各种表情包,各种殷勤,你懂的!正好我前几天刚又重新翻了一遍 那本 600多页 的圣经书,我习惯时不时的去打下基础,只是为了用来装逼,给人讲解。。。。(我是有多蛋疼)!好了下...
  • xllily_11
  • xllily_11
  • 2016-05-23 13:17
  • 6770

JS中call、apply、bind大概区别

为什么需要这些?主要是因为this,来看看this干的好事。box.onclick = function(){   function fn(){     alert(this);   }   fn(); };我们原本以为这里面的this指向的是box,然而却是Window。一般我们这样解决:box....
  • lizeshi125
  • lizeshi125
  • 2016-12-15 14:53
  • 2529

Js apply 方法 详解

Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里我做如下笔记,希望和大家分享..  如有什么不对的或者说法不明确的地方希望读者多多提一些...
  • qianzai5765638
  • qianzai5765638
  • 2011-11-09 14:24
  • 69957

JavaScript 中的 this 用法以及 call(apply) 的理解

想要深入了解 JavaScript 这门语言,一个必须掌握的知识点就是对 `this` 的理解。其中, `call` 和 `apply` 又与 `this` 有着密切的联系。趁现在有空,在网上看了一些教程之后,自己根据印象将其整理在这篇博文中。 this 是什么 this 是 ...
  • gertYY
  • gertYY
  • 2017-02-13 13:53
  • 2264

Js中call和apply的区别和用法

JavaScript中有一个call和apply方法,其作用基本相同,但也有略微的区别。 先来看看JS手册中对call的解释: call 方法 调用一个对象的一个方法,以另一个对象替换当前对象。 call([thisObj[,arg1[, arg2[,  ...
  • fanyuna
  • fanyuna
  • 2012-09-26 14:54
  • 18386

js中的call()和apply()方法

1.call() 语法:obj1.call(obj2[,param1,param2,...]) 定义:用obj2对象来代替obj1,调用obj1的方法。即将obj1应用到obj2上。 说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改...
  • mafan121
  • mafan121
  • 2016-10-25 15:15
  • 1675
    个人资料
    • 访问:12258919次
    • 积分:90823
    • 等级:
    • 排名:第16名
    • 原创:719篇
    • 转载:169篇
    • 译文:16篇
    • 评论:3070条
    学习经历
    中科院、百度、创新工场、小米、阿里巴巴、米扑科技

    期货从业资格证(2017.03)
    基金从业资格证(2016.11)
    证券投资顾问证(2016.9)
    证券从业资格证(2016.6)
    系统架构设计师(2013)
    软件设计师(2008)
    CSDN创业专访

    程序员创业邦
    QQ群: 239292073
    青春,每一个有梦想的人

    资深产品经理人
    QQ群: 338142405
    思与行,人人都是产品经理

    爱脚本,爱技术
    QQ群: 320296250
    (已满)
    python、ruby、php、go、shell

    程序人生的平凡生活
    QQ群: 282297696
    (已满)
    汇聚百度、小米、微软、腾讯、
    创新工场、阿里巴巴、日本雅虎
    个人博客
    博客专栏
    博客公告
    本博客内容,由米扑博客精心整理
    欢迎交流,欢迎转载,大家转载注明出处,禁止用于商业目的。

    文章分类
    文章存档