1. 程式人生 > 實用技巧 >JS中的this - 01

JS中的this - 01

首先從物件開始,物件表示一系列屬性的集合,包括普通的屬性和函式,如下:

let student = {
  nickname: '小明',
  say: function(){
    console.log('我是小明');
  }
}

可以看到log的內容包含了這個物件nickname屬性的值,所以沒必要寫死,可以用this指向這個物件,也就是下面的部分:

let student = {
  nickname: '小明',
  say: function(){
    console.log('我是' + this.nickname);
  }
}
student.say();

上面的程式碼中this.nickname

就表示student這個物件中的nickname,這是很自然的思路,也基本正確。不過,需要注意到一個細節,我們是用student.say()這樣的方式來使用say這個函式的,這裡先關注呼叫的物件student
接著,我們將say函式單獨拎出來使用:

let say = student.say;
say();

按照正常的思路,可能會以為上面還是照常輸出我是小明,而實際上的輸出是我是undefined,於是便會發現將say拎出來單獨使用的時候,this.name的值為undefined,那為什麼會出現這種情況?
首先,檢視student.say()say()這兩者的區別,很明顯前者是通過student

來呼叫say()函式的,後者沒有呼叫物件,這也就是最重要的不同點了。
在JavaScript中,this是“自由”的,它的值是在呼叫時計算出來的,並不取決於方法宣告的位置,而是取決於在“點符號前”的是什麼物件。所以說,如果是student.say(),則this為student,而如果就光禿禿的一個函式,也沒有“點符號”,則分為兩種情況:

  1. "use strict"模式下,this為undefined,所以會報錯;
  2. 非strict模式下,this表示全域性物件(在網頁中是window物件);
    這樣便可以解釋say()this.nickname為什麼為undefined了,因為window.nickname
    undefined
    接著便可以寫幾個例子:
let student = {
  nickname: '小明',
  say: function(){
    console.log('我是' + this.nickname);
  }
}
student.say(); // 我是小明
window.nickname = '小紅';
let say = student.say;
say(); // 我是小紅
let student2 = {
  nickname: '小白',
}
student2.say = student.say;
student2.say(); // 我是小白

平常使用this的時候需要注意以下幾點:

  1. 只在物件的方法裡使用this,不要在普通的方法內使用;
  2. 時刻注意this的指向,特別是setTimeout、setInterval等超時函式(超時呼叫的程式碼都是在全域性作用域中執行的,因此函式中this的值在非嚴格模式下指向window物件,在嚴格模式下是undefined);
  3. 如果需要使用外層的this,可以先將this賦給that,然後使用that;

Vue補充部分

let LoStudent1 = {
  // 因為是呼叫$root.getName(),所以值為小紅
  template: `<div>{{name}}{{$root.getName()}}</div>`,
  data() {
    return {
      name: '小明'
    }
  },
};
let LoStudent2 = new Vue({
  el: '#app',
  template: `<div>{{name}}<lo-student1></lo-student1></div>`,
  data() {
    return {
      name: '小紅'
    }
  },
  components: {
    LoStudent1
  },
  methods: {
    getName() {
      return this.name;
    }
  }
})

有關this繫結與箭頭函式等問題下篇再講