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 相关文章推荐
javascript表单验证 - Parsley.js使用和配置
Jan 25 Javascript
Js放到HTML文件中的哪个位置有什么区别
Aug 21 Javascript
一个简单的jquery的多选下拉框(自写)
May 05 Javascript
jQuery窗口、文档、网页各种高度的精确理解
Jul 02 Javascript
JS+CSS实现六级网站导航主菜单效果
Sep 28 Javascript
网页中JS函数自动执行常用三种方法
Mar 30 Javascript
原生js实现网页顶部自动下拉/收缩广告效果
Jan 20 Javascript
JS中的phototype详解
Feb 04 Javascript
JS module的导出和导入的实现代码
Feb 25 Javascript
使用PreloadJS加载图片资源的基础方法详解
Feb 03 Javascript
js实现页面导航层级指示效果
Aug 25 Javascript
idea编译器vue缩进报错问题场景分析
Jul 04 Vue.js
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/10/09 PHP
如何使用PHP Embed SAPI实现Opcodes查看器
2015/11/10 PHP
PHP图片裁剪与缩放示例(无损裁剪图片)
2017/02/08 PHP
jquery中ajax学习笔记4
2011/10/16 Javascript
js取消单选按钮选中示例代码
2013/11/14 Javascript
深入理解Javascript中this的作用域
2014/08/12 Javascript
全面解析Bootstrap手风琴效果
2020/04/17 Javascript
浅谈js的url解析函数封装
2016/06/28 Javascript
jQuery实现两列等高并自适应高度
2016/12/22 Javascript
利用NPM淘宝的node.js镜像加速nvm
2017/03/27 Javascript
微信小程序 Buffer缓冲区的详解
2017/07/06 Javascript
zTree异步加载展开第一级节点的实现方法
2017/09/05 Javascript
Bootstrap popover 实现鼠标移入移除显示隐藏功能方法
2018/01/24 Javascript
详解react、redux、react-redux之间的关系
2018/04/11 Javascript
详解javascript中的变量提升和函数提升
2018/05/24 Javascript
在Vue 中使用Typescript的示例代码
2018/09/10 Javascript
详解nuxt路由鉴权(express模板)
2018/11/21 Javascript
ES7之Async/await的使用详解
2019/03/28 Javascript
express中static中间件的具体使用方法
2019/10/17 Javascript
JavaScript遍历数组的方法代码实例
2020/01/14 Javascript
vue跳转页面的几种方法(推荐)
2020/03/26 Javascript
js中调用微信的扫描二维码功能的实现代码
2020/04/11 Javascript
JS如何监听div的resize事件详解
2020/12/03 Javascript
一个小示例告诉你Python语言的优雅之处
2014/07/04 Python
Python实现的圆形绘制(画圆)示例
2018/01/31 Python
深入浅析Python中list的复制及深拷贝与浅拷贝
2018/09/03 Python
Python UnboundLocalError和NameError错误根源案例解析
2018/10/31 Python
PyTorch搭建多项式回归模型(三)
2019/05/22 Python
pytorch神经网络之卷积层与全连接层参数的设置方法
2019/08/18 Python
From CSV to SQLite3 by python 导入csv到sqlite实例
2020/02/14 Python
使用Keras构造简单的CNN网络实例
2020/06/29 Python
html5实现的便签特效(实战分享)
2013/11/29 HTML / CSS
澳大利亚购买太阳镜和眼镜网站:Glamoureyes
2020/09/22 全球购物
一名毕业生的自我鉴定
2013/12/04 职场文书
《植树问题》教学反思
2016/03/03 职场文书
Python面试不修改数组找出重复的数字
2022/05/20 Python