人们对于this的绑定常常有两个误解,一:指向函数本身,二:指向函数作用域。这两种想法都是错的,this并不指向函数本身,也不指向函数作用域。

function  foo(){
this.count++;
}
foo.count = 0;
for(var i = 0 ; i<5 ; i++){
foo();
}
alert( foo.count ); //

因为this不指向函数本身,所以foo.count的值依然是0。

function foo(){
var a = 1 ;
alert(this.a);
}
var a = 2;
foo(); //

因为this不指向函数作用域,所以输出的是2。

this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

this的绑定一共有四种绑定:1:默认绑定(即没有明确的调用对象)

2:隐性绑定(即作为对象方法调用,this会被绑定到该对象)

3:显性绑定(使用apply()和call()调用,两个方法的第一个参数为一个对象,this被绑定到该对象)

4:new绑定(使用new来调用函数,会构造一个新对象,并且把this绑定到该对象)

一:默认绑定   (即没有明确的调用对象)   

function foo(){
var a = 1 ;
alert(this.a);
}
var a = 2;
foo(); // 2 (非严格模式下)

没有明确调用对象,this会被绑定到window对象,所以this.a就是window.a,即为2。不过这得在非严格模式下,只有在非严格模式下this才会被绑定到window对象,而在严格模式下,this被绑定到undefined。

 二:隐性绑定   (即作为对象方法调用,this会被绑定到该对象)

function  foo(){
var a = 1;
alert(this.a);
}
var obj = {
a:2,
foo:foo
};
obj.foo(); //

obj对象调用foo()函数,this被绑定到obj对象,所以输出了obj对象的a的值2。

对象属性引用链中只有最后一层会影响调用位置

function  foo(){
alert(this.a);
}
var obj2 = {
a:2,
foo:foo
};
var obj1 = {
a:1,
obj2:obj2
};
obj1.obj2.foo(); //

obj1和obj2两个对象连续调用,this会被绑定到最后一个对象,即obj2,所以输出2

隐式丢失:被隐式绑定的函数会丢失绑定对象,有两种情况会丢失,一种为引用,另一种为回调函数。

         引用:

function  foo(){
alert(this.a);
}
var obj = {
a:1,
foo:foo
};
var bar = obj.foo;
var a = "global 1";
bar(); //global 1

bar是obj.foo的一个引用,实际上它引用的是foo函数本身,所以this被绑定到window对象,输出的是"global 1"

回调函数:

function    foo(){
alert(this.a);
}
function doFoo(fn){
fn();
}
var obj = {
a = 1,
foo:foo
}
var a = "global 1";
doFoo(obj.foo); //"global 1"

    调用回调函数的函数可能会修改this

 三:显性绑定(使用apply()和call()调用,两个方法的第一个参数为一个对象,this被绑定到该对象) 

function  foo(){
alert(this.a);
}
var obj = {
a:1
};
foo.call(obj); //

call()的参数若为空,默认调用window对象,若为一个原始值(字符串类型,布尔类型或者数字类型),则这个原始值会被转换成它的对象形式(new  String(),new Boolean() 或者 new Number()),这被称为“装箱”

硬绑定———显示绑定的一种变形

            优点:可以解决丢失绑定问题

缺点:硬绑定后不可能再修改它的this   

function  foo(){
alert(this.a);
}
var obj = {
a:2
};
var bar = function(){
foo.call(obj);
};
bar(); //
setTimeout(bar,100); //
bar.call(window); //

 ES5中提供了内置方法Function.prototype.bind

function foo(something){
alert(this.a, something);
return this.a + something;
}
var obj = {
a:2
};
var bar = foo.bind(obj);
var b = bar(3); // 2 3
alert(b); //

bind()会返回一个硬编码的新函数,它会把参数设置为this的上下文并调用原始函数

四:new绑定(使用new来调用函数,会构造一个新对象,并且把this绑定到该对象)

function   foo(a){
this.a = a;
}
var bar = new foo(2);
alert(bar.a); //

this绑定的四条规则的优先级: new绑定  >  显示绑定  >  隐式绑定   >  默认绑定

