javascript的this簡單記憶

mckogg811 7年前發布 | 8K 次閱讀 JavaScript開發 JavaScript

一直感覺 javascript 中的 this 是一個大坑,雖然一直都有注意,一直都有研究,但是總是會忘記。在這里,總結一下一些簡單的規律

不考慮箭頭函數的情況下

下面的所有的都是不考慮箭頭函數的情況下,因為箭頭函數和普通的差別很大

直接調用的都是window

除非是 bind 綁定過的 ,其他情況下,直接調用的方法的 this 都是 window 。所謂的直接調用,就是直接以 method() 的形式調用,沒有 call , apply , new

看幾種情況:

function foo(){
   return this;
}
foo(); // window
var obj = {
  foo: function(){ return this; }
}

var foo = obj.foo;
foo(); // window
function Foo(){
  this.foo = function(){
    console.log(this);
  }

  var foo = this.foo;
  foo(); // window
}

new Foo();

誰調用,誰是this

除非是 bind 綁定過的 ,一般情況下,誰調用這個方法,那么內部的 this 就指向這個對象。也就是說 obj.method() ,那么就指向 obj 。 obj.foo.method() ,那么就指向 obj.foo

看幾個例子:

var obj = {
  foo: function(){ return this; }
}
obj.foo(); // obj調用,所以結果是obj
function foo(){ return this };
var obj = {};
obj.foo = foo;
obj.foo(); // obj調用,所以結果是obj
var obj = {
  bar: function(){ return this; },
  foo: function(){
    return this.bar();
  }
}
obj.foo(); // 在foo中, this是obj, 而this調用的bar, 所以返回的是obj
var obj = {
   bar: {
     foo: function(){ return this }
   }
}
obj.bar.foo(); // obj.bar調用的foo,所以返回的結果是bar
function foo(){
  this.bar = function(){ return this }
  return this.bar();
}
foo(); // 由于foo中的this是window, 所以this.bar()返回的是window
function Foo(){
  this.foo = function(){ console.log(this); }
  this.foo();
}
var object = new Foo(); // 由于this.foo中的this是object,所以this是object

new會生成一個新的this

所有情況下,(箭頭函數不能使用 new 關鍵字),使用了 new 以后,會把內部的 this 指向新生成的對象。

除去bind的情況下, prototype 中的 this 也指向新生成的對象

function Foo(){
  console.log(this); // this指向新生成的對象,object
}
var object = new Foo();
function Foo(){
  this.foo = function(){ return this === object; }
}
var object = new Foo();
object.foo(); // 輸出true
function Foo(){}
Foo.prototype.foo = function(){ return this === object; }
var object = new Foo();
object.foo(); // 輸出true

call, apply是誰,this就是誰

除非是bind的情況, call , apply 是誰,那么內部的 this 就是誰。

注意:如果是基本類型,那么 javascript 會把基本類型轉換成 Object 的形式

也是看例子:

function foo(){ return this; }
foo.call("a"); // String
typeof foo.call("a"); // object
var obj = {
  foo : function(){ return this; }
}
obj.foo.call(1); // Number
typeof obj.foo.call(1); // object
function Foo(){
  this.foo = function(){ return this; }
}
var object = new Foo();
object.foo.call(1); // Number

bind是誰,this就是誰

除了 new 這一種特殊情況 , bind 的對象是誰,那么 this 也就是誰。即使 call , apply 也沒有權利改變。

注意:如果是基本類型,那么 javascript 會把基本類型轉換成 Object 的形式

function foo() { return this; } 
foo = foo.bind(1);
foo(); // Number
typeof foo(); // object
function foo() { return this; } 
foo = foo.bind(1);
foo.call("a"); // Number 1
function Foo() { return this; } 
Foo.prototype.foo = (function(){ return this; }).bind(1);
var object = new Foo();
object.foo(); // Number

特殊情況

new 這個關鍵詞可以改變方法內部的 this ,使他指向新生成的對象

function Foo(){ this.foo = function(){ console.log(this === obj) } }
Foo = Foo.bind(1);
var obj = new Foo();
obj.foo(); // 輸入true

箭頭函數

箭頭函數的 this 是根據定義環境的 this 來定的,也就是說定義的函數周圍的 this 是什么,它的 this 就是什么。

而且不會被 bind , call , apply 所改變

var foo = ()=>{ return this };
foo() // window
var obj = { foo: ()=>this }
obj.foo(); // 由于定義的時候,周圍的環境是window,所以返回window
var obj = {
  foo(){
     var bar= ()=>{ return this };
     return bar();
  }
}
obj.foo(); // 由于定義bar的時候,周圍環境是obj,所以返回obj
var foo = obj.foo;
foo(); // 同理,這里是window
var foo = ()=>{ return this };
foo = foo.bind(1);
foo(); // window
foo.call(1); // window
foo.apply(1); // window
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();
function Foo(){}
// window
Foo.prototype.foo = ()=>{ return this }
// window
var object = new Foo();
object.foo(); // 由于定義foo的時候,周圍環境是window,所以這里是window

由于只是我根據經驗和資料自己總結的,所以不知道是否有疏忽或者遺漏,如果有問題的地方,歡迎提出。謝謝

 

來自:https://segmentfault.com/a/1190000008374668

 

 本文由用戶 mckogg811 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!