JavaScript This指向问题详解


Posted in Javascript onNovember 25, 2019

这篇文章主要介绍了JavaScript This指向问题详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

各位小伙伴在面试中被面试官问道this指向问题一定不少吧,同时还被问道apply,call和bind的用法区别,现在,就来简单的聊一聊this到底指向何方。

1.基本概念

MDN的官方解释:与其他语言相比,函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之间也会有一些差别。在绝大多数情况下,函数的调用方式决定了this的值。this不能在执行期间被赋值,并且在每次函数被调用时this的值也可能会不同。

简而言之:

1.this指向的对象称为函数的上下文对象context;

2.this的指向取决于函数被调用方式

不管函数怎么调用的天花乱坠,我们只要记住这几点即可清晰的找出this的指向。

2.小试牛刀

function foo(){
 console.log(this);
}

面试官问你this指向哪里,当然大声回答不知道,原因:谁调用指向谁,函数都没被调用,确实不知道指向。

JavaScript This指向问题详解

小结:直接通过函数名来调用函数,this指向全局变量window;通过对象.函数名调用函数,this指向该对象。

3.DOM对象调用函数时this的指向问题

1.通过选择器选择元素加事件属性来绑定事件,this指向该DOM对象,例子如下:

document.getElementById('btn').onclick=function(){
  console.log('click'); //click
  console.log(this); //<button id="btn">button</button>
 }

2.直接在DOM标签中写事件,this指向window,我们可以通过吧this作为参数传入方法中再使用,例子如下

html:
<button onclick="modify()">add</button>
<span id="count">0</span>
<button onclick="modify()">reduce</button>

script:
// 操作方法
 function modify(){
  console.log(this); //window
 }

因为这个时候是直接调用方法的,所以this指向全局window对象,那么问题来了,我们想判断我们点击的是哪一个按钮,应该怎么做呢,我们可以把this的值作为参数传入方法中再使用,例子如下。

html:
<button onclick="modify(this)">add</button>
<span id="count">0</span>
<button onclick="modify(this)">reduce</button>

script:
// 操作方法
 function modify(_this){
  console.log(_this); 
// <button onclick="modify(this)">add</button>
// <button onclick="modify(this)">reduce</button>
 }

4.对象中this的指向问题

先看一个简单的例子:

var a=1;
function printA(){
 console.log(this.a);
}
var obj={
 a:2,
 foo:printA,
 bar:function(){
  printA();
 }
}
obj.foo(); //2
obj.bar(); //1var foo=obj.foo;foo(); //1

我们定义了一个全局变量a和一个打印a的全局变量方法,之后又定义了一个obj对象,其中包含a属性和foo,bar两个方法。当我们调用obj.foo()打印了2,调用obj.bar()打印了1.

分析:

不管printA在哪里定义的,我们this的指向只取决于被谁调用的。在obj.foo(),foo的属性值为printA,被obj直接调用,所以this指向obj,this.a就是obj.a=2了;

当我们调用obj.bar()时,bar的属性值为function(){printA()},没有明确哪个对象来调用printA方法,this默认指向全局对象window,所以this.a=window.a=1;

第三种情况我们把obj.foo值赋予了foo变量,在调用的时候就相当于是window.foo()了,打印1。

小结:this的指向不是函数声明是绑定的,而是在函数运行过程中动态绑定的。

5.改变this的指向方法:applay call bind

话不多话:写了一个例子,大家先看,万一比喻不恰当,大家能理解其中意思即可

var liLei={
 name:'liLei',
 money:10,
 buyPen:function(){
  this.money=this.money-1;
  console.log(this.name+" have money:"+this.money)
 }
}

var hanMeiMei={
 name:'hanMeiMei',
 money:20,
 buyPan:function(){
  this.money=this.money-2;
  console.log(this.name+" have money:"+this.money)
 }
}

liLei.buyPen(); // liLei have money:9
hanMeiMei.buyPan(); //hanMeiMei have money:18

例子很好理解,输出的结果相信大家也能看得明白,哪天,韩梅梅想买一个盆,她买不了,因为她还没有这个方法,她一想:我没有这个方法,但是李雷有啊,我打电话给李雷把钱他让他帮我买啊;后来李雷想买一个盘,实现方法也是如此。那么,在代码中如何实现呢?

JavaScript有好几个方法可以实现:call,apply,bind。

call方法:

语法:call(thisObj,Object)

定义:调用一个对象的一个方法,以另一个对象替换当前对象。

说明:

call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

liLei.buyPen.call(hanMeiMei); //hanMeiMei have money:19
hanMeiMei.buyPan.call(liLei); //liLei have money:8

apply方法:

语法:apply(thisObj,[argArray])

定义:应用某一对象的一个方法,用另一个对象替换当前对象。

说明:

如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

liLei.buyPen.apply(hanMeiMei); //hanMeiMei have money:19
hanMeiMei.buyPan.apply(liLei); //liLei have money:8

bind方法:

liLei.buyPen.bind(hanMeiMei)(); //hanMeiMei have money:19
hanMeiMei.buyPan.apply(liLei)(); //liLei have money:8

