javascript是一门类java语言有很多跟java相类似的特点,但也仅是类似而已,真正使用中还是有很大的差别。this指针常常让很多初学者抓狂,本人也曾为此困惑不解,查找过很多资料,今天在这里总结一下,希望能帮助后来者更快驯服这只拦路虎。网上有很多讲解this指针的文章其中不乏精品,以我看来了解this指针关键在于掌握javascript中函数的四种调用模式。那么什么是调用?调用指的是跟在任何产生一个函数值的表达式之后使用"()",obj.f()这种方式成为调用,obj.f这种方式称为访问。

  一、方法调用模式:

  在该调用模式中函数作为一个对象的方法被调用:obj.fun()。当函数以此种形式被调用时this指针绑定到调用该方法的对象上即obj。

 var myObj = {
value: 0,
increase: function(){
this.value++;
console.log(this.value);
}
};
// this绑定到myObj对象上
myObj.increase(); // myObj2 = {
value: 10
};
myObj2.increase = myObj.increase;// myObj2与myObj的increase指向同一函数引用地址
// this绑定到myObj2对象上
myObj2.increase(); //

  所以在将一个html元素的某一事件绑定某一函数时,若函数中使用this指针,则this指针会被绑定到该元素上。

 var ele1 = document.getElementById('id');
ele1.addEventListener('click', myObj.increase, false);
// 该绑定相当于
ele1.onclick = myObj.increase;
// 事件触发时即相当于调用click方法
ele1.click(); // 与上文中myObj2.increase一个道理,若ele1中没有value属性则会报错

  二、函数调用模式:

  当函数没有当做方法调用即没有被一个对象通过点语法,这时它被当做一个函数来调用。以此模式调用函数时,this被绑定到全局对象。

 var value = -10;
var myObj = {
value: 0,
increase: function(){
this.value++;
console.log(this.value);
}
};
// this绑定到myObj对象上
myObj.increase(); // var gInc = myObj.increase;
gInc(); // -9 this绑定到window对象上

  所以在方法中使用内部函数时要特别注意,下例中other函数中的this并未绑定到myObj对象上

var value = -10;
var myObj = {
value: 0,
increase: function(){
this.value++;
console.log(this.value);
var other = function(){
this.value++;
console.log(this.value);
};
other();// -9, 这时other中的this绑定到window对象上
}
};
// this绑定到myObj对象上
myObj.increase(); // var gInc = myObj.increase;
gInc(); // -8
///////////////
//
//-9
//-8
//-7

  幸运的是我们可以使用以下方式来在other中访问myObj对象:

 var myObj = {
value: 0,
increase: function(){
this.value++;
console.log(this.value);
var that = this;
var other = function(){
that.value++;
console.log(that.value);
};
other();// -9, 这时other中的this绑定到window对象上
}
};
// this绑定到myObj对象上
myObj.increase(); //
//////////////
//
//

  作为浏览器兼容性中很重要的一条:element.attachEvent绑定事件方法,当该事件触发时this指针并未绑定到element对象上,而是绑定到了window对象上,原因在于IE中事件触发时,响应函数是以一个独立函数即函数调用模式来调用的

  三、构造器模式调用:

  如果在一个函数前面加上new调用则成为构造器模式调用。使用new运算符,会产生一个连接到该函数prototype的新对象,this指针则被绑定到这个新对象上。

 var P = function(n){
this.name = n;
}
P.prototype.getName = function(){
console.log(this.name);
}
var p = new P('woodtree'); // 这时P中的this对象呗绑定p指向的对象引用上
p.getName();// woodtree

  同时new运算符还会改变函数的返回值。以函数调用模式调用P即P()返回undefined,而通过new运算符则返回一个新对象。new运算符类似于以下Function.prototype.create函数:

 var P = function(n){
this.name = n;
}
P.prototype.getName = function(){
console.log(this.name);
}
var p = new P('woodtree');
p.getName(); Object.prototype.create = Object.create || function(proto){
var F = function(){};
F.prototype = proto;
return new F();
} Function.prototype.create = function(){
var that = object.create(this.prototype);
var obj = this.apply(that, arguments); return obj || that;
}
var p2 = P.create('hello new');
p2.getName(); // hello new

  四、apply、call模式调用:

  javascript中函数对象继承自Object亦可以拥有方法。call跟apply允许我们选择this的绑定对象。这两个方法的区别在于apply第二个参数必须是一个数组或者类数组对象即拥有length属性(arguments、NodeList、HTMLElementCollection等),而call除了第一个参数为要绑定this的对象外,后可跟无数的参数,参数之间用逗号间隔。

 var P = function(n){
this.name = n;
}
P.prototype.getNameAndAge = function(age){
console.log(this.name + age);
} P.prototype.getNameAndAge.call({
name: 'catboat'
}, 99);
P.prototype.getNameAndAge.apply({
name: 'lanuch'
}, [99]);

  通过使用apply与call方法我们可以自行实现ES5中的bind函数

 var P = function(n){
this.name = n;
}
P.prototype.getNameAndAge = function(age, age2){
console.log(this.name + age + age2);
} P.prototype.getNameAndAge.call({
name: 'catboat'
}, 99);
P.prototype.getNameAndAge.apply({
name: 'lanuch'
}, [99]); Function.prototype.bindContext = function(that){
var _method = this,
slice = Array.prototype.slice,
args = slice.call(arguments, 1); return function(){
_method.apply(that, Array.prototype.concat.apply(args, arguments));
}
}; var f1 = P.prototype.getNameAndAge.bindContext({
name: 'barque'
}, 88);
f1(9);

  同样我们也可以解决IE中事件触发时,this指针问题(以下代码来自《Javascript框架设计》):

 var addEvent = document.addEventListener ? function(el, type, fn, capture){
return el.addEventListener(type, fn, capture);
} : function(el, type, fn){
el.attachEvent('on' + type, fn.bindContext(el, event));
}

