【问题标题】:How to create a common constant instance of a self-defined object in javascript?如何在javascript中创建自定义对象的通用常量实例?
【发布时间】:2012-04-29 02:28:57
【问题描述】:

我正在创建一个程序来表示 javascript 中的二叉搜索树。我想要的是一种创建公共树节点的方法,其中 ptrs(left, right) 都为空。这是我写的代码:

var BST = function(data) {
    if (data === null || data === undefined){
        this.data  = null;
        this.left  = null;
        this.right = null;
    }

    else{
        this.data  = data;
        this.left  = new BST(null);
        this.right = new BST(null);
    }
};

BST.prototype.insert = function(data) {
    if (this.data === null){
        this.data  = data;
        this.left  = new BST(null);
        this.right = new BST(null);
    }
    else if (data < this.data)
        this.left.insert(data);
    else if (data > this.data)
        this.right.insert(data);
};

BST.prototype.inOrder = function(func) {
    if (this.data !== null) {
        this.left.inOrder(func);
        func(this.data);
        this.right.inOrder(func);
    }
};

在这里,我想为所有空指针分配一个空节点(在if(data === null || data === undefined) 条件中定义)。但是对于每个空节点,我必须创建一个代表相同数据的新节点。 有没有办法分配给空节点的公共实例?
我使用空节点而不是仅使用

的原因
else{
    this.data = data;
    this.left = null;
    this.right = null;
}

是在调用inOrder 方法时,在到达带有left or right = null 的节点时,它会给出TypeError,因为它尝试运行 null.inOrder(func);,因为this.left 转换为null
解决方法是修改inOrder 函数,这将导致每个语句周围出现许多条件,即不是一个非常优雅的实现。
我也可以在对象的原型之外定义inOrder,并使其将树作为参数,即inOder(tree,func),但我不想这样做。

另外,作为代码的第二个改进,考虑insert 方法;在 null 案例中:

if (this.data === null){
    this.data  = data;
    this.left  = new BST(null);
    this.right = new BST(null);
}

因为无论如何我都必须覆盖每个条目,所以我想通过以下方式将此节点完全重新分配给一个新树:

if (this.data === null)
    this = new BST(data);

我知道这对前者来说效率较低,但它仍然简洁得多。那么有什么办法吗?

【问题讨论】:

  • 您不能分配给this,而是需要操作父节点。

标签: javascript constants


【解决方案1】:

但是对于每个空节点,我必须创建一个代表相同数据的新节点。有没有办法分配给空节点的公共实例?

是的,但这会破坏您的代码。想一想:当您在该节点实例上调用insert 方法时会发生什么? ...

至于第二个问题,您无法使用当前模型对其进行优化。没有就地对象替换 (there is in C#) 这样的事情。

我认为您当前的代码还可以,尽管我个人会坚持使用更简单的模型,例如

var BST = function(data) {
    this.insert(data);
};

BST.prototype.insert = function(data) {
    if (typeof this.data == 'undefined') {
        this.data = data;
    } else if (data < this.data) {
        if (!this.left) {
            this.left = new BST();
        }
        this.left.insert(data);
    } else if (data > this.data) {
        if (!this.right) {
            this.right = new BST();
        }
        this.right.insert(data);
    }
};

BST.prototype.inOrder = function(func) {
    if (typeof this.data != 'undefined') {
        this.left && this.left.inOrder(func);
        func(this.data);
        this.right && this.right.inOrder(func);
    }
};

请注意,这完全消除了对 nullNode 的需要,因为 - 嘿! - 它是 JavaScript,所以为什么不使用 undefined 和动态对象扩展等美妙的东西。

【讨论】:

    【解决方案2】:

    是的,在这种情况下,您可以使用常量实例,因为所有空节点都是相同的并且没有不同的引用(如“父”属性)。要创建这样一个常量,您需要一个存储它的地方;可以是(私有)变量或类似的东西

    BST.emptyleaf = new BST(null);
    

    你也可以使用单例模式:

    function BST(data) {
        if (data === null || data === undefined) {
            if (BST.emptyleaf)
                return BST.emptyleaf; // singleton instance if available
            this.data  = null;
            this.left  = null;
            this.right = null;
            BST.emptyleaf = this; // else create it for re-use
        } else {
            this.data  = data;
            this.left  = new BST(null);
            this.right = new BST(null);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-05-10
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 2010-12-08
      • 1970-01-01
      • 2010-10-05
      • 2012-05-27
      相关资源
      最近更新 更多