JavaScript中的this关键字使用方法总结


Posted in Javascript onMarch 13, 2015

在javascritp中,不一定只有对象方法的上下文中才有this, 全局函数调用和其他的几种不同的上下文中也有this指代。
它可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。JavaScript 中函数的调用有以下几种方式:作为对象方法调用,作为函数调用,作为构造函数调用,和使用 apply 或 call 调用。

1.作为对象方法调用

在 JavaScript 中,函数也是对象,因此函数可以作为一个对象的属性,此时该函数被称为该对象的方法,在使用这种调用方式时,this 被自然绑定到该对象。

  

var point = { 

x : 0, 

y : 0, 

moveTo : function(x, y) { 

    this.x = this.x + x; 

    this.y = this.y + y; 

    } 

}; 

point.moveTo(1, 1)//this 绑定到当前对象,即 point 对象

2.作为函数调用

函数也可以直接被调用,此时 this 绑定到全局对象。在浏览器中,window 就是该全局对象。比如下面的例子:函数被调用时,this 被绑定到全局对象,接下来执行赋值语句,相当于隐式的声明了一个全局变量,这显然不是调用者希望的。

  

function makeNoSense(x) { 

this.x = x; 

} 

makeNoSense(5); 

x;// x 已经成为一个值为 5 的全局变量

对于内部函数,即声明在另外一个函数体内的函数,这种绑定到全局对象的方式会产生另外一个问题。我们仍然以前面提到的 point 对象为例,这次我们希望在 moveTo 方法内定义两个函数,分别将 x,y 坐标进行平移。结果可能出乎大家意料,不仅 point 对象没有移动,反而多出两个全局变量 x,y。

var point = { 

x : 0, 

y : 0, 

moveTo : function(x, y) { 

    // 内部函数

    var moveX = function(x) { 

    this.x = x;//this 绑定到了哪里?

   }; 

   // 内部函数

   var moveY = function(y) { 

   this.y = y;//this 绑定到了哪里?

   };
   moveX(x); 

   moveY(y); 

   } 

}; 

point.moveTo(1, 1); 

point.x; //==>0 

point.y; //==>0 

x; //==>1 

y; //==>1

这属于 JavaScript 的设计缺陷,正确的设计方式是内部函数的 this 应该绑定到其外层函数对应的对象上,为了规避这一设计缺陷,聪明的 JavaScript 程序员想出了变量替代的方法,约定俗成,该变量一般被命名为 that。

var point = { 

 x : 0, 

 y : 0, 

 moveTo : function(x, y) { 

      var that = this; 

     // 内部函数

     var moveX = function(x) { 

     that.x = x; 

     }; 

     // 内部函数

     var moveY = function(y) { 

     that.y = y; 

     } 

     moveX(x); 

     moveY(y); 

     } 

 }; 

 point.moveTo(1, 1); 

 point.x; //==>1 

 point.y; //==>1

作为构造函数调用

JavaScript 支持面向对象式编程,与主流的面向对象式编程语言不同,JavaScript 并没有类(class)的概念,而是使用基于原型(prototype)的继承方式。相应的,JavaScript 中的构造函数也很特殊,如果不使用 new 调用,则和普通函数一样。作为又一项约定俗成的准则,构造函数以大写字母开头,提醒调用者使用正确的方式调用。如果调用正确,this 绑定到新创建的对象上。

function Point(x, y){ 

   this.x = x; 

   this.y = y; 

}

使用 apply 或 call 调用

让我们再一次重申,在 JavaScript 中函数也是对象,对象则有方法,apply 和 call 就是函数对象的方法。这两个方法异常强大,他们允许切换函数执行的上下文环境(context),即 this 绑定的对象。很多 JavaScript 中的技巧以及类库都用到了该方法。让我们看一个具体的例子:

function Point(x, y){ 

   this.x = x; 

   this.y = y; 

   this.moveTo = function(x, y){ 

       this.x = x; 

       this.y = y; 

   } 

}
var p1 = new Point(0, 0); 

var p2 = {x: 0, y: 0}; 

p1.moveTo(1, 1); 

p1.moveTo.apply(p2, [10, 10]);

在上面的例子中,我们使用构造函数生成了一个对象 p1,该对象同时具有 moveTo 方法;使用对象字面量创建了另一个对象 p2,我们看到使用 apply 可以将 p1 的方法应用到 p2 上,这时候 this 也被绑定到对象 p2 上。另一个方法 call 也具备同样功能,不同的是最后的参数不是作为一个数组统一传入,而是分开传入的。

function Foo(){

//1.this引用的构造函数是argument.callee引用的对象

//说明是通过new操作符执行的构造函数

if(this.constructor==arguments.callee){

alert('Object Created');

}

//2.this是window, 那么是全局调用

if(this==window){

alert('normal call');

}

else{//3.否则是作为其他对象的方法来调用

alert('called by '+ this.constructor);

}

}

