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 相关文章推荐
[原创]保存的js无法执行的解决办法
Feb 25 Javascript
获取当前点击按钮的id用this.id实现
Mar 17 Javascript
使用js复制链接中的部分文字的方法
Jul 30 Javascript
js 求时间差的实现代码
Apr 26 Javascript
AngularJS 工作原理详解
Aug 18 Javascript
基于JS实现仿百度百家主页的轮播图效果
Mar 06 Javascript
微信小程序之绑定点击事件实例详解
Jul 07 Javascript
浅谈函数调用的不同方式,以及this的指向
Sep 17 Javascript
Vue的土著指令和自定义指令实例详解
Feb 04 Javascript
微信小程序rich-text富文本用法实例分析
May 20 Javascript
继承行为在 ES5 与 ES6 中的区别详解
Dec 24 Javascript
JavaScript使用canvas绘制随机验证码
Feb 17 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
基于php socket(fsockopen)的应用实例分析
2013/06/02 PHP
php注册登录系统简化版
2020/12/28 PHP
通过chrome浏览器控制台(Console)进行PHP Debug的方法
2016/10/19 PHP
PHP输出图像imagegif、imagejpeg与imagepng函数用法分析
2016/11/14 PHP
jquery动画4.升级版遮罩效果的图片走廊--带自动运行效果
2012/08/24 Javascript
javascript ready和load事件的区别示例介绍
2013/08/30 Javascript
Vuejs第八篇之Vuejs组件的定义实例解析
2016/09/05 Javascript
如何给ss bash 写一个 WEB 端查看流量的页面
2017/03/23 Javascript
JavaScript之事件委托实例(附原生js和jQuery代码)
2017/07/22 jQuery
web前端vue实现插值文本和输出原始html
2018/01/19 Javascript
JS获取今天是本月第几周、本月共几周、本月有多少天、是今年的第几周、是今年的第几天的示例代码
2018/12/05 Javascript
vue 实现websocket发送消息并实时接收消息
2019/12/09 Javascript
vue实现移动端input上传视频、音频
2020/08/18 Javascript
Python使用wxPython实现计算器
2018/01/30 Python
python 把文件中的每一行以数组的元素放入数组中的方法
2018/04/29 Python
Python 中字符串拼接的多种方法
2018/07/30 Python
Python离线安装PIL 模块的方法
2019/01/08 Python
基于python-opencv3的图像显示和保存操作
2019/06/27 Python
手写一个python迭代器过程详解
2019/08/27 Python
python机器学习库xgboost的使用
2020/01/20 Python
python列表删除和多重循环退出原理详解
2020/03/26 Python
python如何快速拼接字符串
2020/10/28 Python
Python实现Word文档转换Markdown的示例
2020/12/22 Python
Vero Moda西班牙官方购物网站:丹麦BESTSELLER旗下知名女装品牌
2018/04/27 全球购物
英国优质家居用品网上品牌:URBANARA
2018/06/01 全球购物
Harman Audio官方商店:购买JBL、Harman Kardon、Infinity和AKG
2019/12/05 全球购物
澳大利亚领先的时尚内衣零售商:Bras N Things
2020/07/28 全球购物
实习生自荐信范文分享
2013/11/27 职场文书
便利店的创业计划书
2014/01/15 职场文书
特色冷饮店创业计划书
2014/01/28 职场文书
护士实习求职信
2014/06/22 职场文书
2015年安全工作总结范文
2015/04/02 职场文书
毕业生捐书活动倡议书
2015/04/27 职场文书
关于迟到的检讨书
2015/05/06 职场文书
上班旷工检讨书
2015/08/15 职场文书
vue实现书本翻页动画效果实例详解
2022/04/08 Vue.js