this指向问题

  • 全局上下文 非严格模式和严格模式中this都是指向顶层对象(浏览器中是window)。
  • 1.默认绑定 独立调用
    • 普通函数调用,此时 this 指向 window
    • 被嵌套的函数独立调用时,this默认指向了window
    • 自执行函数 this默认指向了window
    • 闭包中this默认指向window
  • 2.隐式绑定 方法调用
    当函数当作方法来调用,this指向了直接对象
  • 3,显示绑定 间接调用( call() apply() bind() )
    call() apply() bind() 把对象绑定到this上,叫做显示绑定
  • 4.new绑定 构造函数调用 new
    1.如果是new关键字来执行函数,相当于构造函数来实例化对象,那么内部的this指向了当前实例化的对象
    2.使用return关键字来返回对象时,实例化出来的对象是当前的返回对象

隐式丢失
隐式丢失就是指被隐式绑定的函数丢失了绑定对象,从而默认绑定到window

  • 1.函数别名
    把obj.foo赋值给了别名bar,造成隐式丢失的情况,因为只是把obj.foo()赋值了bar变量,而bar与obj对象毫无关系

  • 2.参数传递
    把obj.foo当作参数传递到bar函数中,有隐式的函数赋值fn=obj.foo,
    只是把foo函数赋值给了fn,而fn与obj对象毫无关系,所以当前foo函数内部的this指向了window

  • 3.内置函数setTimeout()和setInterval()
    第一个参数的回调函数中的this,默认指向了window,跟第二种情况类似

  • 4.间接调用
    将obj.foo函数对象赋值给了p.foo函数,然后立即执行。相当于仅仅是foo()函数的 立即调用 ,内部的this,默认指向了window
    (p.foo=obj.foo)()

严格模式下this的指向
1.严格模式下,独立调用的函数内部的this指向了undefined
2.严格模式下,函数apply()和call()内部的this始终是他们的第一个参数

全局上下文 非严格模式和严格模式中this都是指向顶层对象(浏览器中是window)

console.log(this === window);//true
  
'use strict'
console.log(this === window);//true
this.name = '111';
console.log(this.name); // 111

1.默认绑定 独立调用

  • 普通函数调用,此时 this 指向 window
  • 被嵌套的函数独立调用时,this默认指向了window
  • 自执行函数 this默认指向了window
  • 闭包中this默认指向window

普通函数调用,此时 this 指向 window

//函数独立调用,函数内部的this也指向window
    function fn(){
        console.log(this);//window
    }
    fn();

被嵌套的函数独立调用时,this默认指向了window

//被嵌套的函数独立调用时,this默认指向了window
    var a=0;
    var obj={ 
        a:2,
        foo:function(){
            var that=this;
            function test(){
                console.log(this.a);//0
                console.log(that.a);//2
            }
            test();
        }
    }
    obj.foo();

自执行函数 this默认指向了window

//IIFF  自执行函数  this默认指向了window
    var a=10;
    function fooo(){
        (function test(){
            console.log(this);//window
            console.log(this.a);
        })();
    }
    var obj={
        a:2,
        fooo:fooo
    }
    obj.fooo();//10

    (function(){
        console.log(this);//window
    })()

闭包中this默认指向window

//闭包中this默认指向window
    var a=0;
    var obj={
        a:12,
        foo2:function(){
            var _this=this;
            return function(){
                return _this.a;//12
                return this.a;//0
            }
        }
    }
    var fn=obj.foo2();
    console.log(fn());

2.隐式绑定 方法调用

当函数当作方法来调用,this指向了直接对象

//当函数当作方法来调用,this指向了直接对象(。前面的对象)
    function foo(){
        console.log(this.a);
    }
    var obj={
        a:1,
        foo:foo,
        obj2:{
            a:2,
            foo:foo
        }
    }

//foo()函数的直接对象是obj,this的指向指向了直接对象
    obj.foo();//1

    //foo()函数的直接对象是obj2,this的指向指向了直接对象
    obj.obj2.foo();//2

3,显示绑定 间接调用( call() apply() bind() )改变this指向

注意:call() apply() bind()的区别:
在JavaScript中,call和apply都是为了改变某个函数运行时的上下文而存在的,换句话说就是为了改变函数体内部的this指向
bind是返回对应函数,便于稍后使用;apply、call则是立即调用
对于apply、call而言,作用完全

call() apply() bind() 把对象绑定到this上,叫做显示绑定

//call()  apply()  bind() 把对象绑定到this上,叫做显示绑定
    var a=0;
    function foo(){
        console.log(this.a);
    }
    var obj={
        a:2
    }
    foo();
    foo.call(obj);
    foo.apply(obj);
    var fn=foo.bind(obj);
    fn();

硬绑定时显示绑定的一个变种,使得this不能再被改变

 //硬绑定时显示绑定的一个变种,使得this不能再被改变
    var a=0;
    function foo(){
        console.log(this.a);
    }
    var obj={
        a:2
    }
    var bar=function(){
        foo.call(obj);
    }
    bar();//2
    setTimeout(bar,2000);//2
    bar.call(window);//2   这里的this不再改变回window

数组的forEach(fn,对象) map() filter() some() every()

 //数组的forEach(fn,对象)   map()  filter()  some()  every()
    var id="window";
    function fn(el){
        console.log(el,this.id);
    }
    var obj={
        id:"fn"
    }
    var arr=[1,2,3];
    arr.forEach(fn);//window  window  window
    arr.forEach(function(el,index){
        console.log(el,index,this);
    },obj);
   /* 1 0 {id: "fn"}
      2 1 {id: "fn"}
      3 2 {id: "fn"}*/

