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入门—访问DOM对象方法
Jan 07 Javascript
js中的cookie的读写操作示例详解
Apr 17 Javascript
json属性名为什么要双引号(个人猜测)
Jul 31 Javascript
基于Bootstrap的Metronic框架实现条码和二维码的生成及打印处理操作
Aug 29 Javascript
从零开始学习Node.js系列教程四:多页面实现数学运算的client端和server端示例
Apr 13 Javascript
利用javascript如何随机生成一定位数的密码
Sep 22 Javascript
Angular5.0 子组件通过service传递值给父组件的方法
Jul 13 Javascript
深入理解移动前端开发之viewport
Oct 19 Javascript
JS实现鼠标拖拽盒子移动及右键点击盒子消失效果示例
Jan 29 Javascript
js实现多张图片每隔一秒切换一张图片
Jul 29 Javascript
实例讲解React 组件
Jul 07 Javascript
Canvas三种动态画圆实现方法说明(小结)
Apr 16 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
Laravel 5框架学习之路由、控制器和视图简介
2015/04/07 PHP
2017年最新PHP经典面试题目汇总(上篇)
2017/03/17 PHP
Laravel中七个非常有用但很少人知道的Carbon方法
2017/09/21 PHP
你必须知道的Javascript知识点之&quot;深入理解作用域链&quot;的介绍
2013/04/23 Javascript
nodejs 提示‘xxx’ 不是内部或外部命令解决方法
2014/11/20 NodeJs
js脚本实现数据去重
2014/11/27 Javascript
JavaScript随机生成信用卡卡号的方法
2015/04/07 Javascript
JavaScript中的lastIndexOf()方法使用详解
2015/06/06 Javascript
JavaScript实现标题栏文字轮播效果代码
2015/10/24 Javascript
jQuery实现三级菜单的代码
2016/05/09 Javascript
AngularJS路由实现页面跳转实例
2017/03/03 Javascript
Bootstrap超大屏幕的实现代码
2017/03/22 Javascript
使用 Vue.js 仿百度搜索框的实例代码
2017/05/09 Javascript
vue.js实例todoList项目
2017/07/07 Javascript
extjs简介_动力节点Java学院整理
2017/07/17 Javascript
React Form组件的实现封装杂谈
2018/05/07 Javascript
vue中锚点的三种方法
2018/07/06 Javascript
pyside写ui界面入门示例
2014/01/22 Python
Python中特殊函数集锦
2015/07/27 Python
回调函数的意义以及python实现实例
2017/06/20 Python
如何在python中使用selenium的示例
2017/12/26 Python
python3+requests接口自动化session操作方法
2018/10/13 Python
python实现公司年会抽奖程序
2019/01/22 Python
python儿童学游戏编程知识点总结
2019/06/03 Python
PyQt5实现QLineEdit添加clicked信号的方法
2019/06/25 Python
Python3 翻转二叉树的实现
2019/09/30 Python
解决Pycharm中恢复被exclude的项目问题(pycharm source root)
2020/02/14 Python
python中的split、rsplit、splitlines用法说明
2020/10/23 Python
浅谈HTML5 FileReader分布读取文件以及其方法简介
2017/11/09 HTML / CSS
亚马逊中国官方网站:amazon.cn
2017/05/25 全球购物
小学庆六一活动方案
2014/02/28 职场文书
药剂专业求职信
2014/06/20 职场文书
个人事迹材料范文
2014/12/29 职场文书
2015年学生会主席工作总结
2015/04/21 职场文书
比赛主持人开场白
2015/05/29 职场文书
Python获取字典中某个key的value
2022/04/13 Python