介绍

  this在各种对面对象编程中起着非常重要的作用,主要用于指向调用的对象。不过在JavaScript中,this的表现存在很大差异,特别是不同执行上下文。

由前文我们知道this也是属于执行上下文中的一个属性,所有它命中注定和执行上下文脱不了干系。

activeExecutionContext = {VO: {...},this: thisValue

};

  在Javascript中,this的取值取决于调用的模式。调用模式一共有四种:方法调用模式、函数调用模式、构造器调用模式和apply调用模式。

调用模式

  方法调用模式

   当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象,即方法调用模式中的this指向调用对象。这个理解起来非常容易,你是我的一个方法,你属于我,你的this当然指向我啦。

var myObject = {value : 0,increment : function(inc) {this.value += typeof inc === "number" ? inc : 1;}
}
myObject.increment();
console.log(myObject.value);  //输出:1
myObject.increment(3);
console.log(myObject.value);   //输出:4

  因为可以通过this访问到自己所属的对象,所有可以通过它调用和修改对象中属性或者方法。由前文可知,this作为执行上下文中属性的一员,必然是在上下文创建时才创建,所有this到对象的绑定发生在调用的时候,这属于“延迟绑定”。通过延迟绑定可以实现对this的高度复用。

function showValue(){console.log(this.value);
}
var a = { value : "a"};
var b = { value : "b"};
a.showValue = showValue;
b.showValue = showValue;
a.showValue();  //输出“a”
b.showValue();  //输出“b”

上例中函数showValue就属于延迟绑定。

  函数调用模式

  当一个函数并非作为一个对象的方法来调用,这时就是函数调用。函数调用模式中,this被绑定到全局对象。(这是语言设计上的一个错误)

1 myObject.double = function(){
2     var that = this;   //解决方法
3     var helper = function(){
4         console.log(that, ": ", that.value); //输出 Object {value: 4, increment: function, double: function} ": " 4
5         console.log(this, ": ", this.value); //输出  Window {top: Window, window: Window…} ": " undefined
6     }
7
8     helper(); //以函数形式调用
9 }

  按照正常思路,应该如第四行所输出那样,this指向函数所属对象,可是由于语言设计上面的问题导致this指向的却是全局对象。这个更是让this变得神秘,令人捉摸不透。但是作为开发者,这种情况肯定是我们所不愿意见到的,不按常理出牌这是,还好补救措施也很简单,就是上例中用that指代this。这样,在helper方法中调用that就可以当this使用,简单方便。至于函数调用模式为什么this会这样,后面在分析引用类型时会详加说明。

  构造器调用模式

  由于javascript是基于原型继承,但是它的设计者又想要它能像传统的面向对象语言那样能通过new和构造函数创建对象,现实面向对象编程。这个貌似不是什么好的构想,有点画虎不成反类犬的尴尬。一是学不来,而是没必要学。javascript的原型继承机制已经非常强大,足以满足面向对象所需的继承多态。

  闲话少叙,还行言归正传说说构造器调用模式。构造器调用模式这个非常简单,它就是就一个函数当做构造器,然后将你打算公用的属性和方法用this引进声明。如下

function Person(name, age){this.name = name;this.age = age;this.say = function(){console.log("name : %s, age : %n", this.name, this.age);}
}var p1 = new Person("jink", 24);
p1.say(); //输出  name : jink, age : 24var p2 = new Person("张三", 33);
p2.say();//输出  name : 张三, age : 33

  上面例子我们可以清楚看出,this是指向通过new和构造函数创建的对象。为什么会这样?这是因为在javascript中通过new调用构造函数时,new运算符调用“Person”函数的内部的[[Construct]] 方法,接着,在对象创建后,调用内部的[[Call]] 方法。 所有相同的函数“Person”都将this的值设置为新创建的对象。

  apply调用模式

  javascript中所有函数创建之后,都会自带两个方法:apply和call。这两个方法的的具体使用,我在此就不想详细说明,不知道的同学可以百度一下,挺简单的。通过两个方法,我们可以手动设置this。虽然this在创建时候是不允许修改的,但是,我们在创建之前,手动设置过,那就是另外一回事了。这一设置,可不得了,你就可以让你的对象调用任意方法,就好像你可以让汽车大海中航行,非洲象如美洲豹一样飞驰,程序员像钢琴师一样弹奏。哈哈想象总是美好的,调用归调用,但是调用了能不能实现功能就另说了。

var programmer = { name : "程序员",hand : "灵活的双手", programme : function(){ console.log(this.name+"用"+this.hand+"编写代码。");}
}var pianist = { name : "钢琴家",hand : "灵活的双手", play : function(){ console.log(this.name+"用"+this.hand+"弹奏动听的乐曲。");}
}var player = { name : "运动员",foot : "矫健的双腿", run : function(){ console.log(this.name+"用"+this.foot+"在赛场奔驰。");}
}//循规蹈矩
programmer.programme(); //程序员用灵活的双手编写代码。
pianist.play(); //钢琴家用灵活的双手弹奏动听的乐曲。
player.run(); //运动员用矫健的双腿在赛场奔驰。
//异想天开
pianist.play.apply(programmer); //程序员用灵活的双手弹奏动听的乐曲。
player.run.apply(programmer); //程序员用undefined在赛场奔驰。   由于自身运动缺少,没有矫健的双腿

