关于JavaScript中的this指向问题总结篇


Posted in Javascript onJuly 23, 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 相关文章推荐
抽出www.templatemonster.com的鼠标悬停加载大图模板的代码
Jul 11 Javascript
javascript 密码强弱度检测万能插件
Feb 25 Javascript
firebug的一个有趣现象介绍
Nov 30 Javascript
javascript/jquery获取地址栏url参数的方法
Mar 05 Javascript
js 判断浏览器使用的语言示例代码
Mar 22 Javascript
jQuery EasyUI 入门必看
Jun 03 Javascript
基于jQuery实现表格内容的筛选功能
Aug 21 Javascript
微信小程序 保留小数(toFixed)详细介绍
Nov 16 Javascript
Bootstrap与Angularjs的模态框实例代码
Aug 03 Javascript
jQuery实现对网页节点的增删改查功能示例
Sep 18 jQuery
简单实现jquery隔行变色
Nov 09 jQuery
详解vue-cli@2.x项目迁移日志
Jun 06 Javascript
浅析JS中常用类型转换及运算符表达式
Jul 23 #Javascript
js实现带进度条提示的多视频上传功能
Dec 13 #Javascript
基于javaScript的this指向总结
Jul 22 #Javascript
JavaScript之事件委托实例(附原生js和jQuery代码)
Jul 22 #jQuery
基于LayUI实现前端分页功能的方法
Jul 22 #Javascript
浅谈原型对象的常用开发模式
Jul 22 #Javascript
浅谈事件冒泡、事件委托、jQuery元素节点操作、滚轮事件与函数节流
Jul 22 #jQuery
You might like
php版小黄鸡simsimi聊天机器人接口分享
2014/01/26 PHP
PHP实现设计模式中的抽象工厂模式详解
2014/10/11 PHP
PHP性能分析工具xhprof的安装使用与注意事项
2017/12/19 PHP
在Laravel5中正确设置文件权限的方法
2019/05/22 PHP
javascript 模拟JQuery的Ready方法实现并出现的问题
2009/12/06 Javascript
jquery关于页面焦点的定位(文本框获取焦点时改变样式 )
2010/09/10 Javascript
Dom操作之兼容技巧分享
2011/09/20 Javascript
通过正则格式化url查询字符串实现代码
2012/12/28 Javascript
js中call与apply的用法小结
2013/12/28 Javascript
js取值中form.all和不加all的区别介绍
2014/01/20 Javascript
jQuery实现仿腾讯迷你首页选项卡效果代码
2015/09/17 Javascript
跟我学习javascript创建对象(类)的8种方法
2015/11/20 Javascript
Javascript中神奇的this
2016/01/20 Javascript
关于javascript的一些知识以及循环详解
2016/09/12 Javascript
js中的触发事件对象event.srcElement与event.target详解
2017/03/15 Javascript
如何使用bootstrap框架 bootstrap入门必看!
2017/04/13 Javascript
微信小程序 五星评分的实现实例
2017/08/04 Javascript
基于Require.js使用方法(总结)
2017/10/26 Javascript
JSONP原理及应用实例详解
2018/09/13 Javascript
vue项目中使用Hbuilder打包app 设置沉浸式状态栏的方法
2018/10/22 Javascript
JavaScript实现美化滑块效果
2019/05/17 Javascript
python 解析html之BeautifulSoup
2009/07/07 Python
推荐11个实用Python库
2015/01/23 Python
基于Python实现文件大小输出
2016/01/11 Python
Python中字符串的格式化方法小结
2016/05/03 Python
Python计算斗牛游戏概率算法实例分析
2017/09/26 Python
python更改已存在excel文件的方法
2018/05/03 Python
Python动态生成多维数组的方法示例
2018/08/09 Python
pygame游戏之旅 计算游戏中躲过的障碍数量
2018/11/20 Python
python实现贪吃蛇小游戏
2020/03/21 Python
python简单实现矩阵的乘,加,转置和逆运算示例
2019/07/10 Python
python内存动态分配过程详解
2019/07/15 Python
html5之Canvas路径绘图、坐标变换应用实例
2012/12/26 HTML / CSS
高中同学会活动方案
2014/08/14 职场文书
导游词开场白
2015/01/31 职场文书
初中政治教学反思
2016/02/23 职场文书