在JS模块中公开对象方法时,如何管理上下文



好吧,我意识到这可以被认为是主观的,但我正在努力更好地理解在编写只公开所需内容的模块时如何考虑范围。我有一个字符串实用程序,我在下面写了一个对象文字:

const substrings = {
query: {},
text: "",
results: [],
exists: function (index) {
const exists = index >= 0
return exists
},
check: function () {
const q = this.query
const start = q.openIndex
const stop = q.closeIndex
if (q.hasOpen && !q.hasClose) {
console.log("Missing closing delimiter.")
}
if (!q.hasOpen && q.hasClose) {
console.log("Missing opening delimiter.")
}
if (q.hasOpen && q.hasClose && start > stop) {
console.log("Closing delimiter found before opening.")
}
if (!q.hasOpen && !q.hasClose && this.results.length == 0) {
console.log("No results found.")
}
const order = start < stop
const check = q.hasOpen && q.hasClose && order
return check
},
update: function () {
const q = this.query
const text = this.text
q.before = this.text.indexOf(q.open)
q.start = q.before + q.open.length
this.text = text.slice(q.start, text.length)
q.stop = this.text.indexOf(q.close)
q.after = q.stop + q.close.length
q.openIndex = q.before
q.closeIndex = q.before + q.stop
q.hasOpen = this.exists(q.openIndex)
q.hasClose = this.exists(q.stop)
const newPosition = q.start + q.after
q.position = q.position + newPosition
this.query = q
},
substrings: function () {
const q = this.query
const current = this.text.slice(0, q.stop)
const fullLength = this.text.length
this.text = this.text.slice(q.after, fullLength)
this.results.push(current)
this.update()
if (this.check()) {
this.substrings()
}
},
init: function (open, close, text) {
this.results = []
this.query = {
open,
close,
position: 0,
}
this.text = text
this.update()
},
getSubstrings: function (open, close, text) {
this.init(open, close, text)
if (this.check()) {
this.substrings()
return this.results
}
},
getSubstring: function (open, close, text) {
this.init(open, close, text)
if (this.check()) {
return this.text.slice(0, this.query.stop)
}
}
}

我想把它用作Node模块,并公开getSubstringgetSubstrings方法,但如果我要这样做:

module.exports = {
all: substrings.getSubstrings,
one: substrings.getSubstring
}

由于使用了this,我会遇到一个错误。我意识到,如果我用对象var名称substrings替换this来直接引用它,它就可以工作了。我也可以将它重构为一个大函数或更小的函数,然后只导出我需要的2个。

我正在努力以正确的方式学习,并努力思考我应该如何思考上下文。我理解this在这里的变化,但我觉得在构建代码时,我并没有完全考虑到应该如何考虑上下文。

有没有一个更优雅的解决方案可以用这样的代码来公开方法,而这些代码并不是用来分离私有和公共方法的?

一个简单的解决方案是将导出的函数bindexports对象内的正确调用上下文:

module.exports = {
all: substrings.getSubstrings.bind(substrings),
one: substrings.getSubstring.bind(substrings)
}

就我个人而言,在这种情况下,我更喜欢使用揭示模块模式而不是对象文字。使用揭示模块模式,创建一个返回所需函数的IIFE,引用局部变量,而不是this上的属性。例如:

const { getSubstrings, getSubstring } = (() => {
let query = {}
let text = ''
let results = []
function exists(index) {
return index >= 0
}
function check() {
const q = query;
// ...
}
...
function getSubstrings(open, close, text) {
}
...
return { getSubstrings, getSubstring };
})();
module.exports = {
all: getSubstrings,
one: getSubstring
}

这在一定程度上是基于观点的,但当没有任何this引用需要担心时,代码会更容易阅读。

最新更新