加勒比HEZYO黑人专区-久久精品国产99国产精品亚洲-精品国产18久久久久久-久久人妻少妇嫩草AV

歡迎光臨 織晶網絡官網!

  • 服務支持
  • 020-39182790
技術文檔您現在的位置:首頁 > 服務支持 > 技術文檔

從指向看JavaScript中的一些難點

作者:織晶客服部   發布于:2017/7/27 18:39:49  點擊量:  來源:織晶網絡

很多人剛剛接觸前端甚至一些“老”前端都經常會在JavaScript中所謂的難點,如this,原型,繼承,閉包等這些概念中迷失了自我。接下來這篇文章會把我自己對于JavaScript中這些點通過指向的概念做個總結并分享給大家,希望可以幫助大家更好的了解這些所謂的難點。

一、this

this是什么?其實它本身就是一種指向。this指向可以分為以下幾種情況

·         普通調用,this指向為調用者

·         call/apply調用,this指向為當前thisArg參數

·         箭頭函數,this指向為當前函數的this指向

這個怎么理解呢?接下來我會一一做解析。

1、普通調用

通俗理解一下,就是誰調用,則this便指向誰。這里又大致分為幾種情況,分別為

1.1、對象方法的調用

即某方法為某對象上的一個屬性的屬性,正常情況當改方法被調用的時候,this的指向則是掛載該方法的對象。廢話不多說,直接看代碼可能會更好的理解。

var obj = {
  a: 'this is obj',
  test: function () {
    console.log(this.a);
  }
}
obj.test();
// this is obj

1.2、“單純”函數調用

即該函數為自己獨立的函數,而不是掛載到對象上的屬性(window除外),也不會被當成構造函數來使用,而僅僅是當成函數來使用,此時的this指向則是window對象。例子如下

var a = 'this is window'
function test () {
  console.log(this.a);
}
test();
// this is window

這個我們來理解一下,其實也很簡單,我們都知道,window對象是全局對象。其實整個代碼塊等同于

window.a = 'this is window'
window.test = function test () {
  console.log(this.a);
  // 此時是window為調用者,即this會指向window
}
window.test();

1.3、構造函數調用

即該函數被當成構造函數來調用,此時的this指向該構造器函數的實例對象。我們來看一個例子,先上一個屬于第二種情況的例子

function test () {
  this.a = 'this is test';
  console.log(this.a);
  console.log(this);
}
test();
// this is test
// Window {}

按照上面的來理解,此時的this的確指向window對象,但是如果我換種形式,將其換成構造函數來調用呢,結果又會如何呢,直接上代碼

function Test () {
  this.a = 'this is test';
  console.log(this.a);
  console.log(this);
}
var test = new Test();
// this is test
// Test {a: 'this is test'}

OK,好像的確沒有問題了,此時的this的確指向了該構造函數的實例對象。具體這里的一些解釋后面我會在原型鏈繼承里面詳細講解。

2、call/apply調用

2.1、call調用

call方法形式,fun.call(thisArg[, arg1[, arg2[, ...]]])

thisArg,當前this指向

arg1[, arg2[, ...]],指定的參數列表

詳細介紹請猛戳MDN

示例代碼如下

function Test () {
  this.a = 'this is test';
  console.log(this.a);
  console.log(this);
}
function Test2 () {
  Test.call(this);
}
var test = new Test2();
// this is test
// Test2 {a: 'this is test'}

2.2、apply調用

和call類似,唯一的一個明顯區別就是call參數為多個,apply參數則為兩個,第二個參數為數組或類數組形式, fun.apply(thisArg, [argsArray])

thisArg,當前this指向

一個數組或者類數組對象,其中的數組元素將作為單獨的參數傳給fun函數

詳細介紹請猛戳MDN

但是終究apply里面的數組參數會轉變為call方法的參數形式,然后去走下面的步驟,這也是為什么call執行速度比apply快。這邊詳情有篇文章有介紹,點擊鏈接。

另外,提及到call/apply,怎么能不提及一下bind呢,bind里面的this指向,會永遠指向bind到的當前的thisArg,即context上下文環境參數不可重寫。這也是為什么a.bind(b).call(c),最終的this指向會是b的原因。至于為什么,其實就是bind實現實際上是通過閉包,并且配合call/apply進行實現的。具體的請參考bind MDN里面的用法及 Polyfill實現。

3、箭頭函數

首先需要介紹的一點就是,在箭頭函數本身,它是沒有綁定本身的this的,它的this指向為當前函數的this指向。怎么理解呢,直接上個代碼看下

function test () {
  (() => {
    console.log(this);
  })()
}
test.call({a: 'this is thisArg'})
// Object {a: 'this is thisArg'}

這樣看聯想上面的call/apply調用的理解,好像是沒有問題了,那如果我設置一個定時器呢,會不是this指向會變成Window全局對象呢?答案肯定是不會的,因為箭頭函數里面的this特殊性,它依舊會指向當前函數的this指向。不多BB,直接看代碼

function test () {
  setTimeout(() => {
    console.log(this);
  }, 0)
}
test.call({a: 'this is obj'})
// Object {a: 'this is obj'}

當然普通函數使用setTimeout的話會讓this指向指向Window對象的。demo代碼如下

function test () {
  setTimeout(function () {
    console.log(this);
  }, 0)
}
test.call({a: 'this is obj'})
// Window {...}

這里可能會牽扯到setTimeout的一些點了,具體這里我就不講了,想深入了解的猛戳這里

箭頭函數里面還有一些特殊的點,這里由于只提及this這一個點,其他比如不綁定arguments,super(ES6),抑或 new.target(ES6),他們都和this一樣,他會找尋到當前函數的arguments等。

關于箭頭函數里面的this這里也有詳細的介紹,想深入了解的可以自行閱讀。




上一篇:HTML5新技術,離線緩存

下一篇:學習Linux系統的優勢及幾點建議