javascript的this简单记忆

mckogg811 8年前
   <p>一直感觉 javascript 中的 this 是一个大坑,虽然一直都有注意,一直都有研究,但是总是会忘记。在这里,总结一下一些简单的规律</p>    <h2>不考虑箭头函数的情况下</h2>    <p>下面的所有的都是不考虑箭头函数的情况下,因为箭头函数和普通的差别很大</p>    <h2>直接调用的都是window</h2>    <p>除非是 bind 绑定过的 ,其他情况下,直接调用的方法的 this 都是 window 。所谓的直接调用,就是直接以 method() 的形式调用,没有 call , apply , new</p>    <p>看几种情况:</p>    <pre>  <code class="language-javascript">function foo(){     return this;  }  foo(); // window</code></pre>    <pre>  <code class="language-javascript">var obj = {    foo: function(){ return this; }  }    var foo = obj.foo;  foo(); // window</code></pre>    <pre>  <code class="language-javascript">function Foo(){    this.foo = function(){      console.log(this);    }      var foo = this.foo;    foo(); // window  }    new Foo();</code></pre>    <h2>谁调用,谁是this</h2>    <p>除非是 bind 绑定过的 ,一般情况下,谁调用这个方法,那么内部的 this 就指向这个对象。也就是说 obj.method() ,那么就指向 obj 。 obj.foo.method() ,那么就指向 obj.foo</p>    <p>看几个例子:</p>    <pre>  <code class="language-javascript">var obj = {    foo: function(){ return this; }  }  obj.foo(); // obj调用,所以结果是obj</code></pre>    <pre>  <code class="language-javascript">function foo(){ return this };  var obj = {};  obj.foo = foo;  obj.foo(); // obj调用,所以结果是obj</code></pre>    <pre>  <code class="language-javascript">var obj = {    bar: function(){ return this; },    foo: function(){      return this.bar();    }  }  obj.foo(); // 在foo中, this是obj, 而this调用的bar, 所以返回的是obj</code></pre>    <pre>  <code class="language-javascript">var obj = {     bar: {       foo: function(){ return this }     }  }  obj.bar.foo(); // obj.bar调用的foo,所以返回的结果是bar</code></pre>    <pre>  <code class="language-javascript">function foo(){    this.bar = function(){ return this }    return this.bar();  }  foo(); // 由于foo中的this是window, 所以this.bar()返回的是window</code></pre>    <pre>  <code class="language-javascript">function Foo(){    this.foo = function(){ console.log(this); }    this.foo();  }  var object = new Foo(); // 由于this.foo中的this是object,所以this是object</code></pre>    <h2>new会生成一个新的this</h2>    <p>所有情况下,(箭头函数不能使用 new 关键字),使用了 new 以后,会把内部的 this 指向新生成的对象。</p>    <p>除去bind的情况下, prototype 中的 this 也指向新生成的对象</p>    <pre>  <code class="language-javascript">function Foo(){    console.log(this); // this指向新生成的对象,object  }  var object = new Foo();</code></pre>    <pre>  <code class="language-javascript">function Foo(){    this.foo = function(){ return this === object; }  }  var object = new Foo();  object.foo(); // 输出true</code></pre>    <pre>  <code class="language-javascript">function Foo(){}  Foo.prototype.foo = function(){ return this === object; }  var object = new Foo();  object.foo(); // 输出true</code></pre>    <h2>call, apply是谁,this就是谁</h2>    <p>除非是bind的情况, call , apply 是谁,那么内部的 this 就是谁。</p>    <p>注意:如果是基本类型,那么 javascript 会把基本类型转换成 Object 的形式</p>    <p>也是看例子:</p>    <pre>  <code class="language-javascript">function foo(){ return this; }  foo.call("a"); // String  typeof foo.call("a"); // object</code></pre>    <pre>  <code class="language-javascript">var obj = {    foo : function(){ return this; }  }  obj.foo.call(1); // Number  typeof obj.foo.call(1); // object</code></pre>    <pre>  <code class="language-javascript">function Foo(){    this.foo = function(){ return this; }  }  var object = new Foo();  object.foo.call(1); // Number</code></pre>    <h2>bind是谁,this就是谁</h2>    <p>除了 new 这一种特殊情况 , bind 的对象是谁,那么 this 也就是谁。即使 call , apply 也没有权利改变。</p>    <p>注意:如果是基本类型,那么 javascript 会把基本类型转换成 Object 的形式</p>    <pre>  <code class="language-javascript">function foo() { return this; }   foo = foo.bind(1);  foo(); // Number  typeof foo(); // object</code></pre>    <pre>  <code class="language-javascript">function foo() { return this; }   foo = foo.bind(1);  foo.call("a"); // Number 1</code></pre>    <pre>  <code class="language-javascript">function Foo() { return this; }   Foo.prototype.foo = (function(){ return this; }).bind(1);  var object = new Foo();  object.foo(); // Number</code></pre>    <p>特殊情况</p>    <p>new 这个关键词可以改变方法内部的 this ,使他指向新生成的对象</p>    <pre>  <code class="language-javascript">function Foo(){ this.foo = function(){ console.log(this === obj) } }  Foo = Foo.bind(1);  var obj = new Foo();  obj.foo(); // 输入true</code></pre>    <h2>箭头函数</h2>    <p>箭头函数的 this 是根据定义环境的 this 来定的,也就是说定义的函数周围的 this 是什么,它的 this 就是什么。</p>    <p>而且不会被 bind , call , apply 所改变</p>    <pre>  <code class="language-javascript">var foo = ()=>{ return this };  foo() // window</code></pre>    <pre>  <code class="language-javascript">var obj = { foo: ()=>this }  obj.foo(); // 由于定义的时候,周围的环境是window,所以返回window</code></pre>    <pre>  <code class="language-javascript">var obj = {    foo(){       var bar= ()=>{ return this };       return bar();    }  }  obj.foo(); // 由于定义bar的时候,周围环境是obj,所以返回obj  var foo = obj.foo;  foo(); // 同理,这里是window</code></pre>    <pre>  <code class="language-javascript">var foo = ()=>{ return this };  foo = foo.bind(1);  foo(); // window  foo.call(1); // window  foo.apply(1); // window</code></pre>    <pre>  <code class="language-javascript">function Foo(){    // 箭头函数    var a = ()=>{      console.log(this === object); // true    }      // 对比普通函数    var b = function(){      console.log(this === window); // true    }        this.foo = function(){      a(); b();    }  }    var object = new Foo();  object.foo();</code></pre>    <pre>  <code class="language-javascript">function Foo(){}  // window  Foo.prototype.foo = ()=>{ return this }  // window  var object = new Foo();  object.foo(); // 由于定义foo的时候,周围环境是window,所以这里是window</code></pre>    <p>由于只是我根据经验和资料自己总结的,所以不知道是否有疏忽或者遗漏,如果有问题的地方,欢迎提出。谢谢</p>    <p> </p>    <p>来自:https://segmentfault.com/a/1190000008374668</p>    <p> </p>