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控制代码暂停的实现方法分享
Oct 11 Javascript
jQuery 遍历- 关于closest() 的方法介绍以及与parents()的方法区别分析
Apr 26 Javascript
浅谈JavaScript之事件绑定
Jul 08 Javascript
JS实现将人民币金额转换为大写的示例代码
Feb 13 Javascript
采用自执行的匿名函数解决for循环使用闭包的问题
Sep 11 Javascript
javascript封装 Cookie 应用接口
Aug 07 Javascript
实例讲解JavaScript中instanceof运算符的用法
Jun 08 Javascript
JQuery控制DIV的选取实现方法
Sep 18 Javascript
jQuery实现所有验证通过方可提交的表单验证
Nov 21 jQuery
实例解析Vue.js下载方式及基本概念
May 11 Javascript
详解如何在vscode里面调试js和node.js的方法步骤
Dec 24 Javascript
详解js创建对象的几种方法及继承
Apr 12 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
基于mysql的bbs设计(五)
2006/10/09 PHP
php下使用SMTP发邮件的代码
2008/01/10 PHP
php中实现简单的ACL 完结篇
2011/09/07 PHP
ThinkPHP Mobile使用方法简明教程
2014/06/18 PHP
ThinkPHP做文字水印时提示call an undefined function exif_imagetype()解决方法
2014/10/30 PHP
ThinkPHP类似AOP思想的参数验证的实现方法
2019/12/18 PHP
改善你的jQuery的25个步骤 千倍级效率提升
2010/02/11 Javascript
div+css+js实现无缝滚动类似marquee无缝滚动兼容firefox
2013/08/29 Javascript
解析Vue.js中的组件
2018/02/02 Javascript
nodejs简单读写excel内容的方法示例
2018/03/16 NodeJs
JavaScript中变量、指针和引用功能与操作示例
2018/08/04 Javascript
vue-cli 3.x 配置Axios(proxyTable)跨域代理方法
2018/09/19 Javascript
jQuery判断自定义属性data-val用法示例
2019/01/07 jQuery
electron-vue开发环境内存泄漏问题汇总
2019/10/10 Javascript
vuex入门最详细整理
2020/03/04 Javascript
webpack+vue-cil 中proxyTable配置接口地址代理操作
2020/07/18 Javascript
[02:12]Dota 2 推出全新英雄—— 电炎绝手
2019/08/23 DOTA
python字典键值对的添加和遍历方法
2016/09/11 Python
Python实现调用另一个路径下py文件中的函数方法总结
2018/06/07 Python
简单了解python反射机制的一些知识
2019/07/13 Python
PYTHON发送邮件YAGMAIL的简单实现解析
2019/10/28 Python
Python自动化完成tb喵币任务的操作方法
2019/10/30 Python
使用Python实现画一个中国地图
2019/11/23 Python
美国五金商店:Ace Hardware
2018/03/27 全球购物
印度化妆品购物网站:Nykaa
2018/07/22 全球购物
Feelunique德国官方网站:欧洲最大的在线美容零售商
2019/07/20 全球购物
手工制作的意大利皮革运动鞋:KOIO
2020/01/05 全球购物
电子商务专业自荐信
2014/06/02 职场文书
代理人委托书
2014/08/01 职场文书
四川省传达学习贯彻党的群众路线教育实践活动总结大会精神新闻稿
2014/10/26 职场文书
2014年收银工作总结
2014/11/13 职场文书
教学督导岗位职责
2015/04/10 职场文书
杨善洲电影观后感
2015/06/04 职场文书
教你利用python实现企业微信发送消息
2021/05/23 Python
MySQL 主从复制数据不一致的解决方法
2022/03/18 MySQL
Go本地测试解耦任务拆解及沟通详解Go本地测试的思路沟通的重要性总结
2022/06/21 Golang