簡體   English   中英

在Javascript ES6中調用對象方法的函數中解釋'this'的使用

[英]Explain use of 'this' inside a function that calls an object method in Javascript ES6

我正在嘗試處理一些json並將數據寫入幾個文件。

所以我有一個函數來創建基於json數據和一些文字的文件夾/文件。 文件名由包含不同類別的對象定義:

const folders = {
    category1: {
        fileName: 'default',
        path : '/path',
        subpath : () => `/subpath/${this.fileName}${this.uniqueId}`
    }
}

這是你一半會跳一步,告訴我,箭頭功能無法看到this自己的對象等。我知道,這就是故意的,因為我會得到以后必要的數據。

主要功能遵循以下模式:

function readSave() {
    //suppose readFileSync would return a string 'filename' and an int 1029

    this.fileName = 'filename'; 
    this.uniqueId = 1029;

    let filePath = folders.category1.path + folders.category1.subpath();

    // I'd go on to write stuff to that file but for now let's just return
    return filePath;
}

readSave() 
// returns '/path/subpath/undefinedundefined'
// expected '/path/subpath/filename1029'

我也知道我可以fileNameuniqueId作為args傳遞,但這不是重點。 這篇文章並不是試圖找到解決方案,而是要了解它為什么不起作用。

這里的混亂就是利用this里面readSave 根據MDN, this里面的常規函數​​是調用函數的同一個對象。 因為我在節點上的普通js文件上調用它,所以它是global

一切都很好。 如果我檢查函數調用內部的運行, thisglobal並且設置屬性沒有問題。

問題是 folders.category1.subpath()計算結果為undefined

調試器顯示何時轉到evaluate () => /subpath/${this.fileName}${this.uniqueId}this不再是global ,而是一個空的Object。 該文檔讓我覺得箭頭功能應該繼承this它被稱為范圍,這是readSave ,這意味着this應該是global

為了增加我的困惑,在函數外部設置屬性可以完美地工作:

function readSave2() {
   let filePath = folders.category1.path + folders.category1.subpath();
   return filePath;
}

this.fileName = 'filename'; 
this.uniqueId = 1029;

readSave() 
// returns '/path/subpath/filename1029'

檢查上面的代碼,一切都() => /subpath/${this.fileName}${this.uniqueId} ,直到它進入evaluate () => /subpath/${this.fileName}${this.uniqueId} 現在,以前空的Object在設置時有兩個屬性。

最后,這也與前一個示例完全相同:

const readSave3 = () => {
    this.fileName = 'filename'; 
    this.uniqueId = 1029;
    let filePath = folders.category1.path + folders.category1.subpath();
    return filePath;
}

我已經瀏覽並閱讀了幾個小時,但我仍然感到困惑,為什么有些方法有效,有些方法無效。

提前致謝

更新 :結果我對Node的根對象在給定文件或函數調用中做了一些錯誤的假設。 真的不知道模塊包裝器。

這個doc使我認為arrow函數應該繼承它所調用的范圍,即readSave,這意味着它應該是全局的。

在創建箭頭功能時,不會確定箭頭功能的this

[...]無論什么,Foo的this設置為創建時(在上面的例子中,全局對象),這是什么。 這同樣適用於其它箭頭函數中創建的功能:他們this 仍然是封閉詞匯方面的 [...]。

所以this箭頭功能指的是什么this是在這里:

console.dir(this) // <----  refers to `exports`
const folders = {
    category1: {
        fileName: 'default'
        path : '/path',
        subpath : () => `/subpath/${this.fileName}${this.uniqueId}`
    }
}

this兩個代碼塊的this引用了同一個對象,原因完全相同:

console.dir(this) // the `this` in the arrow function below is the same as here
                  // and `this` refers to `exports`
const readSave3 = () => {
    this.fileName = 'filename'; 
    this.uniqueId = 1029;

    // ...
}

readSave3()
function readSave() {
   // ...
}

this.fileName = 'filename'; 
this.uniqueId = 1029;

readSave() 

在加載時,節點文件的內容被包裝成:( 模塊包裝器

(function(exports, require, module, __filename, __dirname) {
   /*... filecontent ... */
})

然后調用該函數作為參數傳遞相應的值,並作為exports函數傳遞的對象調用該函數。 在Node.js中的根對象是什么

所以對於/subpath/${this.fileName}${this.uniqueId} this指的是exportsreadSave3和你的最后一個代碼相同。 對於readSave (第一個), this指的是全局對象。

所以對於節點,你的代碼看起來像這樣:

var moduleSetup = function(exports, require, module, __filename, __dirname) {
  // here `this` is exports 

  const folders = {
    category1: {
      fileName: 'default',
      path: '/path',
      // `this`referes to exports due to arrow function
      subpath: () => `/subpath/${this.fileName}${this.uniqueId}`
    }
  }


  function readSave1() {
    // here `this` refers to `global` because `readSave1` is not called on an object

    //suppose readFileSync would return a string 'filename' and an int 1029

    this.fileName = 'filename';
    this.uniqueId = 1029;

    let filePath = folders.category1.path + folders.category1.subpath();

    // I'd go on to write stuff to that file but for now let's just return
    return filePath;
  }

  readSave1()


  function readSave2() {
    let filePath = folders.category1.path + folders.category1.subpath();
    return filePath;
  }

  // `this` refers to `exports`
  this.fileName = 'filename';
  this.uniqueId = 1029;

  readSave2()


  const readSave3 = () => {
    // `this` refers to `exports` due to arrow function
    this.fileName = 'filename';
    this.uniqueId = 1029;

    let filePath = folders.category1.path + folders.category1.subpath();
    return filePath;
  }
  readSave3()
}

// and that's roughly how node would invoce that function:
var module = {
  exports: {}
}

moduleSetup.call(module.exports, // moduleSetup called on module.exports
                 // with these arguments:
                 module.exports, require, module, theFileName, theDirname)

this總是指出當前的背景。 當箭頭函數將執行this更改到其當前上下文時(在您的情況下)是箭頭函數。 所以this箭頭功能內外的箭頭功能不是相同他們在不同的上下文中this

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM