javascript this指向相关问题及改变方法


Posted in Javascript onNovember 19, 2020

在学习javascript中我们往往会被this的指向问题弄的头昏转向,今天我们就来学习一下this的指向问题,和改变this指向的方法。

一.this的指向问题

在学习this的指向问题之前我们需要明白两点:

1:this永远指向一个对象;

2:this的指向完全取决于函数调用的位置;

针对上面第一点我们能很好理解,因为在javascript中一切都是对象。第二点其实也是好理解,当函数调用的位置不同是,this的指向的对象就不同,所以可以说this的指向可以动态变换的,下面我们先通过一个简单的例子来看一下this的指向是变换的

<script>
function fun(){
   console.log(this.name);

 }
 var change={
   name:'hello',
   f:fun
 }
 var name ='world'
 var result=change.f()//hello
 fun();//world
</script>

通过上述例子我们可以很清楚的看到this的指向的变化,因为有一个函数在对象change里面,所以this就是指向的函数外部的对象,所以输出了hello。

想必看完上述例子后大家对this的动态指向切换有了一定的了解。

那么接下来,我们对this使用最频繁的几种情况做一个总结,最常见的基本就是以下3种:

对象中的方法,事件绑定 ,构造函数 ,定时器

前两个就不必多说了,我们看一下定时器中的this指向问题,

var obj = {
  fun:function(){
    this ;
  }
}
​
setInterval(obj.fun,1000);   // this指向window对象
setInterval('obj.fun()',1000); // this指向obj对象

setInterval() 是window对象下内置的一个方法,接受两个参数,第一个参数允许是一个函数或者是一段可执行的 JS 代码,第二个参数则是执行前面函数或者代码的时间间隔;

在上面的代码中,setInterval(obj.fun,1000) 的第一个参数是obj对象的fun ,因为 JS 中函数可以被当做值来做引用传递,实际就是将这个函数的地址当做参数传递给了 setInterval 方法,换句话说就是 setInterval 的第一参数接受了一个函数,那么此时1000毫秒后,函数的运行就已经是在window对象下了,也就是函数的调用者已经变成了window对象,所以其中的this则指向的全局window对象;

而在 setInterval('obj.fun()',1000) 中的第一个参数,实际则是传入的一段可执行的 JS 代码;1000毫秒后当 JS 引擎来执行这段代码时,则是通过 obj 对象来找到 fun 函数并调用执行,那么函数的运行环境依然在 对象 obj 内,所以函数内部的this也就指向了 obj 对象;

除了这些我们还需要理解三个可以改变this指向的函数,包括箭头函数,call(),apply()

箭头函数:官方有解释,箭头函数引入的其中一个原因,就是其不绑定this;在箭头函数中,箭头函数的this被设置为封闭的词法环境的,换句话说,箭头函数中的this取决于该函数被创建时的环境。

var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
// 接着上面的代码
// 作为对象的一个方法调用
var obj = {foo: foo};
console.log(obj.foo() === globalObject); // true

// 尝试使用call来设定this
console.log(foo.call(obj) === globalObject); // true

// 尝试使用bind来设定this
foo = foo.bind(obj);
console.log(foo() === globalObject); // true

无论如何,foo 的 this 被设置为他被创建时的环境(在上面的例子中,就是全局对象)。这同样适用于在其他函数内创建的箭头函数:这些箭头函数的this被设置为封闭的词法环境的。

// 创建一个含有bar方法的obj对象,
// bar返回一个函数,
// 这个函数返回this,
// 这个返回的函数是以箭头函数创建的,
// 所以它的this被永久绑定到了它外层函数的this。
// bar的值可以在调用中设置,这反过来又设置了返回函数的值。
var obj = {
 bar: function() {
  var x = (() => this);
  return x;
 }
};

// 作为obj对象的一个方法来调用bar,把它的this绑定到obj。
// 将返回的函数的引用赋值给fn。
var fn = obj.bar();

// 直接调用fn而不设置this,
// 通常(即不使用箭头函数的情况)默认为全局对象
// 若在严格模式则为undefined
console.log(fn() === obj); // true

// 但是注意,如果你只是引用obj的方法,
// 而没有调用它
var fn2 = obj.bar;
// 那么调用箭头函数后,this指向window,因为它从 bar 继承了this。
console.log(fn2()() == window); // true

call和apply方法:将一个对象作为call或者apply的第一个参数,this将会被绑定到这个参数对象上

