注:以下内容均在nodejs环境中执行。 如果只是在浏览器中导出一个js文件,可能会报错,因为exports、require之类的东西都只定义在nodejs下。 在浏览器环境中除非提前导出nodejs相关的核心库,否则会报类似:*** is not Define的错误。
1.JS调用JS
创建 2 个新脚本:JSClassA.js 和 JSClassB.js。 你想在JSClassA.js中调用JSClassB.js的函数,定义如下
JSClassB.js
JSClassB.js
JSClassA.js
JSClassA.js
运行结果:
分析:
1.首先,exports和require都是nodejs核心库的一部分。
虽然exports可以看作是每个脚本特有的模块,但它本质上仍然是一个对象。 然而,导出是一种方便的书写方式。 事实上,exports 是对 module.exports 对象的引用。 然而nodejs提供了这么一句糖,这样我们就不需要每次都添加module了。
上面JSClassB.js中的写法其实就是给exports对象添加属性。 这时候执行javascript代码,如果我们在JSClassB的末尾添加一行代码,在控制台输出exports对象,我们就会听到这个对象的结构:
require函数的作用是同步返回里面的exports对象。 在JSClassA中接收到这个对象后,就可以直接使用上面的属性了。
2. TS调用JS
在 TS 中引用 JS 的属性、函数和类通常有两种形式:import 和 require。
import:按照老习惯,我们在ts脚本中总是使用import来导出js脚本。比如下面2个脚本: TSClassA.ts引用了JSClassB.js脚本中的东西
JSClassB.js
JSClassB.js
TSClassA.ts
TSClassA.ts
运行结果如下:
从里面第一行代码可以看出,如果想引用那个属性,就可以导入那个属性,但是还有另一种形式:
运行结果和之前一样。 那么这两种形式有什么区别呢? 我们可以通过查看ts编译成js的代码来判断。 以下是编译后的js代码,有两种形式:
从最终生成的js代码可以看出:没有什么区别。 这和js引用js是一样的原理。 毕竟最后是运行js代码,这个也不难理解。
由此我们可以得出一个推论,其实ts指的是js,原理和js指的是js是一样的,只是写法不同,只要我们掌握了最终的js方法,就可以了不难理解。
所以也可以理解为什么ts引用js还有一种方式:使用require。 我们不妨更改 TSClassA.ts
TSClassA.ts
从前面3张图可以看出,编辑器中require的写法似乎是错误的,但ts编译器仍然正确编译了js代码,输出结果也是正确的。
所以虽然我们完全可以忽略哪些ts句型,但是即使我们在ts脚本中写了js代码,只要不影响ts编译器的编译结果,我们想怎么写就怎么写执行javascript代码,因为最后ts会转化为js,所以ts调用js的问题依然会转化为js调用js的问题。
所以,我们必须把握一个前提:记住js的语法规则,不要写出连nodejs和es5都看不懂的东西。
3.JS调用TS
有一个ts脚本TSClassB.ts如下。 该脚本分别导入属性、函数和类。 我们希望在JSClassC.js中调用它上面的东西
TSClassB.ts
在分析这个问题之前,我们先回顾一下上面提到的一个重要推论:ts调用js的问题依然会转化为js调用js的问题。
按照这个推断,js调用ts最终还是js调用js,所以我们需要看一下之前编译成ts脚本的js代码,然后按照js调用js的句型来编译js脚本。
注意绿色箭头的内容,ts中的export最终会翻译成exports的写法,那么问题就简单了,只需使用require同步导出module.exports对象即可。
以下是JSClassC.js的代码
JSClassC.js
运行结果:
结果完全符合预期。