You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PyScript中更优地初始化并调用JavaScript类?

优化PyScript调用JavaScript类实例的方案

问题描述

希望完全通过PyScript初始化JavaScript类并调用其方法,当前实现用单例工厂类MyClassFactory跟踪MyClass实例,再通过useMyClass函数封装供PyScript调用,但觉得流程繁琐,寻求更简洁的实现方式。

现有实现代码

<head>
  <meta charset="UTF-8">
  <script defer src="https://pyscript.net/latest/pyscript.js"></script>
</head>
<body>
<script>
  class MyClass {
    constructor() {
      this.hi_count = 0;
    }
    sayHi() {
      if (this.hi_count === 0) {
        document.write('Hi<br>')
      } else {
        document.write('Hi Again<br>')
      }
      this.hi_count++
    }
  }
  class MyClassFactory {
    constructor() {
      if (MyClassFactory.instance) {
        return MyClassFactory.instance;
      }
      this.myClasses = new Map();
      MyClassFactory.instance = this;
    }

    createMyClass(id) {
      if(this.myClasses.has(id)) {
        return this.myClasses.get(id);
      } else {
        const myClass = new MyClass();
        this.myClasses.set(id, myClass);
        return myClass;
      }
    }
  }
  function useMyClass(id, method) {
    const myClassFactory = new MyClassFactory();
    const myClass = myClassFactory.createMyClass(id);
    myClass[method]();
  }

</script>
<py-script>
  import js
  js.useMyClass(1,"sayHi")  # Creates new instance and calls sayHi method
  js.useMyClass(2,"sayHi")  # Creates new instance and calls sayHi method
  js.useMyClass(1,"sayHi")  # Uses existing instance with id 1 and calls sayHi method
</py-script>
</body>
</html>

优化方案

方案1:简化JS侧实例管理,直接返回实例给PyScript

去掉冗余的工厂类,用全局Map直接管理MyClass实例,提供一个获取实例的函数,让PyScript能直接拿到实例引用,灵活调用方法或访问属性:

<head>
  <meta charset="UTF-8">
  <script defer src="https://pyscript.net/latest/pyscript.js"></script>
</head>
<body>
<script>
  class MyClass {
    constructor() {
      this.hi_count = 0;
    }
    sayHi() {
      document.write(this.hi_count === 0 ? 'Hi<br>' : 'Hi Again<br>');
      this.hi_count++;
    }
    // 新增方法示例,PyScript可直接调用
    getHiCount() {
      return this.hi_count;
    }
  }

  // 全局Map存储实例,替代工厂类逻辑
  const myClassInstances = new Map();

  // 暴露获取实例的函数给全局
  window.getMyClassInstance = function(id) {
    if (!myClassInstances.has(id)) {
      myClassInstances.set(id, new MyClass());
    }
    return myClassInstances.get(id);
  };
</script>
<py-script>
  import js

  // 获取实例后直接调用方法,逻辑更直观
  instance1 = js.getMyClassInstance(1)
  instance1.sayHi()

  instance2 = js.getMyClassInstance(2)
  instance2.sayHi()

  // 复用实例并调用其他方法
  instance1.sayHi()
  print(f"Instance 1 hi count: {instance1.getHiCount()}")
</py-script>
</body>
</html>

方案2:PyScript侧完全管理实例,JS仅暴露类

把MyClass暴露给全局,让PyScript直接初始化实例,并用Python字典管理实例,彻底简化JS侧代码,完全实现PyScript掌控初始化流程:

<head>
  <meta charset="UTF-8">
  <script defer src="https://pyscript.net/latest/pyscript.js"></script>
</head>
<body>
<script>
  class MyClass {
    constructor() {
      this.hi_count = 0;
    }
    sayHi() {
      document.write(this.hi_count === 0 ? 'Hi<br>' : 'Hi Again<br>');
      this.hi_count++;
    }
  }

  // 将类暴露给全局,供PyScript访问
  window.MyClass = MyClass;
</script>
<py-script>
  import js

  // Python侧用字典管理实例,完全掌控初始化逻辑
  my_instances = {}

  def get_my_class(instance_id):
      if instance_id not in my_instances:
          // 通过js.MyClass.new()创建JS类实例
          my_instances[instance_id] = js.MyClass.new()
      return my_instances[instance_id]

  // 使用示例
  inst1 = get_my_class(1)
  inst1.sayHi()

  inst2 = get_my_class(2)
  inst2.sayHi()

  inst1.sayHi()
</py-script>
</body>
</html>

两种方案的优势:

  • 方案1保留JS侧实例管理,但去掉了冗余的工厂类结构,PyScript能直接操作实例,扩展性更强;
  • 方案2将实例管理完全交给PyScript,JS仅负责定义类,完全符合“通过PyScript初始化”的需求。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:33:19