前言:最近開始在學新框架了,只是說原生的 javascript 也同時在補足觀念中,最近在複習 this 看當初的筆記,有一種 WTF ,我在寫什麼三小?只能當自己是白紙再看一遍了。 嗚嗚
輔助資源:
猜猜這個 "this" 到底是什麼?
https://youtu.be/8uqUD2F_W74
先說重點:
關鍵:this 決定在於函式如何被呼叫
console.log(this);
在全域執行環境呼叫this,此時它會指向全域物件,也就是window

// Outer Environment
console.log(this);
// function statement
function FunctionStatement() {
  console.log(this);
}
FunctionStatement();
// function expression
const FunctionExpression = function() {
  console.log(this);
}
FunctionExpression();
這裡的 this 都代表 不管是 function statement 去執行;或是 使用 function expression 執行 只要在全域定義、呼叫創造其執行環境,這時的this會指向全域物件。
var kara = " p助"
function a(){
	this.kara = "兔兔"
}
a();
console.log(kara)
console.log 答案是
兔兔 !
我在全域宣告一個變數kara,賦值"p助"。
呼叫函式a時,函式a的執行環境被創造出來,同時函式a的執行環境也創造了它自己的this。
賦值兔兔"給函式a的this.kara,因為函式a自己的this指向全域,這下可好了,在全域的變數kara,其值被蓋過從"p助"變成了"兔兔"。
所以回到這一題,這裡的 this 就是 指全域
var name = '全域';
function callMethod () {
  var name = '區域'
  console.log(this.name)
}
callMethod();
所以使用this必須要小心,得清楚它指向的物件對象是誰,否則可能會產生一些開發上的bug。
var Qoo = function (){
 console.log(this.a);
}
var fpp = function (){
   let a =123;
   this Qoo();
}
fpp();
答案是 undefined
因為fpp() 透過 this Qoo 取得 Qoo() 這裡的this Qoo指得是 指向 window.Qoo 。 而Qoo()的 this.a 並非fpp()中的123,而是指向 window.a 所以得到undefined 結果。
請看以下問題:
var name = '全域';
function callMethod() {
  var name = '區域'
  console.log(this.name)
  return function () {       // << 閉包
    var name = '區域的內層變數';
    console.log(this.name)
  }
}
callMethod()();
1.這裡的callMethod()() 執行的 第五行 function
那如果執行出來的結果會是什麼?
答案是: console.log 出現兩個全域
崩潰了嗎?還沒結束喔? 冷靜三秒,數一下 質數
當沒有特別指名this 的情況下, 預設的this 就是全域物件
var name = '全域';
var object = {
  name: 'Object 區域',
  callMethod: function () {
    var name = '區域';
    console.log(this.name);
  },
}
object.callMethod();
其中 callMethod 是一個 匿名函式(anonymous function),程式內容很簡單,就是呼叫出 this 而已。最後則是使用 object.callMethod() 的方式來執行該方法。
Ans "Object 區域"
當某個函式是放在某一個物件裡面時,那麼該函式裡面的 this 指稱的就是該物件本身。
這是ES6的東西 可以補充
function 這個詞彙如果使用在物件內,也可以省略 :function,省略後的語意是沒有變化的,並沒有轉而使用箭頭函式。
const newTeam = {
  // ...
  showPosture: function () {
    console.log('我們是 紅黃綠')
  }
}
const newTeam = {
  // ...
  showPosture () {
    console.log('我們是 紅黃綠')
  }
}
兩個代表一樣意思。
var name = '全域';
var object = {
  name: 'Object 區域1',
  callMethod: function () {
    var name = '區域';
    console.log(this.name);
  },
  
abbCallMethod () {
    var name = '縮寫函式區域';
    console.log(this.name);
  }
}
object.callMethod();   // 
object.abbCallMethod();
第二個 abbCallMethod 就是物件函式縮寫,
所以跟第一個答案 callMethod() 所得到的答案是一樣的。
var name = '全域';
var object = {
  name: 'Object 區域',
 
  arrowCallMethod: () => {
    var name = '箭頭函式區域';
    console.log(this.name);
  }
 
}
object.arrowCallMethod();
這裡要特別注意,箭頭函式 答案是 全域
因為 箭頭函式 特性有強制綁定 this,所以當我們在寫函式時要注意 。
var elements = document.getElementsByTagName('div');
function style () {
  console.log(this);
  this.style.border = '1px solid red';
}
for (var i = 0; i < elements.length; i++) {
  elements[i].addEventListener('click', style, false);
}
這裡 的this 就是我們所執行的 dom 事件 的地方,點擊到的地方
var name = '全域';
var callMethod = function (newName) {
  this.name = '權權權';
  console.log(this.name);
}
var myName = new callMethod();
console.log(myName.name);
console.log 出來的答案是 權權權
因為 myName 繼承了 callMethod 方法 ,所以 myName.name
答案是 權權權
var name = '全域';
var callMethod = function (newName) {
  this.name = newName || '區域';
}
var myName = new callMethod('權權權');
console.log(this.name);
console.log(myName.name);
這裡的  this name  還是指向 全域。
myName.name 就是函式建構式 指的是 權權權。
接下來看陷阱題
 
var name = '全域';
var callMethod = (newName) => {
  this.name = newName || '區域';
}
var myName = new callMethod('卡斯伯');
console.log(this.name);
console.log(myName.name);
這裡不管是哪一個 console.log 都無法執行,因為箭頭函式不能當建構式。
基本上只要看到 bind, apply, call 裡面的this 就是代表綁定的物件
call、apply、bind 三者都是 JavaScript Function 的內建函式,他們與 this 的關係重大,除此之外,call & apply 可以作為呼叫 Function 的另一個手段,而 bind 則會回傳一個經過包裹後的 Function 回來。
function callMethod () {
  var name = '區域'
  console.log(this.name)
}
callMethod.call({name: '魯魯米'});
這裡的 callMethod 所指就是 魯魯米
bind, call, apply 的差異
可以看這篇文章:
讓你弄懂call、apply、bind的應用和區別
https://juejin.im/post/5a9640335188257a7924d5ef
注意事項
先說結論:setTimeout中所執行函數中的this,永遠指向window!!注意是要延遲執行的函數中的this哦!