详解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 相关文章推荐
js 面向对象的技术创建高级 Web 应用程序
Feb 25 Javascript
使用jsonp完美解决跨域问题
Nov 27 Javascript
jquery实现向下滑出的二级导航下滑菜单效果
Aug 25 Javascript
js控制div层的叠加简单方法
Oct 15 Javascript
JavaScript中 this 指向问题深度解析
Feb 21 Javascript
webpack打包后直接访问页面图片路径错误的解决方法
Jun 17 Javascript
JS图片预加载插件详解
Jun 21 Javascript
vue项目常用组件和框架结构介绍
Dec 24 Javascript
vue .js绑定checkbox并获取、改变选中状态的实例
Aug 24 Javascript
使用vue2实现带地区编号和名称的省市县三级联动效果
Nov 05 Javascript
js实现表单项的全选、反选及删除操作示例
Jun 05 Javascript
Vue+TypeScript中处理computed方式
Apr 02 Vue.js
详解微信小程序入门五: 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绝对路径与相对路径之间关系的的分析
2010/03/03 PHP
PHP学习笔记之二 php入门知识
2011/01/12 PHP
php常用ODBC函数集(详细)
2013/06/24 PHP
ThinkPHP3.1新特性之对页面压缩输出的支持
2014/06/19 PHP
PHP中判断文件存在使用is_file还是file_exists?
2015/04/03 PHP
php高清晰度无损图片压缩功能的实现代码
2018/12/09 PHP
phpstorm激活码2020附使用详细教程
2020/09/25 PHP
用javascript实现的图片马赛克后显示并切换加文字功能
2007/04/21 Javascript
学习ExtJS border布局
2009/10/08 Javascript
一个封装js代码-----展开收起效果示例
2013/07/03 Javascript
JavaScript中创建对象和继承示例解读
2014/02/12 Javascript
网站内容禁止复制和粘贴、另存为的js代码
2014/02/26 Javascript
老生常谈原生JS执行环境与作用域
2016/11/22 Javascript
Node.js Mongodb 密码特殊字符 @的解决方法
2017/04/11 Javascript
基于BootStrap的文本编辑器组件Summernote
2017/10/27 Javascript
在 Vue 项目中引入 tinymce 富文本编辑器的完整代码
2018/05/04 Javascript
写一个Vue Popup组件
2019/02/25 Javascript
Vue项目部署的实现(阿里云+Nginx代理+PM2)
2019/03/26 Javascript
JavaScript隐式类型转换代码实例
2020/05/29 Javascript
vue - props 声明数组和对象操作
2020/07/30 Javascript
[01:34]DOTA2 7.22版本新增神杖效果一览(敏捷英雄篇)
2019/05/28 DOTA
Python Requests安装与简单运用
2016/04/07 Python
Tensorflow训练MNIST手写数字识别模型
2020/02/13 Python
Python urllib库如何添加headers过程解析
2020/10/05 Python
Python: glob匹配文件的操作
2020/12/11 Python
城市观光通行证:The Sightseeing Pass
2018/04/28 全球购物
联强国际笔试题面试题
2013/07/10 面试题
为什么要用EJB
2014/04/17 面试题
大学生的网上创业计划书
2013/12/31 职场文书
食品安全检查制度
2014/02/03 职场文书
《大作家的小老师》教学反思
2014/04/16 职场文书
党员民主生活会对照检查材料思想汇报
2014/09/28 职场文书
2019年七夕情人节浪漫祝福语大全!
2019/08/08 职场文书
导游词之上海豫园
2019/10/24 职场文书
面试分析分布式架构Redis热点key大Value解决方案
2022/03/13 Redis
在 Python 中利用 Pool 进行多线程
2022/04/24 Python