详解JavaScript中this的指向问题


Posted in Javascript onJanuary 20, 2017

this是面向对象语言中一个重要的关键字,理解并掌握该关键字的使用对于我们代码的健壮性及优美性至关重要。而javascript的this又有区别于Java、C#等纯面向对象的语言,这使得this更加扑朔迷离,让人迷惑。

this使用到的情况:

1. 纯函数

2. 对象方法调用

3. 使用new调用构造函数

4. 内部函数

5. 使用call / apply

6.事件绑定

1. 纯函数

var name = 'this is window'; //定义window的name属性 
function getName(){ 
 console.log(this); //控制台输出: Window //this指向的是全局对象--window对象 
 console.log(this.name); //控制台输出: this is window / 
} 
getName();

运行结果分析:纯函数中的this均指向了全局对象,即window。

2. 对象方法调用

var name = 'this is window'; //定义window的name属性,看this.name是否会调用到 
var testObj = { 
 name:'this is testObj', 
 getName:function(){ 
 console.log(this); //控制台输出:testObj //this指向的是testObj对象 
 console.log(this.name); //控制台输出: this is testObj 
 } 
} 
testObj.getName();

运行结果分析:被调用方法中this均指向了调用该方法的对象。

3.  使用new调用构造函数

function getObj(){ 
 console.log(this); //控制台输出: getObj{} //this指向的新创建的getObj对象 
} 
new getObj();

运行结果分析:new 构造函数中的this指向新生成的对象。

4. 内部函数

var name = "this is window"; //定义window的name属性,看this.name是否会调用到 
var testObj = { 
 name : "this is testObj", 
 getName:function(){ 
 //var self = this; //临时保存this对象 
 var handle = function(){ 
 console.log(this); //控制台输出: Window //this指向的是全局对象--window对象 
 console.log(this.name); //控制台输出: this is window 
 //console.log(self); //这样可以获取到的this即指向testObj对象 
 } 
 handle(); 
 } 
} 
testObj.getName();

运行结果分析:内部函数中的this仍然指向的是全局对象,即window。这里普遍被认为是JavaScript语言的设计错误,因为没有人想让内部函数中的this指向全局对象。一般的处理方式是将this作为变量保存下来,一般约定为that或者self,如上述代码所示。

5. 使用call / apply

var name = 'this is window'; //定义window的name属性,看this.name是否会调用到 
var testObj1 = { 
 name : 'this is testObj1', 
 getName:function(){ 
 console.log(this); //控制台输出: testObj2 //this指向的是testObj2对象 
 console.log(this.name); //控制台输出: this is testObj2 
 } 
}
var testObj2 = { 
 name: 'this is testObj2' 
}
testObj1.getName.apply(testObj2); 
testObj1.getName.call(testObj2);

Note:apply和call类似,只是两者的第2个参数不同:

[1] call( thisArg [,arg1,arg2,… ] );  // 第2个参数使用参数列表:arg1,arg2,...

[2] apply(thisArg [,argArray] );     //第2个参数使用 参数数组:argArray

运行结果分析:使用call / apply  的函数里面的this指向绑定的对象。

6. 事件绑定

事件方法中的this应该是最容易让人产生疑惑的地方,大部分的出错都源于此。

//页面Element上进行绑定 
 <script type="text/javascript"> 
 function btClick(){ 
 console.log(this); //控制台输出: Window //this指向的是全局对象--window对象 
 } 
 </script> 
 <body> 
 <button id="btn" onclick="btClick();" >点击</button> 
 </body> 
//js中绑定方式(1) 
 <body> 
 <button id="btn">点击</button> 
 </body> 
 <script type="text/javascript"> 
 function btClick(){ 
 console.log(this); //控制台输出:<button id="btn">点击</button> //this指向的是Element按钮对象 
 }
 document.getElementById("btn").onclick = btClick; 
 document.getElementById("btn").onclick(); //默认点击
 </script>
//js中绑定方式(2) 
<body> 
 <button id="btn">点击</button> 
 </body> 
 <script type="text/javascript"> 
 document.getElementById("btn").onclick = function(){ 
 console.log(this); //控制台输出:<button id="btn">点击</button> //this指向的是Element按钮对象 
 } 
 document.getElementById("btn").onclick(); 
 </script>
//js中绑定方式(3) 
<body> 
 <button id="btn">点击</button> 
 </body> 
 <script type="text/javascript"> 
 function btClick(){ 
 console.log(this); 
 }
 document.getElementById("btn").addEventListener('click',btClick); //控制台输出:<button id="btn">点击</button> //this指向的是Element按钮对象把函数(方法)用在事件处理的时候。 
 document.getElementById("btn").attachEvent('onclick',btClick); //IE使用,控制台输出: Window //this指向的是全局对象--window对象 
 </script>

