javascript中this的指向问题(一)

来源:互联网 发布:日本为何没人篡位知乎 编辑:程序博客网 时间:2024/06/14 11:14

最近看《你不知道的js(上卷)》关于this的个人理解加总结:

这本书对于我理解this真的起到了非常大的作用,,,以前看的比较杂乱。。摁,感觉现在很清晰。摁,废话了。

文中有不少自己的话描述的部分,有不对的地方还请批评指正。



首先,this的绑定跟调用位置是有非常大的关系的。

然后,重点来了。。


this的绑定对象有四大种情况:

一、默认绑定

二、隐式绑定

三、显示绑定

四、new绑定



一、默认绑定:通过独立函数调用。

function foo() {
    console.log(this.a);
}
var a=2;
foo();//2

需要注意的有几点:
1、声明在全局作用域中的变量就是全局对象的一个同名属性(例如,本例中var a=2;即window.a=2);
2、foo是直接使用不带任何修饰的函数引用进行调用的,因此只能是默认绑定。
3、如果使用严格模式(strict mode),则不能将全局对象用于默认绑定,因此this会绑定到undefined。
      关于第3点举例如下:

function foo() {
    "use strict";
    console.log(this.a);
}
var a=2;
foo();
该代码段输出结果如下:

       






   但是,

   function foo() {        console.log(this.a);    }    var a=2;    "use strict";    foo();//2
或者

  function foo() {        console.log(this.a);    }    var a=2;    (function () {        "use strict";        foo();//2    })();

会正常的输出2.则说明foo运行在严格模式下时,默认绑定不能绑定到全局对象;如果在严格模式下调用的话,foo则不影响默认绑定,即它仍然可以绑定到全局对象。(注意一个是运行环境,一个是调用环境)。

注意:将"use strict"放在脚本文件的第一行,则整个脚本都将以"严格模式"运行;所以放在下面或者放到自执行函数里面。



二、隐式绑定

看调用位置是否有上下文对象,或者说被某个对象拥有或者包含。(可能这种说法也不太严格)

上代码:

 function foo() {        console.log(this.a);    }    var obj={        a:2,        foo:foo    };    obj.foo();//2
1、函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。

2、foo只是被当作引用属性添加到obj中的,无论foo直接在obj中定义或者先定义再添加为引用属性,这个函数严格来说都不属于obj对象(这大概是给下面的隐式丢失埋下伏笔吧。。。)。

3、对象属性引用链中只有上一层或者说最后一层在调用位置中起作用(如下代码)。

function foo() {    console.log(this.a);}var obj2={    a:42,    foo:foo};var obj1={    a:2,    obj2:obj2};obj1.obj2.foo();//42
然尔。。。隐式绑定的话,就会出现隐式丢失的情况:三种隐式丢失的情况
隐式丢失就是函数丢失了绑定对象,此时他会应用默认绑定(也就是第一大种绑定方式),把this绑定到全局对象或者undefined上,取决于是否是严格模式。
一一:给函数起别名:
上代码:
function foo() {        console.log(this.a);    }    var obj={        a:2,        foo:foo    };    var bar=obj.foo;  //给函数起别名    var a="绑到全局对象了";//a是全局对象的属性    bar();//输出:绑到全局对象了

1、虽然bar是obj.foo的一个引用,但实际上,它引用的是foo函数本身,此时的bar()其实是一个不带任何修饰的函数调用,因此应用默认绑定。
(这个地方会丢失的原因大概是后面属性与方法中讲的,,,从技术角度说,函数永远不会“属于”一个对象!有时候this确实会指向调用位置的对象引用,但是这种用法从本质上来说并没有把一个函数变成一个“方法”。即并不是对象调用了这个函数,这个函数就是它的了。。。。。也并不能说明函数是特别的或者“属于”某个对象。。。。。)

二二:作为参数传入自己声明的函数:

上代码:doFoo是自己声明的函数嘛

function foo() {        console.log(this.a);    }    function doFoo(fn) {        fn();    }    var obj={        a:2,        foo:foo    };    var a="绑到全局对象了";    doFoo(obj.foo);//输出:绑到全局对象了


参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值,所以结果跟一一一样。


三三:作为参数传入语言内置的函数

setTimeout是javascript内置的全局函数嘛
上代码:
function foo() {        console.log(this.a);    }    var obj={        a:2,        foo:foo    };    var a="绑到全局对象了";    setTimeout(obj.foo,100);//输出:绑到全局对象了
这三种就是最常见的this指向丢失的情况了。

显示绑定跟new绑定明天再说吧。。。。。


0 0
原创粉丝点击