Javascript中this关键字指向问题的测试与详解


Posted in Javascript onAugust 11, 2017

前言

Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象。Javascript可以通过一定的设计模式来实现面向对象的编程,其中this “指针”就是实现面向对象的一个很重要的特性。本文将给大家详细介绍关于Javascript中this关键字指向的相关内容,让我们先做一个小测试,如果全部答对了,恭喜你不用往下看了。

测试题目

第一题

<script>
 var str = 'zhangsan';

 function demo() {
  var str = 'lisi';
  alert(this.str);
 }
 window.demo(); // ??

 var obj = {
  str: "wangwu",
  say: function() {
   alert(this.str);
  }
 }
 obj.say(); // ??

 var fun = obj.say;
 window.fun(); // ??
</script>

第二题

<script>
 var username = 'zhangsan';

 (function() {
  var username = 'lisi';
  alert(this.username); // ??
 })()

 function demo() {
  var username = 'wangwu';

  function test() {
   alert(this.username);
  }

  test(); // ??
 }
 demo();
</script>

第三题

<script>
 function Person() {
  this.username = 'zhangsan';
  this.say = function() {
   alert('我叫' + this.username);
  }
 }

 var p = new Person();
 p.say(); // ??

 var p1 = new Person();
 p1.say(); // ??
</script>

第四题

<script>
 var username = 'zhangsan';

 function demo() {
  alert(this.username)
 }

 var obj1 = {
  username: "lisi"
 };
 var obj2 = {
  username: "wangwu"
 };

 demo(); // ??
 demo(obj1); // ??
 demo(obj2); // ??
 demo.call(obj1); // ?? 
 demo.apply(obj2); // ??
</script>

答案

  • 第一题:zhangsan wangwu zhangsan
  • 第二题:zhangsan zhangsan
  • 第三题:我叫zhangsan 我叫zhangsan
  • 第四题:zhangsan zhangsan zhangsan lisi wangwu

(往下看,下面有详细解析哦)

this

  • 指向调用函数的对象
  • 无对象调用函数/匿名函数自调用(this指向window)
  • 通过new产生的对象
  • apply/call调用

一、指向调用函数的对象

<script>
 // this:指向调用函数的对象
 var str = 'zhangsan';

 function demo() {
  var str = 'lisi';

  //this->window
  console.log(this);
  alert(this.str);
 }
 window.demo(); // zhangsan

 var obj = {
  str: "wangwu",
  say: function() {
   // this->obj
   alert(this.str);
  }
 }
 obj.say(); // wangwu

 var fun = obj.say;
 window.fun(); // zhangsan
</script>
  • 全局函数(demo)属于window对象的方法,window调用demo所以this就指向了window
  • obj调用say方法,this就指向了obj
  • fun()是全局函数,而声明的fun接收的是obj里面单纯的一个函数,并没有调用(obj.say()才是调用了函数),此时的fun就是一个函数(function(){alert(this.str);}),那么当fun()调用函数的时候,this指向的就是window
  • 是谁调用的函数,那么this就指向谁

二、无对象调用函数/匿名函数自调用->this指向window

<script>
 // 2.匿名函数自执行|匿名函数|无主函数 this->window
 var username = 'zhangsan';

 // 匿名函数自执行 this->window
 (function() {
  var username = 'lisi';
  console.log(this); // window
  alert(this.username); // zhangsan
 })()

 function demo() {
  var username = 'wangwu';

  // 无主函数 this->window
  function test() {
   // this->window
   alert(this.username);
  }

  test(); // zhangsan
 }
 demo();
</script>
  • 因为匿名函数没有名字,所以就挂给window了
  • test(),谁调用test那么就指向谁。当然实验过,它不是window调用的,也不是demo调用的,没有人管它,那么它就指向window。它就相当于一个没有主人调用它,无主函数。

三、通过new产生的对象

<script>
 // 3.通过new的对象:this指向产生的对象
 // 函数
 function Person() {
  // 属性
  this.username = 'zhangsan';
  // 方法
  this.say = function() {
   // this->p
   console.log(this); // Person对象
   alert('我叫' + this.username);
  }
 }

 // 实例化出一个对象:p就具有了username属性和say方法
 var p = new Person();
 console.log(p); // Person对象
 console.log(p.username); // zhangsan
 p.say(); // 我叫zhangsan

 // this->p1
 var p1 = new Person();
 p1.say(); // Person对象 我叫zhangsan
</script>
  • 当我们的函数Person里面运用了this去写属性和方法这种格式,那么就要通过new来让属性和方法变得有价值,通过new去运用函数里面的属性和方法

四、apply/call调用

首先我们来了解下apply()/call()是个什么东西呢?

apply()/call():最终是调用function,只不过内部的this指向了thisObj

function.call([thisObj[,arg1[, arg2[, [,.argN]]]]])
function.apply([thisObj[,argArray]])

注意:

1. 调用function函数,但是函数内的this指向thisObj(更改对象内部指针)

2. 如果thisObj没有传参,则默认为全局对象

3. call()/apply()联系与区别

    联系:功能一样,第一个参数都是thisObj

    区别:传递的参数如果比较多

        call()的实参就是一一列出

        apply()的实参是全部放置在第二个数组参数中

一个理解apply()/call()的实例:

<script>
 // apply()/call()
 function demo() {
  console.log(123);
 }

 // 调用函数的时候,demo.call()/demo.apply()最终调用的还是demo()
 demo(); // 123
 demo.call(); //123
 demo.apply(); // 123
