1.关于this的误会。

  误会(1):this指向所在函数本身。

    我们常常会对this产生各种误会,比如说我们可能认为this会指向所在函数本身,但实际上并非如此。

  

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

    上面的例子旨在使用函数的this指向this,通过foo函数的count属性计算foo被调用的次数。根据这个目的,输出应该是5,因为for循环了五次,foo函数被调用了5次。但实际上呢?

    我们新建一个js文件,命名为test.js,代码如下:

    实际输出如下:

    输出的foo.count值为0。看上去foo中的this并没有指向foo,那么this指向了哪里呢?

  

    通过chrome JavaScript调试器可以发现,this指向了window全局作用域,并没有如我们预期的指向foo本身。

  误会(二):this指向函数所在作用域

    通过上面的例子,可能你很快就能得出结论:this指向所在函数所在的作用域。比如上一个例子中,函数foo位于全局作用域(在宿主环境中就是window),foo中的this便指向了全局作用域,但是果真如此吗?

    

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

    上面的代码,旨在foo内部,声明一个bar函数用于控制foo作用域内的count变量,实现计算bar被调用次数的功能。理论上,bar函数中的this应该会指向bar所在的作用域,所以this也可以调用count(和bar函数同作用域),应该输出为5。但实际输出呢?

    实际输出仍然为0!说明this根本没有指向bar所在的作用域,那么this指向哪了呢?

    实际上,this还是指向了window作用域,真是非常神奇。

    要想了解this的工作方式,我们先了解一下this的绑定方式。

2.this的绑定规则

   (1)默认绑定

      当函数独立调用时,这条规则就是无法应用其他规则时的默认规则。

       直接使用不带任何修饰的函数,this会指向全局环境。

        

 function foo (){
this.count = 100;
}
foo(); //直接使用,函数未经修饰
console.log(window.count); //输出全局环境中的count变量,就是函数中的this.count,结果为100

        但是this不总是指向全局环境,当使用严格模式时,this会被禁止指向全局环境。

 function foo (){
"use strict"; //使用严格模式
this.count = 100;
}
foo();
console.log(window.count); //输出:Uncaught TypeError: Cannot set property 'count' of undefined

    (2)隐式绑定:

      

 function foo (){
console.log(this.count);
}
var obj = {
count:100,
foo:foo
};
obj.foo(); //输出100

        当所调用的函数是某个对象的成员函数时,函数中的this会指向函数所在的对象。

        隐式绑定可能会存在绑定丢失的场景,当函数作为参数传入到另外一个函数时,作为参数的函数所绑定的this会失效。

 function foo(){
console.log(this.count);
}
function bar (func){
func();
}
var count = 0;
var obj = {
count : 100,
foo : foo
};
bar(obj.foo); //会输出0

        如上例,当obj.foo作为参数传入到函数bar时,原来绑定的this指向obj被修改为指向全局变量window。所以使用回调函数,可能会修改传入参数函数的this指向。

    (3)显式绑定

       使用call()或者apply()函数可以显式强制的绑定函数的this。

        

function foo (){
console.log(this.count);
}
var count = 'window!';
var obj1 = {
count : 100,
foo : foo
};
var obj2 = {
count : 200,
foo : foo
};
foo.call(obj1); //输出100
foo.call(obj2); //输出200

        如上例所示,call两次修改了foo的this指向。使其指向某个固定的对象。当call的传入的第一个参数为null时,所修改函数的this指向不会被显式修改。

     (4)new 绑定

         使用new操作符,可以将函数的this指向新创建的对象。

       

function Foo(name, age){
this.name = name;
this.age = age;
}
var obj = new Foo('Tom',99);
console.log(obj);

        输出如下:

          新构建的obj对象具有了一系列属性,都是用函数Foo中的this所实现。

        通过这个原理,我们可以简单的实现一个_new_函数,以实现new操作符的功能。

         

function _new_ (func , arr){
var obj = {};
func.apply(obj,arr);
return obj;
}
function Foo (name, age){
this.name = name;
this.age = age;
}
var obj = _new_(Foo,['Jerry',99]);
console.log(obj);

        输出的obj如下:

        说明基本的传参构造对象功能已经实现了。

3.四种绑定规则的优先级

    new绑定 > 显示绑定 >隐式绑定 > 默认绑定

    判断this绑定的顺序:

      1.判断是否是new调用,是的话就是new绑定,函数中的this会指向新构造的对象。

          2.判断是否是显示绑定,即是否是通过函数原型中的apply方法或者call方法调用 (还要注意bind返回的函数,this指向也会被修改)。

          3.判断是否是隐式绑定,及通过某个对象调用。是的话,this会指向所属对象。

          4.如果都没有的话,就是默认绑定,this指向全局对象window;严格模式下指向undefined。

……更过this相关,有待补充,如有错误,欢迎指正!

  

最新文章

  1. ubuntu下mysql使用方法
  2. Bash:-:-获取未来40天的日期
  3. js一个抽奖的例子
  4. hiho一下 第一百零七周 Give My Text Back(微软笔试题)
  5. NS2中trace文件分析
  6. 深入理解 Javascript 面向对象编程
  7. .NET书籍推荐
  8. hdu 4652 Dice 概率DP
  9. javasctipt显示几分钟前、几天前等
  10. ios 限制输入长度
  11. 单服务器防护linux iptables脚本
  12. CodeIgniter框架文件结构
  13. cardview和Palette,ActionBar颜色随图改变
  14. PHP秒杀系统-高并发高性能的极致挑战
  15. linux(centos)常用命令
  16. Java开源生鲜电商平台-订单抽成模块的设计与架构(源码可下载)
  17. mysql 关联表修改数据
  18. SFTPUtils工具类及使用
  19. Git误操作 git reset强制回滚 恢复commit方法
  20. English trip -- VC(情景课)10 C I like to watch TV. 我爱看电视

热门文章

  1. DNS劫持和DNS污染
  2. Python 2.7.9 Demo - 003.01.只允许相同缩进
  3. Freemarker-2.3.22 Demo - No01_获取模板并直接输出
  4. 原始tab栏切换
  5. configure new Linux/Mac
  6. Python中的相对文件路径的调用
  7. java 多线程6: 中断机制 优雅的终止java线程
  8. 加载jquery主函数的两种方式
  9. [转]C#读取Word指定页的内容
  10. scala实现彩票算法