![](/img/trans.png)
[英]How does use strict impact this keyword in the context of call and apply method of a Function object in Javascript ES5 and ES6
[英]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'
我也知道我可以將fileName
和uniqueId
作為args傳遞,但這不是重點。 這篇文章並不是試圖找到解決方案,而是要了解它為什么不起作用。
這里的混亂就是利用this
里面readSave
。 根據MDN, this
里面的常規函數是調用函數的同一個對象。 因為我在節點上的普通js文件上調用它,所以它是global
。
一切都很好。 如果我檢查函數調用內部的運行, this
是global
並且設置屬性沒有問題。
問題是 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
指的是exports
與readSave3
和你的最后一個代碼相同。 對於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.