关于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 相关文章推荐
jQuery 验证插件 Web前端设计模式(asp.net)
Oct 17 Javascript
javascript学习笔记(十四) window对象使用介绍
Jun 20 Javascript
jquery+css+ul模拟列表菜单具体实现思路
Apr 15 Javascript
指定区域的图片自动按比例缩小的js代码(防止页面被图片撑破)
Feb 21 Javascript
node.js中的fs.mkdirSync方法使用说明
Dec 17 Javascript
深入理解JavaScript系列(46):代码复用模式(推荐篇)详解
Mar 04 Javascript
图片旋转、鼠标滚轮缩放、镜像、切换图片js代码
Dec 13 Javascript
详解AngularJS用Interceptors来统一处理HTTP请求和响应
Jun 08 Javascript
JS闭包的几种常见形式实例详解
Sep 16 Javascript
vue 搭建后台系统模块化开发详解
May 01 Javascript
Vue.js仿Select下拉框效果
Feb 18 Javascript
ant design的table组件实现全选功能以及自定义分页
Nov 17 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封装的MSSql操作类完整实例
2016/05/26 PHP
Thinkphp结合AJAX长轮询实现PC与APP推送详解
2017/07/31 PHP
js实现俄罗斯方块小游戏分享
2014/01/31 Javascript
24款热门实用的jQuery插件推荐
2014/12/24 Javascript
JS获取表格内指定单元格html内容的方法
2015/03/31 Javascript
js实现非常简单的焦点图切换特效实例
2015/05/07 Javascript
JavaScript检测并限制复选框选中个数的方法
2015/08/12 Javascript
详解JS正则replace的使用方法
2016/03/06 Javascript
Extjs实现下拉菜单效果
2016/04/01 Javascript
实例讲解JavaScript中call、apply、bind方法的异同
2016/09/13 Javascript
D3.js实现柱状图的方法详解
2016/09/21 Javascript
Javascript中arguments对象的详解与使用方法
2016/10/04 Javascript
ReactNative之FlatList的具体使用方法
2017/11/29 Javascript
vue路由切换时取消之前的所有请求操作
2020/09/01 Javascript
[04:30]显微镜下的DOTA2第五期——拉比克
2013/09/26 DOTA
[44:41]Fnatic vs Liquid 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
[54:27]TNC vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python实现爬虫下载漫画示例
2014/02/16 Python
python网络爬虫之如何伪装逃过反爬虫程序的方法
2017/11/23 Python
Python给你的头像加上圣诞帽
2018/01/04 Python
TensorFlow中权重的随机初始化的方法
2018/02/11 Python
Python实现多属性排序的方法
2018/12/05 Python
python判断计算机是否有网络连接的实例
2018/12/15 Python
Python中使用threading.Event协调线程的运行详解
2020/05/02 Python
Numpy中ndim、shape、dtype、astype的用法详解
2020/06/14 Python
python re模块常见用法例举
2021/03/01 Python
HTML5实现移动端弹幕动画效果
2019/08/01 HTML / CSS
世界上最好的足球商店:Unisport
2019/03/02 全球购物
文秘应聘自荐书范文
2014/02/18 职场文书
采购求职信
2014/03/17 职场文书
矿泉水广告词
2014/03/20 职场文书
司机工作自我鉴定
2014/09/19 职场文书
三严三实学习心得体会
2014/10/13 职场文书
中秋节寄语2015
2015/03/24 职场文书
我的中国梦主题班会
2015/08/14 职场文书
redis 限制内存使用大小的实现
2021/05/08 Redis