1. 程式人生 > >讓人頭疼的this

讓人頭疼的this

this是什麼

  this是函式執行時所在的環境變數,是call的第一個引數。

  以及你需要注意的是,this這個鬼東西動不動就會變成window。

怎麼找this

作為物件方法呼叫

var obj = {
  'fn': function(){
    console.log(this)
  }
}
obj.fn()

  此時打印出來的this指的是obj這個物件。在函式作為物件方法呼叫的時候,this指的是呼叫這個函式的物件。

全域性函式呼叫

  所謂全域性函式呼叫,區分於作為物件方法呼叫。

function fn(){
  console.log(this)
}
fn()

  此時打印出來的是window。在函式作為全域性函式呼叫的時候,this指的是window。

  如果是在嚴格模式下,則預設是undefined。

'use strict'
function fn(){
  console.log(this)
}
fn()  //undefined

作為建構函式呼叫

function A(){
  return this
}
var a = new A()
console.log(a)

  此時的this指的是這個新new出來的物件。雖然這樣看起來理所當然,但是好像情況變複雜的話就容易出問題。暫且不提。

如果你搞不清楚上邊的三種情況,那麼請記住,this是call的第一個引數。

  確切地說,call、apply以及bind的第一個引數。關於call、apply和bind的區別很多地方都有寫,這裡簡單提一下,call和apply都是直接呼叫該函式,不同的是call把所有引數一次傳進去,而apply的話,第一個引數是this,第二個引數是函式內部真正需要傳遞的引數構成的陣列(或者是一個偽陣列)。而bind的話,是繫結this並返回一個函式,不會直接進行函式呼叫。

var obj1 = {name: 'wcy'}
var obj2 = {name: 'whw'}
function fn(){
  console.log(this)
}
var fn2 = fn.bind(obj1)
fn2.call(obj2)  //此時即使你傳入了obj2,得到的結果也是obj1,因為fn2的this已經被bind綁定了。

  如果把call呼叫套在上邊的方法中的話,那麼我們可以不需要分類更簡單粗暴地得到this的值。

var obj = {
  'fn': function(){
    console.log(this)
  }
}
var obj1 = {name: 'wcy'}
var obj2 = {name: 'whw'}
var fn2 = obj.fn
obj.fn.call()    
fn2.call()   //call不寫引數,在非嚴格模式下預設值是window,this指向window。在嚴格模式下預設沒有傳引數,所以是undefined。
obj.fn.call(obj)   //call的第一個引數是obj,所以this是obj
fn2.call(obj1)   //call的第一個引數是obj1,所以this是obj1

  那麼,如果call的第一個引數傳的就是this呢?比如下面這樣

function X(){
  return object = {
    name: 'object',
    fn1(x){
      x.fn2.call(this)    //這裡傳入的this指的就是當前的物件,也就是object。如果你不使用call呼叫的話,那麼呼叫的是options中的fn2,輸出結果也是options物件。
    },
    fn2(){
      console.log('A')
      console.log(this)   //A
    }
  }
}
var options = {
  name: 'options',
  fn1(){},
  fn2(){
    console.log('B')
    console.log(this)    //B
  }
}
var x = X()
x.fn1(options)   //此時輸出的結果應該是B  object物件