我有这样的代码:
mycode.js:
export default {
foo() {
return "foo";
},
bar() {
return "bar" + this.foo();
}
}
othercode.js:
import mycode from "mycode.js";
mycode.bar(); // usually works fine, returns "barfoo"
但是,我在箭头函数内调用mycode.bar()时遇到了困难。问题是bar()中的“ this”不再引用mycode中的对象,而是引用调用者的上下文。
如果我想继续使用此代码样式来定义函数并导出它们,如何在bar()中调用foo()?
我已经尝试将mycode中的方法绑定()到导出的对象,但是据我所知,您必须对每个方法分别进行此操作。
我也在mycode的顶部尝试这样做:
let self = this;
然后引用“ self.foo()”,但是在我将其分配给self时尚未定义“ this”。
我可以完全更改代码样式。我可以这样定义每个函数:
mycode.js
function foo() {
return "foo";
}
export default {
foo, bar, ...
}
但是我必须分别命名每个功能。
必须有更好的方法。
问题不在于您如何导出;这是this
在JavaScript中的工作方式。如果在作为方法的上下文之外引用函数,则该方法的主体将没有一致的this
,除非您明确绑定了该函数,并且除非有标识符绑定到该对象,否则您将无法进行任何绑定。您可以这样做,例如:
const mod = {
foo() {
return "foo";
},
bar() {
return "bar" + this.foo();
}
};
mod.foo = mod.foo.bind(mod);
mod.bar = mod.bar.bind(mod);
export default mod;
...但是,我敢肯定,这简明扼要。如果使用类和支持类属性的JS版本,则另一种选择是:
class MyModule {
foo: () => "foo";
bar: () => "bar" + this.foo();
}
export default new MyModule();
个人,虽然我不了解您的整体情况,但我认为命名导出更有意义,并使用模块闭包代替this
:
export function foo() {
return "foo";
}
export function bar() {
return "bar" + foo();
}
如果使用命名的导出而不是默认的导出,则可以引用要导出的对象的名称,例如:
export const myMethods = {
foo() {
return "foo";
},
bar: () => {
return "bar" + myMethods.foo();
}
};
请确保也将导入更改为命名导入:
import { myMethods } from 'mycode.js';
您can also导入当前模块(感谢Bergi),尽管看起来非常奇怪:
import myMethods from './mycode.js'; // <--- THE CURRENT FILE
export default {
foo() {
return "foo";
},
bar: () => {
return "bar" + myMethods.foo();
}
}
默认导出的最大问题之一是,除非像上面那样导入当前模块,否则无法引用要导出的内容。如果您使用默认的export and函数是一个箭头函数,则this
将从模块的外部范围继承,因此要导出的对象必须经过奇怪的引用才能被引用如上。
您可以表达或声明您的功能,在文件中内部使用,然后决定将哪些功能制成public(出口)。
由于使用通配符,您可以获得更大的有效负载并添加了不需要的保密层,因此您最好始终命名要导入的所需方法。
通过使用[{named}导入列表,不再有as <alias>
指针,使得this
结果出现在undefined
中
PS:导出属性时为get rid of the default
default
使用表达式 命名进口:
// foo.mjs
function foo() {
return "foo";
}
function bar() {
console.log(this); // undefined
return "bar" + foo();
}
export {
foo,
bar
}
运行// index.mjs
import { bar } from './foo.mjs';
console.log(bar()); // "barfoo"
,您将在日志$ node --experimental-modules ./index.mjs
中看到
"barfoo"
Careful:通配符导入会将* as alias
引用为常数this
alias导入as
[Module]
// foo.mjs
function foo() {
return "foo";
}
function bar() {
console.log(this) // [Module] { bar: [Function: bar], foo: [Function: foo] }
return "bar" + this.foo(); // `this` points to the importing [Module] alias
// ANTIPATTERN, and can result in undefined if imported as a named list
}
export {
foo,
bar
}
易碎,容易出错,因为如果使用类似// index.mjs
import * as test from './foo.mjs';
console.log(test.bar()); // "barfoo" - but thanks to the wildcard and alias
的命名导入,可能会导致
TypeError:无法读取未定义的属性'foo'
并且应避免。
链接:
import { bar } from "./foo.mjs"; console.log(bar());
https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
问题不在于您如何导出;这是this
在JavaScript中的工作方式。如果在作为方法的上下文之外引用函数,则该方法的主体将没有一致的this
,除非您明确绑定了该函数,并且除非有标识符绑定到该对象,否则您将无法进行任何绑定。您可以这样做,例如: