js this大汇总

346 阅读3分钟

this的绑定只受最靠近的成员引用的影响

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

默认绑定

  • 全局

  • 函数独立调用 window

  • 闭包

    function t(){
    	return function(){
    		console.log(this)  //window,也属于函数独立调用
    	}
    }
    

隐式绑定

  • function foo(){
        console.log(this.a);
    }
    var obj1 = {
        a : 1;
        foo: foo, //this -> obj1
        obj2 : {
            a:2,
            foo:foo //this -> obj2
        }
    }
    
  • 隐式丢失

    • 【函数别名】
      var a = 0;
      function foo(){
          console.log(this.a);
      }
      var obj = {
          a: 1,
          foo:foo
      }
      obj.foo(); //this指向obj
      var bar = obj.foo;  //最靠近成员是bar 他所在的是作用域是全局
      bar();//0
      ---------------------------------------------------
      【参数传递】
      var a = 0;
      function foo() {
          console.log(this.a);
      }
      function bar(fn) {  							
          fn();
      }
      var obj = {
          a: 2,
          foo
      }
      bar(obj.foo);						// var fn = obj.foo 隐式赋值 this就是fn 
      --------------------------------------------------------
      【内置函数】
      var a = 0;
      function foo(){
          console.log(this.a);
      }
      var obj = {
          a : 2,
          foo:foo
      }
      setTimeout(obj.foo,100);//0    var callback = obj.foo
      -----------------------------------------------------------
      【间接调用】
      function foo(){
          console.log(this.a);
      }
      var a = 2;
      var o = {a: 3,foo: foo};
      var p = {a: 4};
      o.foo();//3;
      //将o.foo函数赋值给p.foo函数,然后立即执行。相当于仅仅是foo()函数的立即调用
      (p.foo = o.foo)();//2    var bar = (p.foo = o.foo)
      
      //另一种情况
      function foo() {
          console.log( this.a );
      }
      var a = 2;
      var o = { a: 3, foo: foo };
      var p = { a: 4 };
      o.foo(); // 3
      //将o.foo函数赋值给p.foo函数,之后p.foo函数再执行,是属于p对象的foo函数的执行
      p.foo = o.foo;  
      p.foo();//4
      ------------------------------------------------
      其他情况
      在javascript引擎内部,obj和obj.foo储存在两个内存地址,简称为M1和M2。只有obj.foo()这样调用时,是从M1调用M2,因此this指向obj。但是,下面三种情况,都是直接取出M2进行运算,然后就在全局环境执行运算结果(还是M2),因此this指向全局环境
      var a = 0;
      var obj = {
          a:2,
          foo:foo
      }
      function foo(){
          console.log(this.a);
      }
      (obj.foo = obj.foo)();//0   立即执行
      (false || obj.foo)();//0
      (1,obj.foo)();//0
      

显示绑定

通过call()、apply()、bind()方法把对象绑定到this上,叫做显示绑定。对于被调用的函数来说,叫做间接调用

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

显示绑定无法解决隐式丢失问题

硬绑定

 硬绑定是显式绑定的一个变种,使this不能再被修改
var a = 0;
function foo(){
    console.log(this.a);
}
var obj = {
    a:2
};
var bar = function (){
    foo.call(obj);
}

//在bar函数内部手动调用foo.call(obj)。因此,无论之后如何调用函数bar,它总会手动会在obj上调用foo
bar();//2
setTimeout(bar,2000);//2
bar.call(window);//2

api

javascript中新增了许多内置函数,具有显式绑定的功能,如数组的5个迭代方法:map()forEach()filter()some()every()

//forEach(fn,对象)
var id = 'window';
function foo(value){
    console.log(value,index,this.id);
}
var obj = {
    id: 'fn'
};
[1,2,3].forEach(foo);//1 0 "window" 2 1 "window" 3 2 "window"
[1,2,3].forEach(foo,obj);//1 "fn" 2 "fn" 3 "fn"

bind

ECMAScript 5 引入了 Function.prototype.bind。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。

function f(){
  return this.a;
}

var g = f.bind({a:"azerty"});
console.log(g()); // azerty

var h = g.bind({a:'yoo'}); // bind只生效一次!
console.log(h()); // azerty

var o = {a:37, f:f, g:g, h:h};
console.log(o.f(), o.g(), o.h()); // 37, azerty, azerty

new 绑定

var o = {
    m:function(){
        return this;
    }
}
var obj = new o.m();
console.log(obj,obj === o);//{} false
console.log(obj.contructor === o.m);//true

this场景

严格模式

  • 独立调用的函数的this指向undefined
  • 使用call和apply时,null和undefined不会转换成全局对象,如果不指定的话会出错

getter 与 setter 中的 this

用作 gettersetter 的函数都会把 this 绑定到设置或获取属性的对象。

function sum() {
  return this.a + this.b + this.c;
}

var o = {
  a: 1,
  b: 2,
  c: 3,
  get average() {
    return (this.a + this.b + this.c) / 3;
  }
};

Object.defineProperty(o, 'sum', {
    get: sum, enumerable: true, configurable: true});

console.log(o.average, o.sum); // logs 2, 6

原型链中的 this

指向调用这个方法的对象

var o = {
  f: function() { 
    return this.a + this.b; 
  }
};
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5    p调用这个方法。this指向他

DOM事件处理函数

this指向触发事件的函数

this === e.currentTarget

ul>li ul.onclick ==>this是ul e.target是li

箭头函数

this就是封闭词法环境的this

var foo = () => this;
无论如何,foo 的 this 被设置为他被创建时的环境