像數學公式同樣完全簡單理解JavaScript函數調用與this 指針

一直以來,你們都對函數的調用有不少的疑惑,特別是this指針的指向。 其實理解了核心的原理以後,就很容易理解,甚至就是套用數學公式同樣!javascript

核心原理

讓咱們看看原始的函數調用語句,也就是call方法java

function test(param){
     console.log(this + " loves " + param);
}
複製代碼

test.call("Warren", "you") //=> Warren loves you數組

能夠看到,咱們調用了test方法,而且把this指向Warren,傳入參數you。這就是javascript函數調用的核心概念。其餘函數均可以參考這個概念。bash

簡單的函數調用

若果每次調用函數都用call,會變得很麻煩。Javascript容許咱們直接調用test("you"),其實就至關於閉包

function test(param) {
  console.log("loves " + thing);
}

// this:
test("you")

// 至關於:
test.call(window, "you");
複製代碼

可是這個在ECMAScript的strict模式會變成:app

// this:
test("you")

// 至關於:
test.call(undefined, "you");
複製代碼

歸納就是兩條公式:函數

fn(...args) 就至關於 fn.call(window [ES5-strict: undefined], ...args).ui

(function() {})() 就至關於 (function() {}).call(window [ES5-strict: undefined).this

成員函數

另外一種常見的函數調用方法就是obj.test().es5

var obj = {
  name: "Warren",
  test: function(params) {
    console.log(this + " loves " + params);
  }
}

// this:
obj.test("you")

// 至關於:
obj.test.call(obj, "you");
複製代碼

能夠看到this指向了obj,咱們以前是單獨聲明test,再看看若是將它咱們關聯給其餘對象。

test: function(params) {
    console.log(this + " loves " + params);
}
var obj = {
  name: "Warren",
}
obj.test = test;

obj.test("you") 
// 仍然至關於 obj.test.call(test, "you")

test("you") // "[object DOMWindow]you"
複製代碼

this指針根據調用者的變化而變化!

試下Function.prototype.bind

有時候須要根據調用者來改變this指向,這能夠用簡單閉包來實現

var obj = {
  name: "Warren",
  test: function(params) {
    console.log(this + " loves " + params);
  }
}

var boundTest = function(params) { return obj.test.call(obj, params); }

boundTest("you");
複製代碼

套用以前的公式 fn(...args) 就至關於 fn.call(window [ES5-strict: undefined], ...args).

boundTest("you"); => boundTest(window,"you"),可是咱們在boundTest裏面已經將test的this指向了obj!

讓咱們改造一下這個函數:

var bind = function(func, thisValue) {
  return function() {
    return func.apply(thisValue, arguments);
  }
}

var boundTest = bind(obj.test, obj);
boundTest(you) // "Warren loves you"
複製代碼

要理解上面的代碼,只須要知道2點。

  1. apply 與 call的區別只是 apply接受的參數是數組,call接受的參數是參數列表。
  2. arguments 是像類數組的某個函數的全部參數 bind函數返回一個數組,每次調用的時候綁定this而且接受新的參數。

上面只是爲了更好理解,其實es5原本就有一個bind函數

var boundTest = obj.test.bind(obj);
boundTest(you) // "Warren loves you"
複製代碼

以上大概就是JavaScript函數調用與this 指針的基本原理,只要記住這兩條公式,基本就不虛了。

fn(...args) 就至關於 fn.call(window [ES5-strict: undefined], ...args).

(function() {})() 就至關於 (function() {}).call(window [ES5-strict: undefined).

相關文章
相關標籤/搜索