基于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 相关文章推荐
Use Word to Search for Files
Jun 15 Javascript
JavaScript关于select的相关操作说明
Jan 13 Javascript
javascript自执行函数之伪命名空间封装法
Dec 25 Javascript
js判断两个日期是否相等的方法
Sep 10 Javascript
本人自用的global.js库源码分享
Feb 28 Javascript
js给网页加上背景音乐及选择音效的方法
Mar 03 Javascript
如何利用Promises编写更优雅的JavaScript代码
May 17 Javascript
jQuery插件uploadify实现ajax效果的图片上传
Jun 18 Javascript
Javascript中this绑定的3种方法与比较
Oct 13 Javascript
layui异步加载table表中某一列数据的例子
Sep 16 Javascript
JsonServer安装及启动过程图解
Feb 28 Javascript
VueJS实现用户管理系统
May 29 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
php中判断数组相等的方法以及数组运算符介绍
2015/03/30 PHP
thinkPHP中钩子的两种配置调用方法详解
2016/11/11 PHP
php批量删除操作代码分享
2017/02/26 PHP
php+mysql开发的最简单在线题库(在线做题系统)完整案例
2019/03/30 PHP
取得传值的函数
2006/10/27 Javascript
10个基于Jquery的幻灯片插件教程
2010/10/29 Javascript
Javascript Boolean、Nnumber、String 强制类型转换的区别详细介绍
2012/12/13 Javascript
js使用removeChild方法动态删除div元素
2014/08/01 Javascript
js模仿php中strtotime()与date()函数实现方法
2015/08/11 Javascript
js实现文字垂直滚动和鼠标悬停效果
2015/12/31 Javascript
js canvas仿支付宝芝麻信用分仪表盘
2016/11/16 Javascript
easy ui datagrid 从编辑框中获取值的方法
2017/02/22 Javascript
Node.js如何实现注册邮箱激活功能 (常见)
2017/07/23 Javascript
Vuejs中使用markdown服务器端渲染的示例
2017/11/22 Javascript
解决vue 项目引入字体图标报错、不显示等问题
2018/09/01 Javascript
使用vue自定义指令开发表单验证插件validate.js
2019/05/23 Javascript
jQuery实现高级检索功能
2019/05/28 jQuery
Vue实现点击按钮复制文本内容的例子
2019/11/09 Javascript
ant design的table组件实现全选功能以及自定义分页
2020/11/17 Javascript
[04:04]DOTA2亚洲邀请赛比赛场馆&酒店全攻略
2017/03/23 DOTA
详解 Python中LEGB和闭包及装饰器
2017/08/03 Python
python format 格式化输出方法
2018/07/16 Python
Python爬虫框架Scrapy基本用法入门教程
2018/07/26 Python
聊聊python里如何用Borg pattern实现的单例模式
2019/06/06 Python
Python实现FTP文件传输的实例
2019/07/07 Python
基于python 等频分箱qcut问题的解决
2020/03/03 Python
德国童装购物网站:NICKI´S.com
2018/04/20 全球购物
倩碧澳大利亚官网:Clinique澳大利亚
2019/07/22 全球购物
俄罗斯香水和化妆品网上商店:NOTINO.ru
2019/12/17 全球购物
质检的岗位职责
2013/11/17 职场文书
机械电子工程专业推荐信范文
2013/11/20 职场文书
绘画专业自荐信范文
2014/02/23 职场文书
农林环境专业求职信
2014/03/13 职场文书
告诉你创业计划书的8个实用技巧
2019/07/12 职场文书
教你快速构建一个基于nginx的web集群项目
2021/11/27 Servers
一起来学习Python的元组和列表
2022/03/13 Python