运行结果分析:以上2种常用事件绑定方法,在页面Element上的进行事件绑定(onclick="btClick();"),this指向的是全局对象;而在js中进行绑定,除了attachEvent绑定的事件方法(this指向的是全局对象)外,this指向的是绑定事件的Elment元素。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
javascript学习网址备忘
May 29 Javascript
Jquery中显示隐藏的实现代码分析
Jul 26 Javascript
如何实现JavaScript动态加载CSS和JS文件
Dec 28 Javascript
jQuery实现宽屏图片轮播实例教程
Nov 24 Javascript
理解javascript异步编程
Jan 27 Javascript
AngularJS基础 ng-init 指令简单示例
Aug 02 Javascript
微信小程序之蓝牙的链接
Sep 26 Javascript
利用VS Code开发你的第一个AngularJS 2应用程序
Dec 15 Javascript
vue2过滤器模糊查询方法
Sep 16 Javascript
vue与原生app的对接交互的方法(混合开发)
Nov 28 Javascript
Vue 自定义指令功能完整实例
Sep 17 Javascript
如何在vue中使用百度地图添加自定义覆盖物(水波纹)
Nov 03 Javascript
详解微信小程序入门五: wxml文件引用、模版、生命周期
Jan 20 #Javascript
浅谈JavaScript异步编程
Jan 20 #Javascript
JavaScript实现事件的中断传播和行为阻止方法示例
Jan 20 #Javascript
小程序开发实战:实现九宫格界面的导航的代码实现
Jan 19 #Javascript
BootStrap组件之进度条的基本用法
Jan 19 #Javascript
微信小程序 页面跳转和数据传递实例详解
Jan 19 #Javascript
js实现符合国情的日期插件详解
Jan 19 #Javascript
You might like
关于PHP二进制流 逐bit的低位在前算法(详解)
2013/06/13 PHP
使用PHP生成二维码的两种方法(带logo图像)
2014/03/14 PHP
PHP.ini中配置屏蔽错误信息显示和保存错误日志的例子
2014/05/12 PHP
php实现改变图片直接打开为下载的方法
2015/04/14 PHP
基于swoole实现多人聊天室
2018/06/14 PHP
PHP手机号码及邮箱正则表达式实例解析
2020/07/11 PHP
javascript实现将文件保存到本地方法汇总
2015/07/26 Javascript
深入解读JavaScript中的Hoisting机制
2015/08/12 Javascript
javascript实现禁止复制网页内容汇总
2015/12/30 Javascript
Highcharts学习之坐标轴
2016/08/02 Javascript
easyui datebox 时间限制,datebox开始时间限制结束时间,datebox截止日期比起始日期大的实现代码
2017/01/12 Javascript
在百度搜索结果中去除掉一些网站的资料(通过js控制不让显示)
2017/05/02 Javascript
深究AngularJS之ui-router详解
2017/06/13 Javascript
webpack实现热加载自动刷新的方法
2017/07/30 Javascript
vue2实现搜索结果中的搜索关键字高亮的代码
2018/08/29 Javascript
node将geojson转shp返回给前端的实现方法
2019/05/29 Javascript
js类的继承定义与用法分析
2019/06/21 Javascript
javascript中的offsetWidth、clientWidth、innerWidth及相关属性方法
2020/05/14 Javascript
vue项目打包后请求地址错误/打包后跨域操作
2020/11/04 Javascript
JavaScript事件概念详解(区分静态注册和动态注册)
2021/02/05 Javascript
如何管理Vue中的缓存页面
2021/02/06 Vue.js
[00:12]2018DOTA2亚洲邀请赛 sylar表现SOLO技艺
2018/04/06 DOTA
[01:48:04]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Elephant BO3 第一场 2月7日
2021/03/11 DOTA
Python类定义和类继承详解
2015/05/08 Python
Python实现截屏的函数
2015/07/26 Python
Python实现接受任意个数参数的函数方法
2018/04/21 Python
python pyheatmap包绘制热力图
2018/11/09 Python
python3注册全局热键的实现
2020/03/22 Python
查看keras各种网络结构各层的名字方式
2020/06/11 Python
python中的时区问题
2021/01/14 Python
公司培训欢迎词
2014/01/10 职场文书
军训自我鉴定
2014/01/22 职场文书
小学英语教学反思
2014/01/30 职场文书
如何写贫困证明申请书
2014/10/29 职场文书
vue实现省市区联动 element-china-area-data插件
2022/04/22 Vue.js
微前端qiankun改造日渐庞大的项目教程
2022/06/21 Javascript