var obj = {parent:'男'};
var parent = '28';
function child(obj){
  console.log(this.parent);
}
child(); // 28 
child.call(obj); //男
child.apply(obj); //男

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery EasyUI API 中文文档 - ProgressBar 进度条
Sep 29 Javascript
网页下载文件期间如何防止用户对网页进行其他操作
Jun 27 Javascript
js 判断所选时间(或者当前时间)是否在某一时间段的实现代码
Sep 05 Javascript
深入理解逻辑表达式的用法 与或非的用法
Jun 06 Javascript
ES6新特性之类(Class)和继承(Extends)相关概念与用法分析
May 24 Javascript
使用Vue自定义数字键盘组件(体验度极好)
Dec 19 Javascript
VUE 配置vue-devtools调试工具及安装方法
Sep 30 Javascript
vant(ZanUi)结合async-validator实现表单验证的方法
Dec 06 Javascript
nvm、nrm、npm 安装和使用详解(小结)
Jan 17 Javascript
ES6知识点整理之函数对象参数默认值及其解构应用示例
Apr 17 Javascript
Vue.js如何使用Socket.IO的示例代码
Sep 05 Javascript
原生JS中应该禁止出现的写法
May 05 Javascript
JavaScript实现alert弹框效果
Nov 19 #Javascript
Vue 打包的静态文件不能直接运行的原因及解决办法
Nov 19 #Vue.js
如何使用 vue-cli 创建模板项目
Nov 19 #Vue.js
原生js实现自定义消息提示框
Nov 19 #Javascript
原生js实现点击按钮复制内容到剪切板
Nov 19 #Javascript
jQuery-App输入框实现实时搜索
Nov 19 #jQuery
elementUI同一页面展示多个Dialog的实现
Nov 19 #Javascript
You might like
zf框架的session会话周期及次数限制使用示例
2014/03/13 PHP
PHP文件系统管理(实例讲解)
2017/09/19 PHP
kmock javascript 单元测试代码
2011/02/06 Javascript
JQuery操作tr和td内容的方法实例
2013/03/06 Javascript
javascript检测页面是否缩放的小例子
2013/05/16 Javascript
利用js 进行输入框自动匹配字符的小例子
2013/06/29 Javascript
jquery click([data],fn)使用方法实例介绍
2013/07/08 Javascript
jquery实现的随机多彩tag标签随机颜色和字号大小效果
2014/03/27 Javascript
两种方法基于jQuery实现IE浏览器兼容placeholder效果
2014/10/14 Javascript
AngularJS使用自定义指令替代ng-repeat的方法
2016/09/17 Javascript
bootstrap modal弹出框的垂直居中
2016/12/14 Javascript
理解nodejs的stream和pipe机制的原理和实现
2017/08/12 NodeJs
JavaScript禁用右键单击优缺点分析
2019/01/20 Javascript
微信小程序缓存过期时间的使用详情
2019/05/12 Javascript
Vue最新防抖方案(必看篇)
2019/10/30 Javascript
Vant 中的Toast设置全局的延迟时间操作
2020/11/04 Javascript
[00:35]DOTA2上海特级锦标赛 EG战队宣传片
2016/03/04 DOTA
[51:36]Optic vs Newbee 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python cookbook(数据结构与算法)根据字段将记录分组操作示例
2018/03/19 Python
在python中用print()输出多个格式化参数的方法
2019/07/16 Python
Django Docker容器化部署之Django-Docker本地部署
2019/10/09 Python
centos+nginx+uwsgi+Django实现IP+port访问服务器
2019/11/15 Python
Numpy与Pytorch 矩阵操作方式
2019/12/27 Python
Python利用FFT进行简单滤波的实现
2020/02/26 Python
Python yield的用法实例分析
2020/03/06 Python
SpringBoot首页设置解析(推荐)
2021/02/11 Python
CSS3 filter(滤镜)实现网页灰色或者黑色模式的示例代码
2021/02/24 HTML / CSS
伊利莎白雅顿官网:Elizabeth Arden
2016/10/10 全球购物
公司董事长职责
2013/12/12 职场文书
农村婚礼证婚词
2014/01/08 职场文书
县级文明单位申报材料
2014/05/23 职场文书
2014政府领导班子对照检查材料思想汇报(3篇)
2014/09/26 职场文书
单位单身证明样本
2014/10/11 职场文书
2014年培训工作总结范文
2014/11/27 职场文书
Filebeat 采集 Nginx 日志的方法
2021/03/31 Servers
用Python selenium实现淘宝抢单机器人
2021/06/18 Python