函数 require

简介: 函数 require

尽管函数 require 也只是一个没什么特殊之处的普通函数,但在 Lua 语言的模块实现中扮演着核心角色。要加载模块时,只需要简单地调用这个函数,然后传入模块名作为参数。请记住,当函数的参数只有一个字符串常量时括号是可以忽略的,而且一般在使用 require 时按照惯例也会省略括号。不过尽管如此,下面的这些用法也是正确的:

local m = require("math")
local modname = "math"
local m = require(modname)


函数 require 尝试对模块的定义做最小的假设。对于该函数来说,一个模块可以是定义了一些变量(比如函数或者包含函数的表达式)的代码。典型地,这些代码返回一个由模块中函数组成的。不过,由于这个动作是有模块的代码而不是由函数 require 完成的,所以某些模块可能会选择返回其他的值或者甚至引发副作用(例如,通过创建全局变量)。


首先,函数 require 在表 package.loaded 中检查模块是否已被加载。如果模块已经被加载,函数 require 就返回相应的值。因此,一旦一个模块被加载过,后续的对于同一模块的所有 require 调用都将返回同一个值,而不会再运行任何代码。


如果模块尚未加载,那么函数 require 则会搜索具有指定模块名的 Lua 文件(搜索路径由变量 package.path 指定,我们会在后续对其进行讨论)。如果函数 require 找到了相应的文件,那么就用函数 loadfile 将其进行加载,结果是一个我们称之为加载器的函数(加载器就是一个被调用时加载模块的函数)。


如果函数 require 找不到指定模块名的 Lua 文件,那么它就搜索相应名称的 C 标准库(在这种情况下,搜索路径由变量 package.cpath 指定)。如果找到了一个 C 标准库,则使用底层函数 package.loadlib 进行加载,这个底层函数会查找名为 luaopen_modname 的函数。在这种情况下,加载函数就是 loadlib 的执行结果,也就是一个被表示为 Lua 函数的 C 语言函数 luaopen_modname


不管模块是在 Lua 文件还是 C 标准库中找到的,函数 require 此时都具有了用于加载它的加载函数。为了最终加载模块,函数 require 带着两个参数调用加载函数:模块名加载函数所在文件的名称(大多数模块会忽略这两个参数)。如果加载函数有返回值,那么函数 require 会返回这个值,然后将其保存在表 package.loaded 中,以便与将来在加载同一模块时返回相同的值。如果加载函数没有返回值且表中的 package.loaded[@rep{modname}] 为空,函数 require 就假设模块的返回值是 true 。如果没有这种补偿,那么后续调用函数 require 时将会重复加载模块。


强制函数 require 加载同一模块两次,可以先将模块从 package.loaded 中删除:

package.loaded.modname = nil


下一次再加载这个模块时,函数 require 就会重新加载模块。


对于函数 require 来说,一个常见的抱怨就是它不能给待加载的模块传递参数。例如,数学模块可以对角度和弧度的选择增加一个选项:

-- 错误的代码
local math = require("math", "degree")


这里的问题在于,函数 require 的主要目的之一就是避免重复加载模块。一旦一个模块被加载,该模块就会在后续所有调用 require 的程序部分被复用。这样,不同参数的同名模块之间就会产生冲突。如果真的需要具有参数的模块,那么最好使用一个显式的函数来设置参数,例如:

local mod = require "mod"
mod.init(0, 0)


如果加载函数返回的是模块本身,那么还可以写成:

local mod = require "mod".init(0, 0)


注意

模块在任何情况下只加载一次,至于如何处理冲突的加载,取决于模块自己。

目录
相关文章
|
6月前
|
JavaScript 前端开发
JS require 与 import 的区别
JS require 与 import 的区别
182 1
|
6月前
|
JavaScript 前端开发
JS中 require 与 import 的区别
JS中 require 与 import 的区别
|
28天前
|
JavaScript 前端开发
require
【10月更文挑战第24天】
26 5
|
6月前
nrm 安装后报错 Error [ERR_REQUIRE_ESM]: require() of ES Module
nrm 安装后报错 Error [ERR_REQUIRE_ESM]: require() of ES Module
603 0
|
6月前
|
JavaScript 前端开发
js的check函数
js的check函数
39 1
|
JavaScript
vite无法使用require,require is not defined
vite无法使用require,require is not defined
540 0
|
缓存 JSON 移动开发
深入解析require源码,知其根,洞其源
深入解析require源码,知其根,洞其源
424 1
深入解析require源码,知其根,洞其源
|
缓存 JavaScript 前端开发
require() 方法详解
在 NodeJS 中有一个方法是我们使用频率最高的,那就是 require 方法。NodeJs 遵循 CommonJS 规范,该规范的核心是通过 require来加载其他依赖的模块。
549 0
require() 方法详解
|
JavaScript 前端开发 Java
碰到Cannot find module了吗? 来看看require函数与NodeJS模块加载
目录 下面谈谈require函数 先搞清楚是什么 require能用来干什么? 非内置的模块,也想用require来加载怎么做? require函数加载原理 那么在npm registry上的库,怎么进行加载? 好了,前面提了几个围绕了是否重新开一个NodeREPL终端来require JS库的问题 解答”Cannot find module"问题 解答是否需要重启Node REPL 或者修改代码是否需要重启正在的NodeJS进程的问题 解答为何npm install lodash之后为何能够直接在node终端直接require 构建代码共享,开源文化 总结
1144 0
碰到Cannot find module了吗? 来看看require函数与NodeJS模块加载
RequireJS中的require如何返回模块
  requirejs中定义AMD模块规则如下: define(function(){ var ProductManager={ Create:function(){ console.
1271 0