js中this的绑定的更多相关文章

  1. js中的前绑定和后绑定详解

    这篇文章详细介绍了js中的前绑定和后绑定,有需要的朋友可以参考一下 其主要意思就是看我有没有用过前绑定,即Dom树中的某些元素在还没有创建出来时,就指定该类型的元素一出生就应该拥有的某些事件.在实际开 ...

  2. js中this的绑定规则及优先级

    一.   this绑定规则 函数调用位置决定了this的绑定对象,必须找到正确的调用位置判断需要应用下面四条规则中的哪一条. 1.1 默认绑定 看下面代码: function foo() { cons ...

  3. js中同一个onclick绑定了两个js方法出现的问题

    问题: js中如果同一个onclick绑定了两个js方法问题,即 <li onclick="f1(),f2()"></li> 两个方法f1,f2中都分别有一 ...

  4. js中的事件绑定的三种方式

    1 直接在html标签中绑定 <button onclick = "show()"></button> 注意当你引用的js代码是包裹在window.onlo ...

  5. 关于js中对事件绑定与普通事件的理解

    普通事件指的是可以用来注册的事件: 事件绑定是指把事件注册到具体的元素之上. 通俗点说: 普通事件:给html元素添加一个特定的属性(如:onclick): 事件绑定:js代码中通过标记(id  ta ...

  6. JS 中的事件绑定、事件监听、事件委托

    事件绑定 要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数.所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称. 在JavaScript中,有 ...

  7. js中传统事件绑定模拟现代事件处理

    大家都知道,IE中的现代事件绑定(attachEvent)与W3C标准的(addEventListener)相比存在很多问题, 例如:内存泄漏,重复添加事件并触发的时候是倒叙执行等. 下面是用传统事件 ...

  8. JS 中的事件绑定、事件监听、事件委托是什么?

    在JavaScript的学习中,我们经常会遇到JavaScript的事件机制,例如,事件绑定.事件监听.事件委托(事件代理)等.这些名词是什么意思呢,有什么作用呢? 事件绑定 要想让 JavaScri ...

  9. JS中的事件绑定,事件捕获,事件冒泡以及事件委托,兼容IE

    转载请注明出处:http://www.cnblogs.com/zhangmingze/p/4864367.html   ● 事件分为三个阶段:   事件捕获 -->  事件目标 -->   ...

随机推荐

  1. GitHub iOS-Top 100 简介

    GitHub排名前100的iOS第三方汇总简介,方便开发者选择适合的第三方框架. 项目名称 项目信息 1. AFNetworking 作者是 NSHipster 的博主, iOS 开发界的大神级人物, ...

  2. python 邮件基础篇

    python 操作邮件,不是很方便,说实话还不是理解的特别透彻,这次想把自己碰到的东西总结下来 邮件有imap,pop,imap协议,这次使用的是imap4协议,主要用了imap4和mail类, 代码 ...

  3. 基于redis实现可靠的分布式锁

    什么是锁 今天要谈的是如何在分布式环境下实现一个全局锁,在开始之前先说说非分布式下的锁: 单机 – 单进程程序使用互斥锁mutex,解决多个线程之间的同步问题 单机 – 多进程程序使用信号量sem,解 ...

  4. 无法在“EntityFramework”已存在的情况下创建影像复制该文件的解决方案

    问题产生的原因:你项目正在生成中你就打开浏览器预览了,导致这个问题解决方案:右击重新生成项目,等生成后再打开 “/”应用程序中的服务器错误. 无法在“EntityFramework”已存在的情况下创建 ...

  5. JSDeferred 源码分析

    不经意看到了一个构思非常惊人的异步流程控制库,发出来分享下 http://cho45.stfuawsc.com/jsdeferred/ 关于CommonJS Promises请看另一个异步库 http ...

  6. iOS开发之手势识别

    感觉有必要把iOS开发中的手势识别做一个小小的总结.在上一篇iOS开发之自定义表情键盘(组件封装与自动布局)博客中用到了一个轻击手势,就是在轻击TextView时从表情键盘回到系统键盘,在TextVi ...

  7. geotrellis使用(十四)导出定制的GeoTiff

    Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html 目录 前言 需求说明 实现方案 总结 一.前言        最 ...

  8. MongoDB-基础-limit-skip-sort

    MongoDB Limit() 方法 如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的 ...

  9. 代码片段添加智能提示,打造一款人见人爱的ORM框架

    SqlSugar ORM优点: 1.高性能,达到原生最高水准,比SqlHelper性能要高,比Dapper快30% 比EF快50% 2.支持多种数据库 ,sql版本更新最快,其它会定期更新,可以在多种 ...

  10. sql server实现自定义分割月功能

    本文目录列表: 1.为何出现自定义分割月需求 2.sql server实现自定义分割月功能 3.测试验证效果 4.总结语 5.参考清单列表   1.为何出现自定义分割月的需求   今天梳理一个平台的所 ...