导入(Import)导出(Export)的内存模型及原理

  1. 导入(Import)的内存模型及原理

    • 内存布局

      • 当使用import语句(如import MyTreeTableWrapper from '@/service/prd/test/MyTreeTableWrapper.js';)时,JavaScript引擎会在内存中为导入的模块创建一个模块环境记录(Module Environment Record)。这个记录包含了模块导出的绑定(bindings)信息。
      • 在模块加载过程中,JavaScript引擎会解析被导入的模块文件。对于像MyTreeTableWrapper这样的导入,它会查找模块内部定义的变量、函数、类等,并在模块环境记录中创建相应的引用。
    • 指针关系

      • 导入的模块实际上是通过引用(指针)来访问的。例如,当你在当前模块中使用MyTreeTableWrapper时,你并不是复制了整个MyTreeTableWrapper模块的内容到当前模块的内存空间,而是创建了一个指向被导入模块的指针。这个指针指向被导入模块的模块环境记录,这样当你访问MyTreeTableWrapper中的内容时,实际上是通过这个指针找到被导入模块中的相应定义。
    • 内存管理

      • 模块只被加载和解析一次,无论它被导入多少次。这意味着在内存中只有一份模块代码的实例。如果多个模块导入同一个模块,它们共享这个模块在内存中的实例,通过各自的模块环境记录中的引用来访问。这有助于节省内存,避免不必要的代码重复加载。
  2. 导出(Export)的内存模型及原理

    • 内存布局

      • 在定义模块(如MyTreeTableConstructor模块)时,当使用export关键字(例如export default MyTreeTableConstructor;),JavaScript会将被导出的内容标记为可被外部访问的。对于默认导出(default),它在模块内部是一个特殊的绑定。在模块的内存环境中,这个被导出的内容(这里是MyTreeTableConstructor函数)被存储在模块特定的内存区域。
    • 指针关系

      • 当模块被导出时,其他模块通过导入获取的是对这个导出内容的引用(指针)。以MyTreeTableConstructor为例,当其他模块导入这个函数时,它们得到的是一个指向MyTreeTableConstructor函数在其原模块内存中的指针。这使得在调用MyTreeTableConstructor时,实际上是在调用原始模块中定义的函数,而不是创建一个副本。
    • 内存管理

      • 被导出的内容在模块的生命周期内存在于模块的内存空间中。如果模块被卸载(在某些支持动态模块加载和卸载的环境中),相关的内存资源可能会被回收,但只要模块存在于内存中(例如在一个长期运行的应用程序中),其导出的内容就可供其他模块通过导入使用。

总的来说,JavaScript的导入和导出机制通过引用(指针)来管理模块间的交互,以提高内存使用效率并确保模块的独立性和可维护性。

// 创建一个类来作为MyTreeTable的构造函数
import {defineComponent, h} from "vue";
import TreeTable from "primevue/treetable";
import Column from "primevue/column";

class MyTreeTableWrapper {

  constructor(properties) {
    // 创建一个新的MyTreeTable组件实例
    const MyTreeTableInstance = defineComponent({
      validProperties: ['mytreeData', 'property2', 'property3'],
      name: 'MyTreeTable',
      components: {
        TreeTable,
        Column
      },

      //在Vue 3的setup函数中,this是未定义的,因为setup函数是在组件实例被创建之前执行的,因此没有this上下文。
      setup() {
        // 接受外部的赋值
       let  non_TreetableData_object_param_list=[];
       let  treeData=[];
         const to_TransformData=()=> {
          treeData = transformData(non_TreetableData_object_param_list);
        };
        const transformData=  (data)=> {
          const transform = (arr, parentKey = '') => {
            return arr.map((item, index) => {
              const newKey = parentKey? `${parentKey}-${index}` : `${index}`;
              const newItem = {
                key: newKey,
                data: {
                  id_cases: item.id_cases,
                  id_param: item.id_param,
                  object_Name: item.object_Name,
                  type: item.type,
                  desc: item.desc,
                  is_object: item.is_object,
                  required: item.required,
                  rule: item.rule
                },
                children: item.children? transform(item.children, newKey) : []
              };
              return newItem;
            });
          };
          return transform(data);
        };
       const  displayNameBasedOnId= (typeId)=> {
          const typeMap = [
            { name: "文本", id: 1 },
            { name: "日期", id: 2 },
            { name: "文本域", id: 3 },
            { name: "数值", id: 4 },
            { name: "文件", id: 5 },
            { name: "限选项", id: 6 },
            { name: "其他", id: 7 }
          ];
          for (let i = 0; i < typeMap.length; i++) {
            if (typeMap[i].id === typeId) {
              return typeMap[i].name;
            }
          }
          return "未定义类型";
        };
        if (properties) {
          for (let prop in properties) {
            if (['mytreeData', 'property2', 'property3'].includes(prop)) {
              non_TreetableData_object_param_list = properties[prop];
              to_TransformData();
            }
          }
        }
        return () =>
          h(TreeTable, { value: treeData, tableStyle: 'min - width: 50rem' }, [
            h(Column, { field: 'object_Name', header: '分类名称', expander: true }),
            h(Column, { field: 'is_object', header: '分类类型' }),
            h(Column, { field: item => displayNameBasedOnId(item.type), header: '参数类型' }),
            h(Column, { field: 'required', header: '是否必须' }),
            h(Column, { field: 'desc', header: '描述' })
          ]);
      }
    });
    return MyTreeTableInstance;
  }
}
export default MyTreeTableWrapper;

