javascript - 提高 JavaScript 中工厂模式的内存效率

标签 javascript performance memory prototype factory

JavaScript 的“对象”(实际上是一个映射)概念的简单性和灵 active 一直吸引着我。因此,我更愿意完全避免“对象原型(prototype)”(和“类”,它们只是对象原型(prototype)的语法糖)的概念,而选择工厂模式。

我看到这篇文章,指出与工厂模式相比,对象原型(prototype)可以节省内存:https://medium.freecodecamp.org/class-vs-factory-function-exploring-the-way-forward-73258b6a8d15

"All methods will be created only once in the prototype object and shared by all instances"

假设我有一个网页,它多次调用以下函数来“实例化”许多 AnglePointer 对象:

var AnglePointer = function() {
    var privateMembers = {};
    privateMembers.angle = 0;

    var self = {};

    self.turn = function(degrees) {
        privateMembers.angle += degrees;
        while (privateMembers.angle > 359) {
            privateMembers.angle -= 360;
        }
        while (privateMembers.angle < 0) {
            privateMembers.angle += 360;
        }
    };

    return self;
};

我可以通过引入如下所示的“共享”对象来提高内存效率吗?

var AnglePointer = (function() {
    var sharedMembers = {};

    sharedMembers.turn = function(self, privateMembers, degrees) {
        privateMembers.angle += degrees;
        while (privateMembers.angle > 359) {
            privateMembers.angle -= 360;
        }
        while (privateMembers.angle < 0) {
            privateMembers.angle += 360;
        }
    };

    return function() {
        var privateMembers = {};
        privateMembers.angle = 0;

        var self = {};

        self.turn = function(degrees) {
            shared.turn(self, privateMembers, degrees);
        };

        return self;
    };
})();

在第二个版本中,turn 函数的实现位于 sharedMembers 对象内部,使得 AnglePointer 的每个“实例”仅包含一个小的单行函数调用共享功能。这会实现与对象原型(prototype)类似的内存效率吗?或者,尽管每个实例的 turn 函数是单行函数,但它会占用与以前一样多的内存吗?如果是后者,对象原型(prototype)如何避免这个问题?

最佳答案

with just a small one-line function calling the shared function

这是基于错误的信念,即将为每个对象创建一个新函数。那是错的。代码中的所有函数仅被解析一次并且仅存在一次。每次创建时都会创建一个新的闭包(规范将其称为EnvironmentRecord)。如果函数敌人不访问任何外部变量,则可以优化此闭包,使其内存效率更高(并且可能更快)。

因此,你的“新模式”实际上让事情变得更糟(但只是一点点)。主要问题仍然是:

self.turn = function(degrees) {
   shared.turn(self, privateMembers, degrees);
};

这是无法优化的,因为该函数使用其父级作用域中的变量,因此必须创建一个闭包。因此,每个 turn 方法都必须有一个闭包,并且每个对象都必须保留对其自己的闭包 turn 的引用。

使用符号可以非常准确地实现私有(private)成员:

const angle = Symbol.for("angle");

function AnglePointer() {
  return {
   [angle]: 0,
   turn(degrees) {
     this[angle] = (this[angle] + degrees) % 360;
   },
  };
}

这里的turn有望被共享,因为它不访问任何外部变量。

关于javascript - 提高 JavaScript 中工厂模式的内存效率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54989048/

相关文章:

Javascript 日期格式显示不正确的小时

javascript - 将非文本数据粘贴到基于浏览器的应用程序中

algorithm - Mergesort 对三个输入数组进行排序

python - 内存错误 : numpy. genfromtxt()

javascript - 如何找出元素是否溢出(使用 jQuery)?

javascript - 仅从外部 url 解析 json Html 和 JS

c++ - 哪个更耗内存?矩阵或三角函数变换

performance - 循环 ggplots 以创建动画 : increasing speed

php - php 读取 1Gb 文件的内存限制应该是多少?

c - 用字符填充的动态分配的字符串导致空字符串 C