Foo();//全局函数调用

Foo.call(new Object());//作为一个object对象的成员方法来调用

new Foo();//被new操作符调用,执行对象构造
Javascript 相关文章推荐
JS面向对象、prototype、call()、apply()
May 14 Javascript
基于jquery的划词搜索实现(备忘)
Sep 14 Javascript
用Jquery选择器计算table中的某一列某一行的合计
Aug 13 Javascript
jquery+css实现的红色线条横向二级菜单效果
Aug 22 Javascript
JS+JSP通过img标签调用实现静态页面访问次数统计的方法
Dec 14 Javascript
七个不允许错过的jQuery小技巧
Dec 21 Javascript
javascript 判断是否是微信浏览器的方法
Oct 09 Javascript
echarts3 使用总结(绘制各种图表,地图)
Jan 05 Javascript
jQuery使用DataTable实现删除数据后重新加载功能
Feb 27 Javascript
推荐VSCode 上特别好用的 Vue 插件之vetur
Sep 14 Javascript
详解webpack4.x之搭建前端开发环境
Mar 28 Javascript
CKeditor富文本编辑器使用技巧之添加自定义插件的方法
Jun 14 Javascript
javascript中slice(),splice(),split(),substring(),substr()使用方法
Mar 13 #Javascript
在linux中使用包管理器安装node.js
Mar 13 #Javascript
JQuery中serialize() 序列化
Mar 13 #Javascript
JavaScript中通过prototype属性共享属性和方法的技巧实例
Mar 13 #Javascript
JQuery中$.each 和$(selector).each()的区别详解
Mar 13 #Javascript
JavaScript实现判断图片是否加载完成的3种方法整理
Mar 13 #Javascript
JavaScript检查弹出窗口是否被阻拦的方法技巧
Mar 13 #Javascript
You might like
黑夜路人出的几道php笔试题
2009/08/04 PHP
php下使用curl模拟用户登陆的代码
2010/09/10 PHP
php中将html中的br换行符转换为文本输入中的换行符
2013/03/26 PHP
大家都应该掌握的PHP关联数组使用技巧
2015/12/25 PHP
关于ThinkPhp 框架表单验证及ajax验证问题
2017/07/19 PHP
javascript权威指南 学习笔记之javascript数据类型
2011/09/24 Javascript
让js弹出窗口居前显示的实现方法
2013/07/10 Javascript
js实现下拉框选择要显示图片的方法
2015/02/16 Javascript
jQuery实现可关闭固定于底(顶)部的工具条菜单效果
2015/11/06 Javascript
基于React.js实现原生js拖拽效果引发的思考
2016/03/30 Javascript
微信小程序 前端源码逻辑和工作流详解
2016/10/08 Javascript
vue-cli如何添加less 以及sass
2017/07/06 Javascript
Vue刷新修改页面中数据的方法
2018/09/16 Javascript
微信小程序如何实现全局重新加载
2019/06/05 Javascript
vue中上传视频或图片或图片和文字一起到后端的解决方法
2019/12/01 Javascript
JS中==、===你分清楚了吗
2020/03/04 Javascript
vue 项目引入echarts 添加点击事件操作
2020/09/09 Javascript
浅析我对JS延迟异步脚本的思考
2020/10/12 Javascript
[45:14]Optic vs VP 2018国际邀请赛淘汰赛BO3 第二场 8.24
2018/08/25 DOTA
用于统计项目中代码总行数的Python脚本分享
2015/04/21 Python
详解Python中expandtabs()方法的使用
2015/05/18 Python
Python简单连接MongoDB数据库的方法
2016/03/15 Python
python 获取指定文件夹下所有文件名称并写入列表的实例
2018/04/23 Python
解决python 无法加载downsample模型的问题
2018/10/25 Python
Python读取Pickle文件信息并计算与当前时间间隔的方法分析
2019/01/30 Python
Django 博客实现简单的全文搜索的示例代码
2020/02/17 Python
Python使用cn2an实现中文数字与阿拉伯数字的相互转换
2021/03/02 Python
用CSS3实现背景渐变的方法
2015/07/14 HTML / CSS
英国领先的家庭时尚品牌:Peacocks
2018/01/11 全球购物
西部世纪面试题
2014/12/05 面试题
美术师范毕业生自荐信
2013/11/16 职场文书
挑战杯创业计划书的写作指南
2014/01/07 职场文书
陈胜吴广起义口号
2014/06/20 职场文书
交通事故委托书范本精选
2014/10/04 职场文书
工厂见习报告范文
2014/10/31 职场文书
邹越演讲观后感
2015/06/15 职场文书