javascript中this的指向问题(一)

最近看《你不知道的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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值