上面看着是不是挺有意思的,apply的第一个参数就是执行方法中的this指向。这样我们就可以借用别人的方法自己私下偷偷的用,可谓方便至极。在一些框架中经常用的此类技巧。

总结

  关于this就说这么多,相信大家看过之后,对在不同情境中this的判定都有些了解了,本来打算讨论接下来讨论引用对象的,阐述一下方法调用模式和函数调用模式中this取值的原理,但害怕篇幅过长,所以决定用单独一章向大家分析一下引用对象这个概念。

转载于:https://www.cnblogs.com/jink/p/3475758.html

Javascript浅谈之this相关推荐

  1. JavaScript 浅谈DOM节点层次:Text /Coment等类型

    浅谈DOM其他节点层次:Text .Coment. 一.Text类型--文本 Text类型表示纯文本内容,其特性有 nodeType == 3  ;  nodeName == "#text& ...

  2. 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6621566 上一篇文章Android进程间通信(IPC)机制Binder简要介绍和学 ...

  3. 浅谈javascript中原型(prototype)、构造函数、对象实例及三者之间的关系

    转自:http://www.cnblogs.com/zhangwei412827/archive/2012/12/14/2816263.html 浅谈javascript中原型(prototype). ...

  4. 浅谈JavaScript作用域,关于Java的学习路线资料

    javascript是目前web领域中使用非常广泛的语言,不管是在前端还是在后端都能看到它的影子,可以说web从业者不论怎样都绕不开它.在前端领域,各种框架层出不穷.在后端领域,nodejs可谓如火如 ...

  5. javascript数组浅谈1

    最近心血来潮要开始玩博客了,刚好也在看数组这块内容,第一篇就只好拿数组开刀了,自己总结的,有什么不对的地方还请批评指正,还有什么没写到的方面也可以提出来我进行完善,谢谢~~ 首先,大概说说数组的基本用 ...

  6. 老姚浅谈:怎么学JavaScript?

    大家好,我是若川.当初我就是看本文深受启发,开始看书读源码.所以现在联系了作者@老姚 授权转载分享给大家.我按照文中的做法敲完了<JavaScript语言精粹 修订版>,在2017年7月2 ...

  7. python封装继承多态_浅谈JavaScript的面向对象和它的封装、继承、多态

    写在前面 既然是浅谈,就不会从原理上深度分析,只是帮助我们更好地理解... 面向对象与面向过程 面向对象和面向过程是两种不同的编程思想,刚开始接触编程的时候,我们大都是从面向过程起步的,毕竟像我一样, ...

  8. 浅谈 JavaScript 编程语言的编码规范--转载

    原文:http://www.ibm.com/developerworks/cn/web/1008_wangdd_jscodingrule/ 对于熟悉 C/C++ 或 Java 语言的工程师来说,Jav ...

  9. JavaScript 中的 require / exports、import / export、浅谈JavaScript、ES5、ES6

    Node.js 的基础教学 之 exports 和 module.exports:https://zhuanlan.zhihu.com/p/82057593 浅谈 JavaScript.ES5.ES6 ...

最新文章

  1. (shell脚本编程)linux如何利用脚本执行多条命令以及linux如何执行定时任务
  2. java switch小程序,小程序自定义switch组件
  3. java启动scrapy爬虫,爬虫入门之Scrapy 框架基础功能(九)详解
  4. 初次就这么给了你(Django-rest-framework)
  5. 如何在Spring中将@RequestParam绑定到对象
  6. WCF系列(1)—— CustomBehavior 入门
  7. java作业 计算平均分和总成绩
  8. SpringCloud系列-Feign的基本应用
  9. 2018ACM上海大都会赛: A. Fruit Ninja(这绝对是道原题+随机)
  10. 人脸方向学习(十二):Face Detection-Tiny-DSOD解读
  11. 计算机程序试题答案,历年计算机软考程序设计模拟试题及答案
  12. Shufflenet解读
  13. webpack ——自定义Loader,将i18n英文单词首字母转大写
  14. tomcat+mysql+腾讯云_腾讯云服务器配置tomcat和mysql
  15. Android仿苹果电量显示
  16. qt emit是什么意思_2020年12月12日 无赞赏QT吗哪 :如天上的星星永远发光的信仰...
  17. 网站排名优化快排SEO网站源码
  18. 钉钉小程序快照技术初窥
  19. 图像处理实验,中值滤波处理椒盐噪声
  20. 【PAT乙级】1031 查验身份证

热门文章

  1. 期货品种产业链图表_工业
  2. 量化策略回测TRIXKDJ
  3. 【必备干货】1000字讲清3大财务数据表
  4. 再复杂的报表,用这3种方式,都能解决!
  5. python 动态类型性能_动态且强类型的Python
  6. python获取当前日期的前一天爆炸_python蒙特卡洛脚本模拟—挑战者号爆炸概率
  7. python字符串format和center居中应用(三分钟读懂)
  8. android 崩溃日志捕获,安卓Java崩溃的捕获和日志记录
  9. nvidia的jetson系列的方案_NVIDIAJetson系统在工业网络中的集成
  10. 在html中定位属性怎么用,CSS元素定位的使用方法