import MyTreeTableWrapper  from '@/service/prd/test/MyTreeTableWrapper.js';
// // 使用示例
const MyTreeTable1 = new MyTreeTableWrapper({
  mytreeData:PrdServiceFunCasesInputParameters.zwgetPrdServiceFunCasesInputParameters(),
});
    <Card>
      <template #content>
        <MyTreeTable2></MyTreeTable2>
      </template>
    </Card>
  1. 导入模块时的压栈顺序

    • 当执行import MyTreeTableWrapper from '@/service/prd/test/MyTreeTableWrapper.js';

      • 首先,JavaScript引擎会将MyTreeTableWrapper.js文件加载到内存中。这个过程涉及到文件系统的读取操作(如果是在浏览器环境下,可能是从服务器获取文件内容)。
      • 然后,开始解析文件内容。在解析MyTreeTableWrapper类的定义时,会将类的结构(包括构造函数、内部的方法等)压入执行上下文的解析栈中。对于其中的import语句(如import {defineComponent, h} from "vue";import TreeTable from "primevue/treetable";以及import Column from "primevue/column";),会先暂停当前文件的解析,去加载和解析被导入的模块。
      • import {defineComponent, h} from "vue"为例,引擎会查找vue模块(假设已安装并在模块查找路径内),加载并解析它,将defineComponenth函数的定义压入栈中(或者是创建引用指向它们在vue模块中的定义)。同样的过程也会发生在TreeTableColumn的导入过程中。
  2. 实例化类时的压栈顺序

    • 当执行const MyTreeTable1 = new MyTreeTableWrapper({mytreeData:PrdServiceFunCasesInputParameters.zwgetPrdServiceFunCasesInputParameters()});

      • 首先,会将MyTreeTableWrapper类的构造函数压入执行栈。在构造函数内部:
        • 当执行const MyTreeTableInstance = defineComponent({...})时,defineComponent函数被调用,它内部的逻辑开始执行,相关的函数定义(如setup函数内部定义的to_TransformDatatransformDatadisplayNameBasedOnId等)会被压入执行栈进行解析和执行。
        • setup函数中,当执行if (properties) {...}循环时,根据传入的属性进行操作。如果涉及到函数调用(如to_TransformData函数中的transformData函数调用),这些函数也会被压入执行栈。
        • setup函数中的return () => h(TreeTable, {...})语句执行时,h函数被调用,它内部的逻辑会被压入执行栈,包括对TreeTableColumn组件的渲染逻辑处理。
      • 最后,当MyTreeTableWrapper类的构造函数执行完毕,返回MyTreeTableInstance,这个结果被赋值给MyTreeTable1,此时相关的临时变量(如在构造函数内部定义的局部变量)会从执行栈中弹出,但MyTreeTable1会持有对返回结果的引用。

总体而言,代码的压栈顺序遵循JavaScript的模块加载、解析和函数调用的执行顺序,从外层的模块导入到内层的类实例化和组件构建相关的函数调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值