js的call()的this指向的一些诱惑!

ruishq 2011-12-10 12:47:53
今天看重看jquery源码时候,想到一个关于js里面call()问题。

网络上常用的解释call的代码如下:

function Animal(){
this.name = "Animal";
this.showName = function(){
alert(this.name);
}
}
/**定义一个Cat类*/
function Cat(){
this.name = "Cat";
}

/**创建两个类对象*/
var animal = new Animal();
var cat = new Cat();

//通过call或apply方法,将原本属于Animal对象的showName()方法交给当前对象cat来使用了。
//输入结果为"Cat"
animal.showName.call(cat,",");
//animal.showName.apply(cat,[]);

这样的代码和我以前一直的理解也都是一样的。我以前一直这样理解call或者apply的方法

animal.showName.call(cat,",");

其实也就是将showName里面的this本来是指向animal,call调用后this指向cat。
这样理解,也就能解释了。


但是今天搜索资料时候看到别人另外一段demo:

function add(a,b)
{
alert(a+b);
}
function sub(a,b)
{
alert(a-b);
}
add.call(sub,3,1); //4

为了理解上面这个demo我重新修改了一些:

var test = 111;
function _add()
{
// this.test = 444; //注释①
alert(this.test);
}
function _sub()
{
this.test = 222;
alert(this.test);
}
_add();
_sub();
_add.call(_sub); //未去掉注释①:undefined 去掉:444
var d = new _add();//结果等同于_add.call(_sub);

那我就不明白了啊。
1.
_add.call(_sub)
_add.call(_sub) = window._add.call(_sub),this开始是指向window的,call掉用后为什么就又指向哪里去了呢?
2.
_add.call(new _sub())如果这样写得话呢,那很明显结果this是指向 _sub的对象的,
但是,我们又常说JS里面的方法(function)也是对象,那么是不是说
_add.call(_sub) 等于如下代码:

var _sub = new function (){
this.test = 222;
alert(this.test);
}
_add.call(_sub)//222

3.那为什么以上1和2的返回值是不一样的呢?一个是undefined,一个是222


PS:现在是感觉就差那么一点点就懂了。但是就是一想多了深了就又糊涂了,求大神指点啊。
...全文
590 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
likeajin 2011-12-10
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 ruishq 的回复:]

_add.call(_sub);//_add中this指向_sub,_sub无test属性,undefined
如果this指向_的话sub,为什么//this.test = 444; //注释① 这个注释去掉,_add.call(_sub);会弹出444呢?
引用 2 楼 likeajin 的回复:

没注释 第一个注释
JScript code

var test = 111……
[/Quote]

var test = 111;
function _add()
{
this.test = 444; //注释①
this();
alert(this.test);
}
function _sub()
{
this.test = 222;
alert(this.test);
}
_add.call(_sub);
/*
_add.call(_sub)的执行效果:执行_add函数,函数体中的this指向_sub,_sub是个函数对象,它也有它的属性
结果:
_add.call(_sub);
function _add()
{
alert(window.test);//弹出111,与alert(test)一样
this.test = 444; //注释① this指向_sub,为_sub添加了一个test属性,值为444
this();//this指向_sub,执行_sub方法,在_sub方法中,_sub中的this指向window
alert(window.test);//上一句的效果,与alert(test)一样
alert(this.test); //上一句代码为_sub添加test属性,这里等价于alert(_sub.test);弹出444
}
*/

注意,在_add中有一句this();假使call的时候调用的不是一个函数对象将出错
ruishq 2011-12-10
  • 打赏
  • 举报
回复
啊哦。是我钻牛角尖了。应该是明白了。
ruishq 2011-12-10
  • 打赏
  • 举报
回复
_add.call(_sub);//_add中this指向_sub,_sub无test属性,undefined
如果this指向_的话sub,为什么//this.test = 444; //注释① 这个注释去掉,_add.call(_sub);会弹出444呢?
[Quote=引用 2 楼 likeajin 的回复:]

没注释 第一个注释
JScript code

var test = 111;
function _add()
{
this.test = 444; //注释①
alert(this.test);
}
function _sub()
{
this.test = 222;
alert(this.test);
}
_add();//弹……
[/Quote]
likeajin 2011-12-10
  • 打赏
  • 举报
回复
没注释 第一个注释

var test = 111;
function _add()
{
this.test = 444; //注释①
alert(this.test);
}
function _sub()
{
this.test = 222;
alert(this.test);
}
_add();//弹出444
_sub();//弹出222
_add.call(_sub);
/*
_add.call(_sub)的执行效果:执行_add函数,函数体中的this指向_sub
结果:
1.函数_sub有一个test属性,即_sub.test=444;
2._add中alert(this.test)中的this指向_sub,弹出444
*/
alert(_sub.test);

注释第一个注释后

var test = 111;
function _add()
{
//this.test = 444; //注释①
alert(this.test);
}
function _sub()
{
this.test = 222;
alert(this.test);
}
_add();//弹出111,_add中this指向window
var d=new _sub();//_sub中this指向d
alert(test);//弹出111 !!!!!!!!
_sub();//弹出222,_sub中的this继续指向window
alert(test);//执行_sub()的结果!!!!!!!!
_add.call(_sub);//_add中this指向_sub,_sub无test属性,undefined

注意打了感叹号的两个弹出
likeajin 2011-12-10
  • 打赏
  • 举报
回复

var f1=function(){this.a='类f1的实例的a属性'};
f1.a='对象f1的a属性';
var f2=function(){};//类f2的实例没有a属性
f2.a='对象f2的a属性';
var test=function(){alert(this.a)};
test.call(f1);//弹出'对象f1的a属性'
test.call(new f1());//弹出'类f1的实例的a属性'
test.call(f2);//弹出'对象f2的a属性'
test.call(new f2());//弹出undefined

解释:call和apply函数只是单纯地把调用的方法中的this指向了第一个参数,从第二个参数开始为传递到调用方法的参数

test.call(f1);//==>test=function(){alert(this.a);}this指向对象f1
test.call(new f1());//==>test=function(){alert(this.a);}this指向类f1的实例

87,916

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