声明var的澄清

时间:2019-01-25 15:45:38

标签: javascript node.js

我有2个js类,我需要同时在后端和前端上运行。为此,我写了这张支票(在module.exports之前有一张类似的支票):

// in foo.js
class foo {
  constructor(){...}
  fooMethod(){...}
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
    module.exports = foo;
else
  window.foo = foo



// in bar.js
if (typeof require !== 'undefined' ){
  var foo = require('./foo.js');
  var baz = require('baz_module')
  // note, baz is loaded from a cdn on the front-end. 
  // I wrote some extension functions here
}

// error still happens if I don't do anything here
baz.prototype.myFunction = function(){ ... }

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
  module.exports = baz;
else
  window.baz = baz

index.html

<script src="http://cdn.com/baz"></script>
<script src="./path/to/foo.js"></script>
<script src="./path/to/bar.js"></script>

问题是当将此文件加载到前端时,出现错误: Identifier 'foo' has already been declared。这是有道理的,因为文件foo.js已经运行。

我尝试交换浏览器加载文件的顺序(bar之前的foo),但是遇到相同的错误。 console.log(foo)undefined中返回bar,而不是预期的ReferenceError: foo is not defined

我的困惑是为什么var foo ...行即使在if语句为false的情况下也行?我的期望是var声明应与脚本的其余部分内联运行

1 个答案:

答案 0 :(得分:0)

var声明被提升到if块作用域之外。您在class foo声明中遇到错误,抱怨foo已被全局声明。

一种解决方案是仅对全局变量(即var)使用function(和var foo = class foo {…};)。但是,imo真正的问题是,您根本使用的是全局变量,而不是某些模块系统。您应该将模块放在IIFE中,并让模块系统检查代码将IIFE返回值作为导出处理。或者更好的是,不要自己编写该校验代码,而是使用ES6模块语法并将其模块(例如,使用Rollup进行转换)到UMD format中,这正是为您完成的。