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 相关文章推荐
SyntaxHighlighter语法高亮插件使用说明
Aug 14 Javascript
Jquery使用Firefox FireBug插件调试Ajax步骤讲解
Dec 02 Javascript
JQuery Tips相关(1)----关于$.Ready()
Aug 14 Javascript
JavaScript中的操作符==与===介绍
Dec 31 Javascript
JavaScript电子时钟倒计时第二款
Jan 10 Javascript
js判断手机系统是android还是ios
Mar 07 Javascript
node-sass安装失败的原因与解决方法
Sep 04 Javascript
使用socket.io实现简单聊天室案例
Jan 02 Javascript
JS如何操作DOM基于表格动态展示数据
Oct 15 Javascript
JS如何使用剪贴板操作Clipboard API
May 17 Javascript
uniapp引入支付宝原生扫码插件步骤详解
Jul 23 Javascript
JS前端使用canvas实现物体的点选示例
Aug 05 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
解析thinkphp的左右值无限分类
2013/06/20 PHP
解析yahoo邮件用phpmailer发送的实例
2013/06/24 PHP
php基于mcrypt的加密解密实例
2014/10/27 PHP
PHP模板引擎Smarty内建函数foreach,foreachelse用法分析
2016/04/11 PHP
php使用curl_init()和curl_multi_init()多线程的速度比较详解
2018/08/15 PHP
laravel-admin解决表单select联动时,编辑默认没选上的问题
2019/09/30 PHP
PHP函数用法详解【初始化、嵌套、内置函数等】
2020/06/02 PHP
Javascript中的var_dump函数实现代码
2009/09/07 Javascript
基于jQuery UI CSS Framework开发Widget的经验
2010/08/21 Javascript
Jquery阻止事件冒泡 event.stopPropagation
2011/12/11 Javascript
js使用函数绑定技术改变事件处理程序的作用域
2011/12/26 Javascript
JavaScript词法作用域与调用对象深入理解
2012/11/29 Javascript
jquery在Chrome下获取图片的长宽问题解决
2013/03/20 Javascript
教你如何终止JQUERY的$.AJAX请求
2016/02/23 Javascript
JavaScript获取css行间样式,内连样式和外链样式的简单方法
2016/07/18 Javascript
Bootstrap中点击按钮后变灰并显示加载中实例代码
2016/09/23 Javascript
AngularJS深入探讨scope,继承结构,事件系统和生命周期
2016/11/02 Javascript
DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)
2016/11/09 Javascript
jQuery命名空间与闭包用法示例
2017/01/12 Javascript
AngularJS折叠菜单实现方法示例
2017/05/18 Javascript
JS实现简单短信验证码界面
2017/08/07 Javascript
详解使用路由延迟加载 Angular 模块
2017/10/12 Javascript
详解在WebStorm中添加Vue.js单文件组件的高亮及语法支持
2017/10/21 Javascript
Vue实战之vue登录验证的实现代码
2017/10/31 Javascript
vue2实现数据请求显示loading图
2017/11/28 Javascript
jQuery+ajax实现批量删除功能完整示例
2019/06/06 jQuery
详解利用nodejs对本地json文件进行增删改查
2019/09/20 NodeJs
适用于 Vue 的播放器组件Vue-Video-Player操作
2020/11/16 Javascript
python从sqlite读取并显示数据的方法
2015/05/08 Python
python生成器用法实例详解
2019/11/22 Python
python中的数组赋值与拷贝的区别详解
2019/11/26 Python
团队经理竞聘书
2014/03/31 职场文书
团队激励口号
2014/06/06 职场文书
SpringCloud Alibaba项目实战之nacos-server服务搭建过程
2021/06/21 Java/Android
详解Python为什么不用设计模式
2021/06/24 Python
青岛市的收音机研制与生产
2022/04/07 无线电