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 相关文章推荐
div移动 输入框不能输入的问题
Nov 19 Javascript
让图片旋转任意角度及JQuery插件使用介绍
Mar 20 Javascript
IE、FF、Chrome浏览器中的JS差异介绍
Aug 13 Javascript
js模仿hover的具体实现代码
Dec 30 Javascript
jquery mobile开发常见问题分析
Jan 21 Javascript
AngularJS实现按钮提示与点击变色效果
Sep 07 Javascript
微信小程序-拍照或选择图片并上传文件
Jan 06 Javascript
vue实现消息的无缝滚动效果的示例代码
Dec 05 Javascript
微信小程序将字符串生成二维码图片的操作方法
Jul 17 Javascript
微信小程序实现购物车代码实例详解
Aug 29 Javascript
微信小程序全局变量GLOBALDATA的定义和调用过程解析
Sep 23 Javascript
解决vue-loader加载不上的问题
Oct 21 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
PHP setcookie() cannot modify header information 的解决方法
2009/01/09 PHP
又一个php 分页类实现代码
2009/12/03 PHP
超级实用的7个PHP代码片段分享
2012/01/05 PHP
php颜色转换函数hex-rgb(将十六进制格式转成十进制格式)
2013/09/23 PHP
php file_get_contents抓取Gzip网页乱码的三种解决方法
2013/11/12 PHP
php计算程序运行时间的简单例子分享
2014/05/10 PHP
PHP轻量级数据库操作类Medoo增加、删除、修改、查询例子
2014/07/04 PHP
使用php-timeit估计php函数的执行时间
2015/09/06 PHP
总结PHP内存释放以及垃圾回收
2018/03/29 PHP
JavaScript中的Screen屏幕对象
2008/01/16 Javascript
js 新浪的一个图片播放图片轮换效果代码
2008/07/15 Javascript
使用原生js写的一个简单slider
2014/04/29 Javascript
jquery实现清新实用的网页菜单效果
2015/08/28 Javascript
基于HTML5上使用iScroll实现下拉刷新,上拉加载更多
2016/05/21 Javascript
javascript基本语法
2016/05/31 Javascript
基于AngularJS实现的工资计算器实例
2017/06/16 Javascript
微信小程序url传参写变量的方法
2018/08/09 Javascript
使用vue2.0创建的项目的步骤方法
2018/09/25 Javascript
基于VSCode调试网页JavaScript代码过程详解
2020/07/20 Javascript
[53:15]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS TNC
2018/03/30 DOTA
[03:01]完美盛典趣味短片 DOTA2年度最佳&拉胯英雄
2019/12/07 DOTA
python学习--使用QQ邮箱发送邮件代码实例
2019/04/16 Python
Python数据可视化:箱线图多种库画法
2019/11/06 Python
详解Python修复遥感影像条带的两种方式
2020/02/23 Python
Python键鼠操作自动化库PyAutoGUI简介(小结)
2020/05/17 Python
Python的历史与优缺点整理
2020/05/26 Python
pytorch __init__、forward与__call__的用法小结
2021/02/27 Python
一张图片能隐含千言万语之隐藏你的程序代码
2012/12/13 HTML / CSS
大学生作弊检讨书
2014/02/19 职场文书
绿化工程实施方案
2014/03/17 职场文书
党的群众路线领导班子整改方案
2014/09/27 职场文书
应聘教师自荐信
2015/03/26 职场文书
《比的意义》教学反思
2016/02/18 职场文书
导游词之无锡华莱坞
2019/12/02 职场文书
导游词之铁岭象牙山
2019/12/06 职场文书
windows10声卡驱动怎么安装?win10声卡驱动安装操作步骤教程
2022/08/05 数码科技