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 相关文章推荐
基于jQuery的投票系统显示结果插件
Aug 12 Javascript
用JavaScript实现动画效果的方法
Jul 20 Javascript
jQuery左侧大图右侧小图焦点图幻灯切换代码分享
Aug 19 Javascript
jQuery实现图像旋转动画效果
May 29 Javascript
JS实现鼠标框选效果完整实例
Jun 20 Javascript
概述如何实现一个简单的浏览器端js模块加载器
Dec 07 Javascript
Ext JS 实现建议词模糊动态搜索功能
May 13 Javascript
jQuery图片缩放插件smartZoom使用实例详解
Aug 25 jQuery
vue.js项目nginx部署教程
Apr 05 Javascript
编写更好的JavaScript条件式和匹配条件的技巧(小结)
Jun 27 Javascript
vue-cli配置flexible过程详解
Jul 04 Javascript
js找出5个数中最大的一个数和倒数第二大的数实现方法示例小结
Mar 04 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
并发下常见的加锁及锁的PHP具体实现代码
2010/10/12 PHP
JQuery this 和 $(this) 的区别
2009/08/23 Javascript
一个可以兼容IE FF的加为首页与加入收藏实现代码
2009/11/02 Javascript
Extjs学习笔记之八 继承和事件基础
2010/01/08 Javascript
js对图片base64编码字符串进行解码并输出图像示例
2014/03/17 Javascript
Javascript中的回调函数和匿名函数的回调示例介绍
2014/05/12 Javascript
Jquery仿IGoogle实现可拖动窗口示例代码
2014/08/22 Javascript
jquery实现表单验证并阻止非法提交
2015/07/09 Javascript
javascript中递归函数用法注意点
2015/07/30 Javascript
jQuery 如何给Carousel插件添加新的功能
2016/04/18 Javascript
异步加载JS、CSS代码(推荐)
2016/06/15 Javascript
vue.js指令v-model实现方法
2016/12/05 Javascript
极简主义法编写JavaScript类
2017/11/02 Javascript
nodejs中密码加密处理操作详解
2018/03/20 NodeJs
解决layer弹出层自适应页面大小的问题
2019/09/16 Javascript
详解微信小程序「渲染层网络层错误」的解决方法
2021/01/06 Javascript
[35:39]完美世界DOTA2联赛PWL S2 FTD.C vs Rebirth 第二场 11.22
2020/11/24 DOTA
Python内置数据类型详解
2014/08/18 Python
Python实现递归遍历文件夹并删除文件
2016/04/18 Python
python与sqlite3实现解密chrome cookie实例代码
2018/01/20 Python
基于python3 OpenCV3实现静态图片人脸识别
2018/05/25 Python
python 使用装饰器并记录log的示例代码
2019/07/12 Python
Python交互式图形编程的实现
2019/07/25 Python
python对Excel按条件进行内容补充(推荐)
2019/11/24 Python
Python如何实现后端自定义认证并实现多条件登陆
2020/06/22 Python
增大python字体的方法步骤
2020/07/05 Python
Python实现一个优先级队列的方法
2020/07/31 Python
HTML5边玩边学(2)基础绘图实现方法
2010/09/21 HTML / CSS
如何填写个人简历自我评价
2013/12/10 职场文书
财政局长自荐信范文
2013/12/22 职场文书
计算机专业毕业生自荐信
2013/12/31 职场文书
公司司机岗位职责范本
2014/03/03 职场文书
导师推荐信范文
2014/05/09 职场文书
小学生交通安全寄语
2015/02/27 职场文书
世界上超棒的8种逻辑思维
2019/08/06 职场文书
MySQL Router的安装部署
2021/04/24 MySQL