JS-this

93 阅读3分钟

this的默认绑定

  1. 全局环境下的this指向window
  2. 函数独立调用,函数内部的this指向window
function fn(){
    console.log(this);//window
}
var a = 0;
var obj = {
    a:2,
    foo:function(){
        function test(){
            //window调用的test函数 所以指向的是window
            console.log(this.a);//0
        }
    }
}
obj.foo();

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

var a = 0;
var obj = {
    a:2,
    foo:function(){
    //函数当做对象的方法来调用 this指向obj
        var that = this;
        function test(){
            console.log(that.a);2
        }
    }
}
obj.foo();
  1. IIFE 自执行函数this指向window(隐式绑定)
var a = 0;
function foo(){
    console.log(this.a);//2
    (function test(){
        console.log(this.a);//0
    })();
}
var obj = {
    a:2,
    foo:foo
}
  1. 闭包中this指向window 原理与IIFE一致

绑定丢失

  1. 隐式绑定
var a = 10;
function foo(){
    console.log(this.a);//10
}
var obj = {
    a:2,
    foo:foo
}
var bar = obj.foo;
bar();
//这时候的this指向的是window 因为bar()=window.bar();

小结:看哪个对象调用的这个函数 那么这个函数指向的就是这个对象 如果上面代码的后两行换成

var bar = obj.foo();
bar;

那么foo函数指向的是obj对象 打印的是obj里的a 故为2

2. 参数传递

var a = 10;
function foo(){
    console.log(this.a);//10
}
var obj = {
    a:2,
    foo:foo
}
function bar(fn){
    fn();
}
bar(obj.foo);
//把obj.foo当做参数传递到bar函数中,其实就是把foo函数丢给了bar去调用,
//所以this指向的是bar
  1. 内置函数
var a = 10;
    function foo() {
      console.log(this.a);//10
    }
    var obj = {
      a: 1,
      foo: foo
    }
    setTimeout(obj.foo, 1000);
//原理与上面一致
  1. 间接调用
function foo() {
      console.log(this.a);
    }
    var a = 10;
    var obj = {
      a: 2,
      foo: foo
    }
    var p = { a: 4 }
    obj.foo();//2
    //将obj.foo函数对象赋值给p.foo函数然后立即执行。
    //相当于仅仅是foo()函数的立即调用 默认指向window
    (p.foo = obj.foo)();//10 立即执行的this都指向window
    
    //将obj.foo赋值给p.foo。函数,之后p.foo()函数再执行,
    //其实是属于p对象的方法的指向,this指向当前的p对象
    p.foo = obj.foo;
    p.foo();//4

显示绑定

var a = 10;
    function foo() {
      console.log(this.a);
    }
    var obj = {
      a: 1
    }
    foo();//10
    foo.call(obj);//1 
    foo.apply(obj);//1
    var fn = foo.bind(obj);
    fn();//1
  1. 硬绑定
var a = 10;
    function foo() {
      console.log(this.a);
    }
    var obj = {
      a: 2
    }
    var bar = function () {
      foo.call(obj);
    }
    bar();//2
    setTimeout(bar, 1000);//2
    bar.call(window);//2
  1. 回调函数
var id = 'window';
    function fn(el) {
      console.log(el, this.id);
    }
    var obj = {
      id: 'fn'
    }
    var arr = [1, 2, 3];
    arr.forEach(fn);//window
    arr.forErch(fn, obj);//obj

new绑定

function fn() {
      //如果是new关键字来执行函数,相当于构造函数来实例化对象,
      //那么内部的this指向当前的实例化对象
      console.log(this);
    }
    var fn = new fn();
    fn;
function fn2() {
      console.log(this);//fn2
      //是用return返回对象的时候,实例化出来的对象是当前的返回对象
      return {
        name: 'qaq'
      }
    }
    var fn2 = new fn2();
    console.log(fn2);//obj对象
var person = {
      fav: function () {
        return this;
      }
    }
    var p = new person.fav();
    console.log(p);//fav {}
    //实例化出来的对象内部属性constructor属性指向当前的构造函数
    console.log(p.constructor === person.fav);//true

严格模式下的this指向

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