小结:三种方法的相同指出是:可以改变this的指向,不同之处是:apply接受的参数为一个数组,call接收的参数为一个个独立的值;apply,call会直接调用方法,bind改变this的指向返回一个方法不调用。

注:有些低版本的浏览器不支持函数使用bind方法,我们在做浏览器兼容时可以加以判断,具体实现方法暂不赘述。

以上就是个人对于this的指向问题的理解,我们只需记住一点:this指向-谁调用,指向谁。不得不说JavaScript真是个奇妙的世界,文中有纰漏不足的地方,欢迎指正。

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

Javascript 相关文章推荐
JavaScript对象链式操作代码(jquery)
Jul 04 Javascript
javascript object array方法使用详解
Dec 03 Javascript
鼠标滑在标题上显示图片的JS代码
Nov 19 Javascript
Javascript学习笔记之 函数篇(三) : 闭包和引用
Nov 23 Javascript
javascript实现超炫的向上滑行菜单实例
Aug 03 Javascript
JS+DIV+CSS实现仿表单下拉列表效果
Aug 18 Javascript
bootstrap-treeview自定义双击事件实现方法
Jan 09 Javascript
详解Node.js包的工程目录与NPM包管理器的使用
Feb 16 Javascript
AngularJS  自定义指令详解及实例代码
Sep 14 Javascript
JavaScript实现数值自动增加动画
Dec 28 Javascript
Vue 微信端扫描二维码苹果端却只能保存图片问题(解决方法)
Jan 19 Javascript
小程序中使用css var变量(使js可以动态设置css样式属性)
Mar 31 Javascript
简单了解JavaScript sort方法
Nov 25 #Javascript
vue使用swiper实现中间大两边小的轮播图效果
Nov 24 #Javascript
通过GASP让vue实现动态效果实例代码详解
Nov 24 #Javascript
JS控制只能输入数字并且最多允许小数点两位
Nov 24 #Javascript
解决Vue.js应用回退或刷新界面时提示用户保存修改问题
Nov 24 #Javascript
Egg Vue SSR 服务端渲染数据请求与asyncData
Nov 24 #Javascript
mpvue微信小程序开发之实现一个弹幕评论
Nov 24 #Javascript
You might like
全国FM电台频率大全 - 17 湖北省
2020/03/11 无线电
基于ubuntu下nginx+php+mysql安装配置的具体操作步骤
2013/04/28 PHP
Yii配置文件用法详解
2014/12/04 PHP
jquery 图片 上一张 下一张 链接效果(续篇)
2010/04/20 Javascript
网页编辑器ckeditor和ckfinder配置步骤分享
2012/05/24 Javascript
十个迅速提升JQuery性能让你的JQuery跑得更快
2012/12/10 Javascript
使用GruntJS链接与压缩多个JavaScript文件过程详解
2013/08/02 Javascript
jQuery的选择器中的通配符使用介绍
2014/03/20 Javascript
封装了一个支持匿名函数的Javascript事件监听器
2014/06/05 Javascript
JavaScript模块规范之AMD规范和CMD规范
2015/10/27 Javascript
基于jquery实现左右按钮点击的图片切换效果
2021/01/27 Javascript
js中用cssText设置css样式的简单方法
2016/09/19 Javascript
js获取隐藏元素的宽高
2017/02/24 Javascript
WebPack配置vue多页面的技巧
2018/05/15 Javascript
JavaScript基础教程之如何实现一个简单的promise
2018/09/11 Javascript
vuejs中监听窗口关闭和窗口刷新事件的方法
2018/09/21 Javascript
小程序登录态管理的方法示例
2018/11/13 Javascript
python爬虫爬取快手视频多线程下载功能
2018/02/28 Python
Python selenium抓取微博内容的示例代码
2018/05/17 Python
Python采集猫眼两万条数据 对《无名之辈》影评进行分析
2018/12/05 Python
python 如何将数据写入本地txt文本文件的实现方法
2019/09/11 Python
Python3读写Excel文件(使用xlrd,xlsxwriter,openpyxl3种方式读写实例与优劣)
2020/02/13 Python
python+selenium+chromedriver实现爬虫示例代码
2020/04/10 Python
印尼美容产品购物网站:PerfectBeauty.id
2017/12/01 全球购物
莫斯科隐形眼镜网上商店:Linzi
2019/07/22 全球购物
C#公司笔试题
2014/03/28 面试题
简历上的自我评价
2014/02/03 职场文书
经济类毕业生求职信
2014/06/26 职场文书
党员民主评议自我评价
2014/10/20 职场文书
2014年资料员工作总结
2014/11/18 职场文书
解除劳动合同证明书模板
2014/11/20 职场文书
2014城乡环境综合治理工作总结
2014/12/19 职场文书
导游词之无锡梅园
2019/11/28 职场文书
Python爬虫入门案例之回车桌面壁纸网美女图片采集
2021/10/16 Python
Win11任务栏无法正常显示 资源管理器不停重启的解决方法
2022/07/07 数码科技
Win11 Build 25179预览版发布(附更新内容+ISO官方镜像下载)
2022/08/14 数码科技