javascript中this指针探讨的更多相关文章

  1. javascript中this指针

    看完此片文章豁然开朗,非常感谢.javascript技术难点(三)之this.new.apply和call详解 下面说一说自己的理解: this指针总是指向调用他的对象,其实我更愿意理解为:this指 ...

  2. 图说js中的this——深入理解javascript中this指针

    没搞错吧!js写了那么多年,this还是会搞错!没搞错,javascript就是回搞错! ………… 文章来源自——周陆军的个人网站:http://zhoulujun.cn/zhoulujun/html ...

  3. javascript中this指针的认识

    javascript中上下文环境就是this指针,即被调用函数所处的环境.这个上下文环境在大多数情况下指的是函数运行时封装这个函数的那个对象:当不通过任何对象单独调用一个函数时,上下文环境指的就是全局 ...

  4. JavaScript中this指针指向的彻底理解

    this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象 这一点与函数中自由变量Action-varibal不同 var ...

  5. 彻底理解javascript中的this指针

    http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/ https://www.benn ...

  6. 由javascript中的this指针所想到的

    初次结识 this 指针,是在学 <<C++ Primer Plus>>这本书的时候(这本书勉强读了一二遍,之后转学 html+css+js了,不过这是后话). 依稀记得书中举 ...

  7. 深入认识JavaScript 中的this指针

    深入认识JavaScript 中的this指针this指针是面向对象程序设计中的一项重要概念,它表示当前运行的对象.在实现对象的方法时,可以使用this指针来获得该对象自身的引用.和传统意义的面向对象 ...

  8. 从函数调用的角度,探讨JavaScript中this的用法

    js函数调用方式大概可分为:函数调用,构造器调用,call或apply,方法调用四种方式.下面结合一些基础概念和实测代码,从函数调用的角度,探讨JavaScript中this的用法. 1. new对函 ...

  9. <javaScript>谈谈JavaScript中的变量、指针和引用

    1.变量我们可能产生这样一个疑问:编程语言中的变量到底是什么意思呢?事实上,当我们定义了一个变量a时,就是在存储器中指定了一组存储单元,并将这组存储单元命名为a.变量a的值实际上描述的是这组存储单元中 ...

随机推荐

  1. C# 抓取网站数据

    项目主管说这是项目中的一个亮点(无语...), 类似于爬虫一类的东西,模拟登陆后台系统,获取需要的数据.然后就开始研究这个. 之前有一些数据抓取的经验,抓取流程无非:设置参数->服务端发送请求- ...

  2. [11]APUE:(文件)记录锁

    [a] 概念 建议锁:在遵循相同记录锁规则的进程间生效,通常用于保证某个程序自身多个进程间的数据一致性 强制锁:意在保证所有进程间的数据一致性,但不一定有效:如不能应对先 unlink 后建立同名副本 ...

  3. .net/C# HttpWebRequest传送与接收参数

    public string PostData(string url, string data)//url:要发送到网站的地址 data:传送需要的参数 { HttpWebRequest myReque ...

  4. AspNetPager 免费分页控件7.5.1版发布!

    AspNetPager 免费分页控件7.5.1版发布,本次升级主要内容有: 修正了ShowDisabledButtons为false时html闭合标签丢失的bug:改为从System.Web.UI.W ...

  5. android书籍

    教程 源码下载 高薪招聘 Cocos2d-x 博客 签到 视频教程 wiki     帖子 搜索 热搜:二维码定时器手电筒滑块斗地主书架定位买手机聊天游戏开发游戏股票查询机顶盒通话记录二维码扫描振动器 ...

  6. 如何解决pycharm输入中文报错问题

    在pycharm中的python文件中输入中文会报错SyntaxError: 问题解决方法在文件开头添加 : # -*- coding:utf-8 -*- 每次添加都很麻烦,一劳永逸解决此问题的方法: ...

  7. spring aop一些名词的理解

    最近想深入了解spring,已经使用spring一段时间,但是对spring的理解一直很肤浅,先把几个常见的名词理解一下. 比如一个ssh架构的电商系统上面有用户模块,商品模块,订单模块,支付模块等, ...

  8. redis hash数据类型

    我们可以将Redis中的Hashes类型看成具有String Key和String Value的map容器.所以该类型非常适合于存储值对象的信息.如Username.Password和Age等.如果H ...

  9. linux split 命令 将一个大的文件拆分成若干小文件

    . 以行数拆分 -l 参数: 原始文件 拆分后文件名前缀 例:以50行对文件进行拆分 big.txt small_ 拆分后会生成 small_aa small_ab small_ac ... . 以大 ...

  10. springboot使用之二:整合mybatis(xml方式)并添加PageHelper插件

    整合mybatis实在前面项目的基础上进行的,前面项目具体整合请参照springboot使用之一. 一.整合mybatis 整合mybatis的时候可以从mybatis官网下载mybatis官网整合的 ...