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 相关文章推荐
鼠标图片振动代码
Jul 06 Javascript
InnerHtml和InnerText的区别分析
Mar 13 Javascript
在网页中使用document.write时遭遇的奇怪问题
Aug 24 Javascript
iframe里的页面禁止右键事件的方法
Jun 10 Javascript
JavaScript中的Reflect对象详解(ES6新特性)
Jul 22 Javascript
JS实现显示带倒影的图片横排居中放大展示特效实例【测试可用】
Aug 23 Javascript
JS基于面向对象实现的多个倒计时器功能示例
Feb 28 Javascript
如何写好你的JavaScript【推荐】
Mar 02 Javascript
微信小程序之数据双向绑定与数据操作
May 12 Javascript
AngularJS实现的JSONP跨域访问数据传输功能详解
Jul 20 Javascript
js实现掷骰子小游戏
Oct 24 Javascript
在vue中使用vant TreeSelect分类选择组件操作
Nov 02 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 数组动态添加实现代码(最土团购系统的价格排序)
2011/12/30 PHP
php中cookie实现二级域名可访问操作的方法
2014/11/11 PHP
php文件上传简单实现方法
2015/01/24 PHP
基于PHP实现的事件机制实例分析
2015/06/18 PHP
laravel5创建service provider和facade的方法详解
2016/07/26 PHP
php表单处理操作
2017/11/16 PHP
PHP Pipeline 实现中间件的示例代码
2020/04/26 PHP
基于jquery &amp; json的省市区联动代码
2012/06/26 Javascript
js实现在字符串中提取数字
2013/11/05 Javascript
js转化毫秒为时间格式代码
2014/04/10 Javascript
jquery实现select选中行、列合计示例
2014/04/25 Javascript
浅析Node.js中使用依赖注入的相关问题及解决方法
2015/06/24 Javascript
jQuery实现的点赞随机数字显示动画效果(附在线演示与demo源码下载)
2015/12/31 Javascript
JS实现自动阅读单词(有道单词本添加功能)
2016/11/14 Javascript
js实现移动端微信页面禁止字体放大
2017/02/16 Javascript
js获取json中key所对应的value值的简单方法
2020/06/17 Javascript
基于游标的分页接口实现代码示例
2018/11/12 Javascript
js实现京东秒杀倒计时功能
2019/01/21 Javascript
Vue.js下拉菜单组件使用方法详解
2019/10/19 Javascript
在vue中通过render函数给子组件设置ref操作
2020/11/17 Vue.js
python 字符串split的用法分享
2013/03/23 Python
基于windows下pip安装python模块时报错总结
2018/06/12 Python
mac PyCharm添加Python解释器及添加package路径的方法
2018/10/29 Python
对pandas写入读取h5文件的方法详解
2018/12/28 Python
python 切换root 执行命令的方法
2019/01/19 Python
PyQt5+Caffe+Opencv搭建人脸识别登录界面
2019/08/28 Python
python如何写try语句
2020/07/14 Python
HTML5网页音乐播放器的示例代码
2017/11/09 HTML / CSS
美国领先的精品家居照明和装饰产品在线零售商:LightsOnline.com
2018/01/23 全球购物
亚洲领先的设计购物网站:Pinkoi
2020/11/26 全球购物
班队活动设计方案
2014/01/30 职场文书
工作态度不端正检讨书
2014/10/04 职场文书
2015年幼儿园学期工作总结
2015/05/22 职场文书
学习经验交流会总结
2015/11/02 职场文书
《正比例》教学反思
2016/02/23 职场文书
Mysql中存储引擎的区别及比较
2021/06/04 MySQL