基于javaScript的this指向总结


Posted in Javascript onJuly 22, 2017

在javascript中this的指向一直是前端同事的心头病,也同时是各面试题的首选,现在我们就来总结一下js中this的指向。首先需要了解一下几个概念:

1:全局变量默认挂载在window对象下

2:一般情况下this指向它的调用者

3:es6的箭头函数中,this指向创建者,并非调用者

4:通过call、apply、bind可以改改变this的指向

下面我们具体分析一下

1:在函数调用时

 (非严格模式)

const func = function () {
  console.log(this);
  const func2 = function () {
   console.log(this);
  };
  func2(); //Window
 };
 func(); //Window

 (严格模式)

'use strict'
 const func = function () {
  console.log(this);
  const func2 = function () {
   console.log(this);
  };
  func2(); //undefined
 };
 func(); //undefined

结合第四和第一两条规则:func这个函数是全局的,默认挂载在window对象下,this指向它的调用者即window,所以输出window对象,但是在严格模式下,this不允许指向全局变量window,所以输出为undefined(func2在函数直接调用时默认指向了全局window,其实这属于javascript设计上的缺陷,正确的设计方式是内部函数的this 应该绑定到其外层函数对应的对象上,为了规避这一设计缺陷,聪明的 JavaScript 程序员想出了变量替代的方法,约定俗成,该变量一般被命名为 that。这种方式在接下来会讲到)。

2:作为对象方法

const user = {

  userName: '小张',
  age: 18,
  selfIntroduction: function () {
   const str = '我的名字是:' + this.userName + ",年龄是:" + this.age;
   console.log(str);

   const loop = function () {
    console.log('我的名字是:' + this.userName + ",年龄是:" + this.age);
   };

   loop();  //我的名字是:undefined,年龄是:undefined

  }
 };

 user.selfIntroduction(); //我的名字是:小张,年龄是:18

按照咱的第一条规则,this指向他的调用者,selfIntroduction()方法的调用者是user,所以在selfIntroduction()方法内部this指向了他的父对象即user,而loop方法输出的为undefined的原因就是我在上面所说的javascript的设计缺陷了,在这种情况下,我们通常选择在selfIntroduction()方法里将this缓存下来。

const user = {
  userName: '小张',
  age: 18,
  selfIntroduction: function () {
   const str = '我的名字是:' + this.userName + ",年龄是:" + this.age;
   console.log(str);

   const that=this;

   const loop = function () {
    console.log('我的名字是:' + that.userName + ",年龄是:" + that.age);
   };

   loop();  //我的名字是:小张,年龄是:18

  }
 };

 user.selfIntroduction(); //我的名字是:小张,年龄是:18

此时loop的this指向就理想了。

const user={

  userName:'小张',
  age:18,
  selfIntroduction:function(){
   const str='我的名字是:'+this.userName+",年龄是:"+this.age;
   console.log(str); 
  }
 };

 const other =user.selfIntroduction;
 other(); //我的名字是:undefined,年龄是:undefined

 const data={
  userName:'小李',
  age:19,
 };
 data.selfIntroduction=user.selfIntroduction;
 data.selfIntroduction(); //我的名字是:小李,年龄是:19

在看这段代码,将selfIntroduction()赋值给了全局变量other,调用other()方法,other挂载在全局函数window对象下,window对象下没有userName 和 age 这两个属性,所以输出为undefined。第二段代码,申明了data对象,包含了username和age属性,记住我们的第二条规则一般情况下this指向它的调用者,大家就明白了,data是selfIntroduction()的函数的调用者,所以输出了data的userName和age。

3:在html里作为事件触发

<body>

 <div id="btn">点击我</div>

</body>
const btn=document.getElementById('btn');

  btn.addEventListener('click',function () {
   console.log(this); //<div id="btn">点击我</div>
  })

在种情况其实也是遵循了第二条规则一般情况下this指向它的调用者,this指向了事件的事件源即event。

4:new关键字(构造函数)

const fun=function(userName){
  this.userName=userName;
 }

 const user=new fun('郭德纲'); 

 console.log(user.userName); //郭德纲

这个就不多赘述了,new关键字构造了一个对象实例,赋值给了user,所以userName就成为了user对象的属性。

5:es6(箭头函数)

const func1=()=>{

  console.log(this); 

 };

 func1(); //Window
const data={
  userName:'校长',
  selfIntroduction:function(){
   console.log(this); //Object {userName: "校长", selfIntroduction: function}

   const func2=()=>{
    console.log(this); //Object {userName: "校长", selfIntroduction: function}
   }

   func2();
  }

 }

 data.selfIntroduction();

大家在看看我开头说的第三条准则:es6的箭头函数中,this指向创建者,并非调用者,fun1 在全局函数下创建,所以this指向全局window,而fun2在对象data下创建,this指向data对象,所以在func2函数内部this指向data对象,个人认为es6的箭头函数的this指向是对我上面所说的javascript设计缺陷的改进,(个人认知)。

6:改变this的指向

call、apply、bind这三个函数是可以人为的改变函数的this指向的,在这里就不多说这三者的区别了,在往后的博客里我会详细解释这三者的区别的。现在先拿一个来举一个例子

