js中call与apply的用法小结
js中call与apply的用法小结
发布时间:2016-12-30 来源:查字典编辑
摘要:前天去面试,有个gg问了一些js知识,其中有一道call与apply用法的题目,尽管在365天前用过call方法,但当时还是没能答上来,今天...

前天去面试,有个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 Chrome10.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 Chrome10.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浏览器的调试工具,下断点,进行调试,结果发现:

js中call与apply的用法小结1

当调用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调试信息也验证了我们的正确性:

js中call与apply的用法小结2

继承改进(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

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新Javascript教程学习
热门Javascript教程学习
编程开发子分类