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 相关文章推荐
一个判断email合法性的函数[非正则]
Dec 09 Javascript
JSQL  一个 web DB 的封装
May 05 Javascript
jQuery select操作控制方法小结
May 26 Javascript
用C/C++来实现 Node.js 的模块(二)
Sep 24 Javascript
解决angular的post请求后SpringMVC后台接收不到参数值问题的方法
Dec 10 Javascript
JavaScript简单实现合并两个Json对象的方法示例
Oct 16 Javascript
初学者AngularJS的环境搭建过程
Oct 27 Javascript
细说webpack源码之compile流程-rules参数处理技巧(2)
Dec 26 Javascript
JS实现统计字符串中字符出现个数及最大个数功能示例
Jun 04 Javascript
Vue中的异步组件函数实现代码
Jul 20 Javascript
面试题:react和vue的区别分析
Apr 08 Javascript
jquery检测上传文件大小示例
Apr 26 jQuery
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生成静态页面详解
2006/11/19 PHP
PHP去除数组中重复的元素并按键名排序函数
2008/08/18 PHP
用php实现的获取网页中的图片并保存到本地的代码
2010/01/05 PHP
常用的PHP数据库操作方法(MYSQL版)
2011/06/08 PHP
php加密解密实用类分享
2014/01/07 PHP
Thinkphp关闭缓存的方法
2015/06/26 PHP
php开发工具有哪五款
2015/11/09 PHP
激活 ActiveX 控件
2006/10/09 Javascript
Javascript 函数对象的多重身份
2009/06/28 Javascript
Jquery工作常用实例 使用AJAX使网页进行异步更新
2011/07/26 Javascript
JQuery UI的拖拽功能实现方法小结
2012/03/14 Javascript
ExtJS下 Ext.Direct加载和提交过程排错小结
2013/04/02 Javascript
在javascript中实现函数数组的方法
2013/12/25 Javascript
如何防止回车(enter)键提交表单
2014/05/11 Javascript
php,js,css字符串截取的办法集锦
2014/09/26 Javascript
vue 使用vue-i18n做全局中英文切换的方法
2018/10/29 Javascript
layui 实现table翻页滚动条位置保持不变的例子
2019/09/05 Javascript
VuePress 中如何增加用户登录功能
2019/11/29 Javascript
Vue 嵌套路由使用总结(推荐)
2020/01/13 Javascript
微信小程序canvas开发水果老虎机的思路详解
2020/02/07 Javascript
浅析TypeScript 命名空间
2020/03/19 Javascript
python操作数据库之sqlite3打开数据库、删除、修改示例
2014/03/13 Python
在Python中pandas.DataFrame重置索引名称的实例
2018/11/06 Python
python 函数的缺省参数使用注意事项分析
2019/09/17 Python
Python json模块与jsonpath模块区别详解
2020/03/05 Python
pytorch查看模型weight与grad方式
2020/06/24 Python
详解CSS3 Media Queries中媒体属性的使用
2016/02/29 HTML / CSS
大学毕业感言
2014/01/10 职场文书
奠基仪式主持词
2014/03/20 职场文书
岗位竞聘演讲稿范文
2014/04/24 职场文书
大学生个人求职信例文
2014/07/07 职场文书
学校班子个人对照检查材料思想汇报
2014/09/27 职场文书
办理信用卡工作证明
2014/09/30 职场文书
六一领导慰问欢迎词
2015/01/26 职场文书
内勤岗位职责范本
2015/04/13 职场文书
python使用pygame创建精灵Sprite
2021/04/06 Python