const func=function(){
 console.log(this);
};

func(); //window

func.apply({userName:"郭德纲"}); //Object {userName: "郭德纲"}

这三个方法都是可以人为的改变this的指向,区别是call、apply会将该方法绑定this之后立即执行,而bind方法会返回一个可执行的函数。

说这很多总结起来就是我开头说的4点

1:全局变量默认挂载在window对象下

2:一般情况下this指向它的调用者

3:es6的箭头函数中,this指向创建者,并非调用者

4:通过call、apply、bind可以改改变this的指向

说实话第一次写博客,确实挺忐忑的,会不会有人看我的博客?会不会写的不正确?……想好多了,总结了:不好的地方欢迎指正。

以上这篇基于javaScript的this指向总结就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
clientX,pageX,offsetX,x,layerX,screenX,offsetLeft区别分析
Mar 12 Javascript
JavaScript学习历程和心得小结
Aug 16 Javascript
Google Maps API地图应用示例分享
Oct 23 Javascript
关于编写性能高效的javascript事件的技术
Nov 28 Javascript
JQuery移动页面开发之屏幕方向改变与滚屏的实现
Dec 03 Javascript
JavaScript操作 url 中 search 部分方法函数
Jun 15 Javascript
详解在vue-cli中引用jQuery、bootstrap以及使用sass、less编写css
Nov 08 jQuery
基于JS实现带动画效果的流程进度条
Jun 01 Javascript
Vuerouter的beforeEach与afterEach钩子函数的区别
Dec 26 Javascript
vue的keep-alive用法技巧
Aug 15 Javascript
layui加载数据显示loading加载完成loading消失的实例代码
Sep 23 Javascript
详解element-ui 表单校验 Rules 配置 常用黑科技
Jul 11 Javascript
JavaScript之事件委托实例(附原生js和jQuery代码)
Jul 22 #jQuery
基于LayUI实现前端分页功能的方法
Jul 22 #Javascript
浅谈原型对象的常用开发模式
Jul 22 #Javascript
浅谈事件冒泡、事件委托、jQuery元素节点操作、滚轮事件与函数节流
Jul 22 #jQuery
JS实现微信摇一摇原理解析
Jul 22 #Javascript
一个简易的js图片轮播效果
Jul 22 #Javascript
基于JS脚本语言的基础语法详解
Jul 22 #Javascript
You might like
Wordpress 相册插件 NextGEN-Gallery 添加目录将中文转为拼音的解决办法
2010/12/29 PHP
解析php dirname()与__FILE__常量的应用
2013/06/24 PHP
YII Framework框架教程之使用YIIC快速创建YII应用详解
2016/03/15 PHP
PHP PDOStatement::execute讲解
2019/01/31 PHP
js innerHTML 的一些问题的解决方法
2008/06/22 Javascript
jquery的选择器的使用技巧之如何选择input框
2013/09/22 Javascript
jQuery平滑旋转幻灯片特效代码分享
2015/09/07 Javascript
AngularJS入门教程之控制器详解
2016/07/27 Javascript
ES6 javascript中Class类继承用法实例详解
2017/10/30 Javascript
基于vue2.0实现简单轮播图
2017/11/27 Javascript
JS实现自定义弹窗功能
2018/08/08 Javascript
javascript之分片上传,断点续传的实际项目实现详解
2019/09/05 Javascript
基于JS实现table导出Excel并保留样式
2020/05/19 Javascript
vue实现桌面向网页拖动文件的示例代码(可显示图片/音频/视频)
2021/03/01 Vue.js
[18:16]sakonoko 2017年卡尔集锦
2018/02/06 DOTA
[42:06]2019国际邀请赛全明星赛 8.23
2019/09/05 DOTA
python基础教程之元组操作使用详解
2014/03/25 Python
python之文件的读写和文件目录以及文件夹的操作实现代码
2016/08/28 Python
对python当中不在本路径的py文件的引用详解
2018/12/15 Python
python3.6使用tkinter实现弹跳小球游戏
2019/05/09 Python
浅析HTML5 Landmark
2020/09/11 HTML / CSS
速卖通欧盟:Aliexpress EU
2020/08/19 全球购物
Java中实现多态的机制是什么?
2014/12/07 面试题
客服端调用EJB对象的几个基本步骤
2012/01/15 面试题
如何通过jdbc调用存储过程
2012/04/19 面试题
电子商务专业推荐信范文
2013/12/02 职场文书
总经理秘书的岗位职责
2013/12/27 职场文书
喷漆工的岗位职责
2014/03/17 职场文书
小组名称和口号
2014/06/09 职场文书
物流专业求职信
2014/06/30 职场文书
医院合作意向书范本
2015/05/08 职场文书
女方离婚起诉书
2015/05/18 职场文书
律师函格式范本
2015/05/27 职场文书
Idea连接MySQL数据库出现中文乱码的问题
2021/04/14 MySQL
MySQL基于索引的压力测试的实现
2021/11/07 MySQL
Ubuntu Server 安装Tomcat并配置systemctl
2022/04/28 Servers