JavaScript call 与apply的用法(转)

一、方法的定义
call方法:
语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定义:调用一个对象的一个方法,以另一个对象替换当前对象。
说明:
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply方法:
语法:apply([thisObj[,argArray]])
定义:应用某一对象的一个方法,用另一个对象替换当前对象。
说明:
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。


实质:通过改变this指向,改变函数的调用对象。(this指向调用时才知道指向谁)

二、例子程序:
Java代码
1. <html>
2. <head>
3. <script language="javascript">
4. /**定义一个animal类*/
5. function Animal(){
6. this.name = "Animal";
7. this.showName = function(){
8. alert(this.name);
9. }
10. }
11. /**定义一个Cat类*/
12. function Cat(){
13. this.name = "Cat";
14. }
15.
16. /**创建两个类对象*/
17. var animal = new Animal();
18. var cat = new Cat();
19.
20. //通过call或apply方法,将原本属于Animal对象的showName()方法交给当前对象cat来使用了。
21. //输入结果为"Cat"
22. animal.showName.call(cat,",");
23. //animal.showName.apply(cat,[]);
24.
25.
26. </script>
27. </head>
28. <body></body>
29. </html>


以上代码无论是采用animal.showName.call或是animal.showName.apply方法,运行的结果都是输出一个"Cat"的字符串。说明showName方法的调用者被换成了cat对象,而不是最初定义它的animal了。这就是call和apply方法的妙用!

三、小结:
call和apply方法通常被用来实现类似继承一样的功能,以达到代码复用的功效。它们的区别主要体现在参数上。

。。。。。。。。。。。你所写的,只是call和apply最基本的作用。根本不是面向对象

你代码的修改版(一般情况已经够用)
Javascript代码
1. <html>
2. <head>
3. <script language="javascript">
4.
5. function Animal(name){
6. this.name = name;
7. this.showName = function(){
8. alert(this.name);
9. }
10. }
11.
12. function Cat(name){
13. Animal.call(this, name);
14. }
15.
16. var cat = new Cat("Black Cat");
17.
18. cat.showName();
19.
20.
21. </script>
22. </head>
23. <body></body>
24. </html>


更完全版
Javascript代码
1. <html>
2. <head>
3. <script language="javascript">
4.
5. function Animal(name){
6. this.name = name;
7. this.showName = function(){
8. alert(this.name);
9. }
10. }
11.
12. function Cat(name){
13. Animal.call(this, name);
14. }
15.
16. Cat.prototype = new Animal();
17.
18. var cat = new Cat("Black Cat");
19.
20. cat.showName();
21.
22. alert(cat instanceof Animal);
23.
24.
25. </script>
26. </head>
27. <body></body>
28. </html>


call和apply都是基于this替换。把this的语义转了

模拟call, apply的this替换
Javascript代码
1. function Animal(name){
2. this.name = name;
3. this.showName = function(){
4. alert(this.name);
5. };
6. };
7.
8. function Cat(name){
9. this.superClass = Animal;
10. this.superClass(name);
11. delete superClass;
12. }
13.
14. var cat = new Cat("Black Cat");
15.
16. cat.showName();


1. function Animal(name)
2. {
3. this.name = name;
4. }
5. function Dog(name)
6. {
7. this.name = name;
8. this.base = Animal;
9. this.base('animal');
10. }
11.
12. var d = new Dog('dog.chen');
13. window.alert(d.name);


为什么Dog传递的是'dog.chen',而结果居然是 'animal'?我想不明白
在 Dog的构造函数里面直接调用了 Animal的构造函数为什么会影响Dog的name的属性呢?

1. function Animal(name) {
2. this.name=name;
3. }
4.
5. funciton Dog(name) {
6. this.base=Animal
7. this.base(name); /*先执行父类的构造函数,此时父类构造函数中上下文的this,就是Dog构造函数中的上下文this*/
8. this.name=name //覆盖了父类中继承下来的this.name
9. }


1. function Animal(name){
2. this.name = name;
3. }
4. Animal.protptype.showName = function(){
5. alert(this.name);
6. }
7. function Dog(name,color){
8. Animal.call(this,name); //相当于 java的super();
9. this.color = color;
10. }
11. Dog.prototype = new Animal(); //继承父类的方法,书上说在这里调用无参数的构造函数是标准做法,但我不清楚为什么
12. Dog.prototype.showColor = function(){
13. alert(this.color);
14. }
15. var dog = new Dog('wangwang','white');
16. dog.showName(); //输出wangwang
17. dog.showColor(); //输出white


apply(),call()最常见的理解就是继承的概念,继承这个概念有点不好理解,我们可以从他的扩充函数作用域这个角度去理解:
《javascript高级程序设计》书上的例子:
window.color="red";
var o={color:"blue"};
function sayColor(){
alert(this.color);
}
sayColor();//red
sayColor().call(this);//red
sayColor.call(window);//red
sayColor.call(o);//blue

sayColor()是全局函数,
sayColor().call(this);//red
sayColor.call(window);//red
这两个是显式的在全局作用域中调用函数方式

运行sayColor.call(o);时,函数的执行环境就改变了,这是函数中的this指向了o作用域改变到o中了。

在这里,使用call(),apply()扩充作用域的最大好处在于,对象不需要和方法有任何耦合关系。

另外再次从扩充作用域的角度去回顾之前的一片文章(Javascript 中的 call 继承(转载整理))的例子:

function Person(name,age){
this.name = name;
this.age=age;
this.alertName = function(){
alert(this.name);
}
this.alertAge = function(){
alert(this.age);
}
}

function webDever(name,age,sex){
Person.call(this,name,age);//这里的Person作用域就变为了webDever里面的作用域了,Person原本的this指向的是全局,现在它的this指向webDever函数中,可以理解为webDever类就继承Person类,更加通俗的理解就是,Person函数可以在webDever的作用域中执行了
this.sex=sex;
this.alertSex = function(){
alert(this.sex);
}
}

var test= new webDever("愚人码头",28,"男");
test.alertName();//愚人码头
test.alertAge();//28
test.alertSex();//男
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值