</script>

<script>
 // call()/apply()的区别:
 // call()参数单独再call中罗列
 // apply()的参数通过数组表示
 function demo(m, n, a, b) {
  alert(m + n + a + b);
 }
 demo(1, 5, 3, 4); // 13
 demo.call(null, 1, 5, 3, 4); // 13
 demo.apply(null, [1, 5, 3, 4]); // 13
</script>

this的第四个用法实例

<script>
 // this的第四个用法:call(obj)/apply(obj):强制性的将this指向了obj
 var username = 'zhangsan';

 function demo() {
  alert(this.username)
 }

 var obj1 = {
  username: "lisi"
 };
 var obj2 = {
  username: "wangwu"
 };

 // call()/apply():打劫式的改变了this的指向
 demo(); // zhangsan
 demo(obj1); //zhangsan
 demo(obj2); //zhangsan
 demo.call(obj1); // lisi 
 demo.apply(obj2); // wangwu
</script>
  • 如果直接调用demo里面写的不管是obj1还是obj2,那么demo还是属于window调用的。
  • 不管你用call还是apply最终调用的都是demo函数,但它们会强制的this指向了obj1/obj2,强制的指向了它们的第一个参数对象。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
详解Webwork中Action 调用的方法
Feb 02 Javascript
AngularJS ng-bind-html 指令详解及实例代码
Jul 30 Javascript
利用angular.copy取消变量的双向绑定与解析
Nov 25 Javascript
js实现时间轴自动排列效果
Mar 09 Javascript
bootstrap3使用bootstrap datetimepicker日期插件
May 24 Javascript
React Native中NavigatorIOS组件的简单使用详解
Jan 27 Javascript
jQuery利用cookie 实现本地收藏功能(不重复无需多次命名)
Nov 07 jQuery
通过js实现压缩图片上传功能
Feb 25 Javascript
js实现数字跳动到指定数字
Aug 25 Javascript
JavaScript 与 TypeScript之间的联系
Nov 27 Javascript
Vue自定义铃声提示音组件的实现
Jan 22 Vue.js
使用Ajax实现无刷新上传文件
Apr 12 Javascript
使用JS编写的随机抽取号码的小程序
Aug 11 #Javascript
javascript简写常用的12个技巧(可以大大减少你的js代码量)
Mar 28 #Javascript
Mobile Web开发基础之四--处理手机设备的横竖屏问题
Aug 11 #Javascript
Vue.js仿微信聊天窗口展示组件功能
Aug 11 #Javascript
Node.js服务器开启Gzip压缩教程
Aug 11 #Javascript
JS SetInterval 代码实现页面轮询
Aug 11 #Javascript
IScroll5实现下拉刷新上拉加载的功能实例
Aug 11 #Javascript
You might like
10个值得深思的PHP面试题
2016/11/14 PHP
Laravel框架路由管理简单示例
2019/05/07 PHP
laravel5.6实现数值转换
2019/10/23 PHP
jquery 笔记 事件
2011/11/02 Javascript
jQuery版仿Path菜单效果
2011/12/15 Javascript
Node.js开发指南中的简单实例(mysql版)
2013/09/17 Javascript
一个CSS+jQuery实现的放大缩小动画效果
2014/02/19 Javascript
nodejs的10个性能优化技巧
2014/07/15 NodeJs
js网页右下角提示框实例
2014/10/14 Javascript
js随机生成网页背景颜色的方法
2015/02/26 Javascript
jQuery实现鼠标悬停显示提示信息窗口的方法
2015/04/30 Javascript
js基于cookie记录来宾姓名的方法
2016/07/19 Javascript
AngularJS ng-mousedown 指令
2016/08/02 Javascript
基于JavaScript实现在新的tab页打开url
2016/08/04 Javascript
JS实现HTML标签转义及反转义
2020/04/14 Javascript
JS Array.from()将伪数组转换成数组的方法示例
2020/03/23 Javascript
Vue实现附件上传功能
2020/05/28 Javascript
在vue中嵌入外部网站的实现
2020/11/13 Javascript
[01:54]TI珍贵瞬间系列(三):翻盘
2020/08/28 DOTA
python操作摄像头截图实现远程监控的例子
2014/03/25 Python
python实现简单的TCP代理服务器
2014/10/08 Python
Python的Flask框架中的Jinja2模板引擎学习教程
2016/06/30 Python
Python字典操作详细介绍及字典内建方法分享
2018/01/04 Python
numpy.random.seed()的使用实例解析
2018/02/03 Python
python计算两个地址之间的距离方法
2018/06/09 Python
Python3列表内置方法大全及示例代码小结
2019/05/10 Python
python scipy卷积运算的实现方法
2019/09/16 Python
python编写微信公众号首图思路详解
2019/12/13 Python
英国口碑最好的的维他命胶囊品牌:Myvitamins(有中文站)
2016/12/03 全球购物
Needle & Thread官网:英国仙女品牌
2018/01/13 全球购物
台湾7-ELEVEN线上购物中心:7-11
2021/01/21 全球购物
Kendra Scott官网:美国领先的时尚配饰品牌
2020/10/22 全球购物
公务员保密承诺书
2014/03/27 职场文书
个人求职意向书
2015/05/11 职场文书
新手初学Java网络编程
2021/07/07 Java/Android
十大最强火系宝可梦,喷火龙上榜,第一名有双火属性
2022/03/18 日漫