在web项目中Javascript是一门必须要掌握的动态语言,基于Javascript的框架大多离不开不了最基础的Javascript的用法和原理。本文主要是总结一下Javascript中那万恶的this关键字。

开门见山,抛出一个观点:“Javascript中this永远是指向调用它的对象”。下面我会举3个最有代表性的例子来验证我的这个观点。

例一 对象方法调用

    var x = 1;
  function testThis(){
    console.log(this.x);
  } testThis(); // 这里声明了一个全局变量x,一个全局方法,这两个对象都绑定在Window上,所以当运行testThis()的结果就是取Window对象上的x成员,结果是1   var o={};
  o.x = 5;
  o.method = testThis; o.method(); // 此时,我们讲o对象的method指向了testThis, 当调用它的时候,this指向调用他的对象,这是x就是去o对象的x,结果是5

这个例子十分基础,也就是常见的对象调用方法的时候,方法里面的this就是指向调用他或者是拥有他的对象

例二 构造函数创建

    var x = 2;
  function test(){
    this.x = 1;
  }   var o = new test();
  console.log(o.x); // //这就是javascript中的构造函数,通过new来创建一个实例,这里取的值是绑定在对象o里面的x,所以是1 //下面这个例子是Angular中的Service,你可以直接理解成他会通过第二个参数new一个单例对象
app.service("MyService", function ($http, $modal) {
this.test = function() {
console.log(this);
test2();
} function test2() {
console.log(this)
}
} MyService.test() // 打印 MyService {test: function} 和 Window {} //这里log出来虽然test2()可以被test1()调用,但它其实并不属于Service, 所以如果test2里面调用this,就会出现常见的错误,哎呀妈呀,咋调不了自己的方法?!

这个例子我们项目中经常出现,而且很难解释清楚,就像还有人问我为什么controller中不直接使用this,而是要用$scope来绑定方法和变量,当然用this能够取代部分$scope,但是难免遇到this的上下文不同引起的一系列问题。这个问题的关键就是test2方法并不属于对象Service,但是由于在service闭包(closure)里面,他可以被Service调用,所以test2里面的this就不是指向Service,从而调用Service里面的其他方法就会报错。

例三 改变this指向

  function test(){
    console.log(this.x);
  }
  var o={};
  o.x = 1;
  o.m = test;   o.m.apply({x:5}); //
o.m.call() // undefined //通过apply/call来指定调用函数的this作用上下文,都是指用参数对象来调用o对象的函数,默认参数是Global

其实通过这个例子,大家就已经可以看到this的指向是不确定的,this值在进入上下文时确定,并且在上下文运行期间永久不变。上面的例子改变this的上下文,导致两次结果不一致也是最好的证据。

最后

本文最大的作用就是如果看完本文你能够理解this为什么有时候会跟自己期望不一样,而且能得到一个避免这样问题发生的解决方案,那我的目的就达到了。很幸运你能看到这里,解决方案呈现给大家:就像Angular要将属性和方法给你提供一个$scope来绑定属性,也像coffeeScript会在对象一开头有这么个赋值“ _this = this”,我们在自己的js实践中不妨定义"val self = this",在之后的作用域里面用self来操作对象的属性,这是解决之道。

最新文章

  1. nodejs:连接数据库SqlServer,mssql模块
  2. 解决Scala Play框架在Git Bash运行的异常:Could not find configuration file ../framework/sbt/sbt.boot.properties
  3. R语言中判断是否是整数。以及读写excel
  4. [Jobdu] 题目1527:首尾相连数组的最大子数组和
  5. Kinect For Windows V2开发日志三:简单的深度读取
  6. 关于T公司的强矩阵架构的思考
  7. MYSQL 磁盘临时表和文件排序
  8. md笔记——微信JS接口
  9. 1.Why Apache Spark?
  10. Win10 UWP Intro to controls and events
  11. mybatis 一对一关联映射实例
  12. 团队作业4——第一次项目冲刺(Alpha版本) Day 2
  13. Python并发编程的几篇文章
  14. SQL Server 动态掩码
  15. 电子产品使用感受之——为什么我把Apple Watch S2 升级到了 S4?
  16. vmware-tools安装——实用
  17. CentOS7的网卡重启方法
  18. Linux-03
  19. Linux---一级/二级目录以及位置目录名/指令
  20. day28 面向对象:反射,内置函数,类的内置方法

热门文章

  1. 【转】 如何利用C#代码来进行操作AD
  2. e653. 写入段落文本
  3. 您可以从 Windows 命令行上运行 gcc、g++、ar、ranlib、dlltool 和其他一些 GNU 工具
  4. 说说自己对hibernate一级、二级、查询、缓存的理解。
  5. 【AngularJS】AngularJS整合Springmvc、Mybatis环境搭建
  6. 使用_snscanf_s转换十六进制时引起的内存越界
  7. CentOS查看登录用户以及踢出用户
  8. MySQL Date函数的正确用法
  9. OpenGL介绍
  10. js中以键值对的形式当枚举