4.new绑定 构造函数调用 new

1.如果是new关键字来执行函数,相当于构造函数来实例化对象,那么内部的this指向了当前实例化的对象
2.使用return关键字来返回对象时,实例化出来的对象是当前的返回对象

 function fn(){
        console.log(this);
        return;
    }
    //1.如果是new关键字来执行函数,相当于构造函数来实例化对象,那么内部的this指向了当前实例化的对象
    
    var fn=new fn();
    console.log(fn);//fn fn



    function fn2(){
        //this还是指向了当前对象
        console.log(this);
        //使用return关键字来返回对象时,实例化出来的对象是当前的返回对象
        return {
            name:"qqq"
        }
    }
    var fn2=new fn2();//fn2()
    console.log(fn2);//{name: "qqq"}

严格模式下this的指向

1.严格模式下,独立调用的函数内部的this指向了undefined
2.严格模式下,函数apply()和call()内部的this始终是他们的第一个参数

//1.严格模式下,独立调用的函数内部的this指向了undefined
    function fn(){
        'use strict'
        console.log(this);
    }
    fn();//undefined

//2.严格模式下,函数apply()和call()内部的this始终是他们的第一个参数
    var color="red";
    function showColor(){
        'use strict';
        console.log(this);
        console.log(this.color);
    }
    showColor.call(null);//null

隐式丢失

隐式丢失就是指被隐式绑定的函数丢失了绑定对象,从而默认绑定到window

  • 1.函数别名
    把obj.foo赋值给了别名bar,造成隐式丢失的情况,因为只是把obj.foo()赋值了bar变量,而bar与obj对象毫无关系

  • 2.参数传递
    把obj.foo当作参数传递到bar函数中,有隐式的函数赋值fn=obj.foo,
    只是把foo函数赋值给了fn,而fn与obj对象毫无关系,所以当前foo函数内部的this指向了window

-3. **内置函数setTimeout()和setInterval()**第一个参数的回调函数中的this,默认指向了window,跟第二种情况类似

  • 4.间接调用
    将obj.foo函数对象赋值给了p.foo函数,然后立即执行。相当于仅仅是foo()函数的 立即调用 ,内部的this,默认指向了window
    (p.foo=obj.foo)()
 //隐式丢失就是指被隐式绑定的函数丢失了绑定对象,从而默认绑定到window
    //这种情况比较容易出错却又非常常见
    //1.隐式丢失   函数别名
    var a=0;
    function foo(){
        console.log(this.a);
    }
    var obj={
        a:1,
        foo:foo
    }
    var bar=obj.foo();
    bar();
    //把obj.foo赋值给了别名bar,造成隐式丢失的情况,因为只是把obj.foo()赋值了bar变量,而bar与obj对象毫无关系

//上面的函数相当于
    var a=0;
    var bar=function foo(){
        console.log(this.a);
    }
    bar();

把obj.foo当作参数传递到bar函数中,有隐式的函数赋值fn=obj.foo,

只是把foo函数赋值给了fn,而fn与obj对象毫无关系,所以当前foo函数内部的this指向了window

//2.参数传递
    var a=0;
    function foo(){
        console.log(this.a);
    }
    function bar(fn){
        fn()
    }
    var obj={
        a:1,
        foo:foo
    }
    bar(obj.foo)
    //把obj.foo当作参数传递到bar函数中,有隐式的函数赋值fn=obj.foo,
    //只是把foo函数赋值给了fn,而fn与obj对象毫无关系,所以当前foo函数内部的this指向了window

    //上面的函数相当于
    var a=0;
    function foo(){
        console.log(this.a);
    }
    function bar(fn){
        fn()
    }
    
    bar(function foo(){
        //内部的this指向了window
        console.log(this.a);
    })

内置函数setTimeout()和setInterval()第一个参数的回调函数中的this,默认指向了window,跟第二种情况类似

 //3.内置函数setTimeout()和setInterval()第一个参数的回调函数中的this,默认指向了window,跟第二种情况类似
    var a=10;
    function foo(){
        console.log(this.a);
    }
    var obj={
        a:1,
        foo:foo
    }
    setTimeout(obj.foo,1000);

将obj.foo函数对象赋值给了p.foo函数,然后立即执行。相当于仅仅是foo()函数的 立即调用 ,内部的this,默认指向了window
(p.foo=obj.foo)()

    //4.间接调用
    function foo(){
        console.log(this.a);
    }
    var a=2;
    var obj={
        a:3,
        foo:foo
    }
    var p={a:4};
   // 隐式绑定,函数当作对象中的方法来使用,内部的this指向了该对象
    obj.foo();//3
    //将obj.foo函数对象赋值给了p.foo函数,然后立即执行。相当于仅仅是foo()函数的 立即调用 ,内部的this,默认指向了window
    (p.foo=obj.foo)();//2

    //将obj.foo赋值给了p.foo函数,之后p.foo()函数再执行,其实是属于p对象的方法的指向,this指向了当前的p对象
    p.foo=obj.foo
    p.foo();//4
//5.其他情况,指向了window的特殊情况
    var a=0;
    var obj={
        a:1,
        foo:foo
    }
    function foo(){
        console.log(this.a);
    }
    (obj.foo=obj.foo)();//0
    (false||obj.foo)();//0
    (1,obj.foo)()//0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值