javascript基礎之this

javascript基礎之this指針

越日後面學愈加現基礎的重要性,因此打算從新過一遍基礎,以後出幾個vue和react的實戰教程。
ok,嚴歸正傳。javascript

首先什麼是this

this是執行上下文建立時肯定的一個在執行過程當中不可改變的變量。
總之記住一句話this的指向由以執行時候的上下文決定的而非定義時的上下文vue

看過一本書叫《JavaScript語言精粹》,裏面把this的出現場景爲4類,固然那是在es6出來以前,不過也能夠表示基本的用法了,在es6出來以後出現箭頭函數,因此一共是5種:java

  1. 有對象的就指向該對象
  2. 沒有對象的就指向全局對象,在非嚴格模式下指向window
  3. 有new構造函數的就指向new完以後的新對象
  4. 經過apply或者bind或者call改變this指向的對象
  5. 出現箭頭函數的時候,this指向爲定義時的上下文對象而非指向時,而且不能被call改變

函數有對象的時候就指向該對象

let name = 'bob';
    let obj = {
      name,
      getName(){
         console.log(this.name);  
      }
    };

console.log(obj.getName()); //=>bob

由於getName()屬於對象obj,而且由obj進行調用,因此毫無疑問是指向obj這個對象,ok,咱們再看一個例子react

var name = 'jay';
 var obj = {
      name:'bob'
      getName(){
         console.log(this.name);  
      }
 };
 
 let t = obj.getName;
 console.log(t()); // => jay

如上,爲何此次t函數打印出來的值是jay?excuse me?
其實要理解也好簡單,當執行t()的時候(在非嚴格模式下)其實t實際上是屬於全局對象(在瀏覽器環境)也就是window,而var name = 'jay'爲全局變量,因此輸出jay也不奇怪了。es6

沒有對象的就指向全局對象,在非嚴格模式下指向window

var name = 'bob';
var obj = {
  name,
  getName:function(){
     function otherName(){
        return this.name;
     }
     console.log(otherName());
  }
};

obj.getName(); // =>bob

otherName隨即是在obj的getName中定義的,可是它仍是一個普通函數,他的this其實和數組

var name = 'bob';
    function otherName(){
       return this.name;
    }
    console.log(otherName()); // =>bob

執行效果同樣的,他的this的指向實際上是undefined,在非嚴格模式下,當this指向undefined的時候其實會自動轉化成window對象(在瀏覽器中)。
ok,讓咱們再看一種狀況瀏覽器

var name = 'bob';
function otherName(){
   "use strict"
   return this.name;
}
console.log(otherName()); // Uncaught TypeError: Cannot read property 'name' of undefined

這個時候會拋出一個錯誤,由於在嚴格模式下當this指針指向undefined的時候不會自動轉化成window對象。app

有new構造函數的就指向new完以後的新對象

首先什麼是構造函數,其實能夠用一句話去歸納:
構造函數其實就是用來新建對象的函數函數

JavaScript自己就爲咱們定義了幾個經常使用的構造函數,你確定認識 好比Function, Object, Array, Date等等,只不過咱們日常object,function都不是用new Function,new Object,而是用他的語法糖好比
var obj = {} 其實等同於 var obj = new Object();this

function Human(name,age,sex){
   this.name = name;
   this.age = age;
   this.sex = sex;
   this.common = function(){
       console.log('名字爲'+this.name);
   }
}

var h = new Human('bob',25,'sex');
h.common(); // => 名字爲bob

有new構造函數的就指向new完以後的新對象,此時的this指向的是他new出現來的對象h。

經過apply或者bind或者call改變this指向的對象

因爲函數具備函數做用域,因此有時候咱們須要引用外層做用域的時候一般用的方法是call,apply,和bind這三兄弟

首先咱們來看看call,老樣子先看代碼

var a = {
    user:"bob",
    fn:function(){
        console.log(this.user); 
    }
}
var b = {
    user:'jay'
}

a.fn.call(b); // => jay

若是不調用call,咱們直接使用a.fn的話將會輸出bob,由於fn這個方法是a這個對象定義出來的,因此this指向是a這個對象,可是當咱們使用了call以後this指針指向的對象就變成b了,因而乎也不難理解爲何輸出的user是jay了。
簡介一下call的用法:
fn.call(obj,argument-1,argument-1,...)
是以obj這個對象去代替fn的this指針也就時fn的this指針指向obj,後面的argument-1,argument-1是形參
apply和call的用法基本相同,不一樣點是apply調用傳形參的時候穿的是數組或者是類數組,以下:
fn.apply(obj,[argument-1,argument-1,...])

至於bind和call或者apply的區別,我也舉一個例子

var a = {
    user:"bob",
    fn:function(){
        console.log(this.user); 
    }
}
var b = {
    user:'jay'
}

var c = a.fn.bind(b); 
c(); // => jay

從上面這個例子能夠得出一個結論:
其實call和apply方法,都是對函數的直接調用,可是bind()方法須要加上()來執行。

出現箭頭函數的時候,this指向爲定義時的上下文對象而非指向時,而且不能被call改變

首先咱們先看一個例子:

var obj = {name:'bob'};

var name = 'jay';

var sayName = () => console.log(this.name);

sayName(); // => jay
sayName.call(obj); //jay

由上面的例子咱們能夠看出來此時this指針在用call改變了以後指向的依然是全局對象(非嚴格瀏覽器環境中是window)而非obj。

ok,至此this指針的用法總結完畢。

後記

以上this的用法都爲我的總結,若有不當之處還請指出

轉載請註明出處.

相關文章
相關標籤/搜索