JavaScript中的this、call、apply

举报
yd_221104950 发表于 2020/12/05 00:01:57 2020/12/05
【摘要】 1、this JavaScript中的this,总是指向一个对象 ,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。 this的指向大致可以分以下4种: 作为对象的方法调用作为普通函数调用构造器调用Function.prototype.call或Function.prototype.apply调用 1、作为对象的方法调用 var...

1、this

JavaScript中的this,总是指向一个对象 ,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境
this的指向大致可以分以下4种:

  • 作为对象的方法调用
  • 作为普通函数调用
  • 构造器调用
  • Function.prototype.call或Function.prototype.apply调用

1、作为对象的方法调用

var obj =  { name:"Tome", getName:function(){ alert(this == obj); // true alert(this.name);  // Tome } };
obj.getName();


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

因为obj字面量对象调用了getiName()方法,所以this就代表了obj字面量对象。字面量对象一创建就在内存中有自己的空间。
2、作为普通函数调用
当函数不作为对象的属性被调用时,此时this总是指向全局对象。在浏览器的JavaScript中,这个全局对象就是window对象。

var name = "globalName";
var getName = function(){ return this.name;
};
alert(getName());

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

window.name = "globalNameA";
var getName = function(){ return this.name;
};
alert(getName());

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

window.name = "globalNameB";
var myObject = { name:"Jhony", getName:function(){ return this.name; } }
var getName = myObject.getName;
alert(getName()); // globalNameB
alert(myObject.getName()); // Jhony

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

var getName = myObject.getName这一句只是把myObject字面的对象方法借来用。而里面用到的this是根据具体的运行环境来绑定的,所以当在myObject字面量对象外且不作为myObject的属性来调用getName方法时,this指向全局对象。当作为myObject对象的属性来调用时,即myObject.getName()调用时,this又指向字面量对象myObject。
注意:有个很趣的现象

window.id = "window";
document.getElementById("root").onclick = function(){ alert(this.id); // root var callback = function(){ alert(this.id); }; callback(); // window
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

此时callback里的this是指向了全局对象window而不是id为root的元素对象,为什么会这样呢,因为callback方法前面没有指明调用对象,callback方法不是作为id为root元素对象的属性来调用的,所以this默认指向全局对象。如果你要callback方法里的this指向id为root元素,怎么办?可以通过call或apply方法,重新指定this的指向,如:

 window.id = "window"; document.getElementById("root").onclick = function(){ alert(this.id); // root var callback = function(){ alert(this.id); }; callback.call(document.getElementById("root")); // root callback.apply(document.getElementById("root")); // root }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3、构造器调用
JavaScript中没有类,但是可以从构造器中创建对象,同时也提供了new运算符,但他们只是用来申请一个内存空间,然后通过这个构造器方法来对这个空间进行赋值。

var MyClass = function(name){ this.name = name; } function MyClass1(name){ this.name = name; } var myClass = new MyClass("Tome"); alert(myClass.name) var myClass1 = new MyClass1("Haha"); alert(myClass1.name)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

构造器会帮我们申请内存空间后,然后把这个对象隐式地返回来,再用构造器方法对其进行赋值。不要在构造器中显示return返回其他东西,否则将会取代之前申请好的对象。前面的功夫就白做了,如:

var MyClass = function(name){ this.name = name; return { name:"Jeety" } }
var myClass = new MyClass("Tome");
alert(myClass.name) // Jeety

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

上面这个反例里做事就是一开始去申请了内存空间,然后用构造器函数对内存空间进行了赋值,让内存有了一个name值为Tome,结果在最后又去创建了一个字面量对象,在内存另开一个空间,把name赋值了Jeety,最后把前面那个抛弃了,返回这个字面量对象。不要这样做, 我真想说,这是吃饱了撑的吗?

4、Function.prototype.call或Function.prototype.apply调用

 window.id = "window"; document.getElementById("root").onclick = function(){ alert(this.id); // root var callback = function(){ alert(this.id); }; callback(); callback.call(document.getElementById("root")); // root callback.apply(document.getElementById("root")); // root }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

上面的callback函数里的this是指向了全局对象window而不是id为root的元素对象,为什么会这样呢,因为当函数不作为对象的属性被调用时,此时this总是指向全局对象。而callback方法前面没有指明调用对象,即没有作为id为root的元素对象的属性来调用,所以this指向全局对象。如果你要callback方法里的this指向id为root元素,怎么办?可以通过call或apply方法,重新指定this的指向,如上所示。

谢谢阅读!

文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_40763897/article/details/90710950

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。