我以为我有一个这个引用传递到Javascript闭包中的私有函数,我想错了

时间:2015-10-25 20:30:29

标签: javascript

因此,我认为代码解释得非常好。我使用一个闭包来保持一个名为reverseAll的方法是私有的。 reverseAll是递归的,但你不必担心我的想法。我想在this.head函数中引用reverseAll,但我发现它是undefined。所以我传递了对this.head的引用并继续通过递归调用。唉,这不是故意的。我可以将reverseAll方法拉出闭包,我将引用this.head。但是我想知道为什么我传入的this.head引用不是“引用的副本”或“指针的副本”,如果您希望Javascript在将对象传递给函数时执行。顺便提一下,this.headnode个对象。

这是代码(对jQuery的引用是因为Stackoverflow代码段“IDE”在联机var obj = new LinkedList();时失败,所以我添加了一个document.ready,jQuery不需要除此之外的任何原因:

function LinkedList() {
    this.head = null;
};

LinkedList.prototype = (function () {

    function reverseAll(current, prev, theHead) {

        if (!current.next) { //we have the head
            console.log('ending recursion, new head!!');
            console.log('we have a refence to this.head in theHead or so I thought:');
            console.log(theHead);
            theHead = current;
            theHead.next = prev;
            console.log('theHead has a new "pointer":');
            console.log(theHead);
            return;
        }

        var next = current.next;
        current.next = prev;

        //keep passing the theHead reference through recursion
        reverseAll(next, current, theHead);
    };

    return {
        constructor: LinkedList,

        reverse: function () {
            console.log('clone head to iterate and change');
            console.log('but also pass in reference of this.head obj as this.head is a node obj and this.head will be undefined in reverseAll()');
            var headClone = JSON.parse(JSON.stringify(this.head));
            reverseAll(headClone, null, this.head);
        }
    }
})();

LinkedList.prototype.add = function(value) {
    var node = {
        value: value,
        next: null
    };

    var current;

    if (this.head === null) {
        this.head = node;
    } else {
        current = this.head;
        while (current.next) {
            current = current.next;
        }
        current.next = node;
    }

    return node;
}

LinkedList.prototype.remove = function(node) {
    var current, value = node.value;

    if (this.head !== null) {
        if (this.head === node) {
            this.head = this.head.next;
            node.next = null;
            return value;
        }
        //find node if node not head
        current = this.head;
        while (current.next) {
            if (current.next === node) {
                current.next = node.next;
                return value;
            }

            current = current.next;
        }
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(function() {
    var obj = new LinkedList();
    
    for (var i = 1; i <= 10; i++) {
        obj.add(i);
    }

    console.log('about to call obj.reverse()!');
    console.log('obj.head:');
    console.log(obj.head);
    obj.reverse();

    console.log('obj instance obj.head after reverse call, it has not changed!!:');
    console.log(obj.head);

});
</script>

2 个答案:

答案 0 :(得分:1)

当前实施的实际问题在于作业theHead = current。这对您LinkedList的实例没有任何影响。一个简单的解决方法是将this作为reverseAll(current, prev, instance)的最后一个参数传递,并将有问题的分配更改为:

instance.head = current;
current.next = prev;

但是,我相信更好的代码设计可以帮助避免这个问题。将reverseAll放在reverse内。首先它属于那里,因为它不用于任何其他目的,其次你甚至不需要将this传递给它,如果你使用名称替换var self = this;,则从闭包中使用它。后者是在其他地方使用的可取模式,它有助于避免琐碎的错误:

function LinkedList() {
    this.head = null;
}

LinkedList.prototype.reverse = function() {
    var self = this;
    var reverseAll = function(current, prev) {
        var exitCondition = !current.next;
        var next = current.next;
        current.next = prev;

        if (exitCondition) {
            self.head = current;
            return;
        }

        reverseAll(next, current);
    };

    // FIXME this is ugly, but unrelated, so keep it
    var headClone = JSON.parse(JSON.stringify(self.head));
    reverseAll(headClone, null);
};

// remove and add prototypes as in the original
  

节点

> a = new LinkedList();
LinkedList { head: null, reverse: [Function] }
> a.add(1);
{ value: 1, next: null }
> a.add(2);
{ value: 2, next: null }
> a
LinkedList {
  head: { value: 1, next: { value: 2, next: null } },
    reverse: [Function] }
> a.reverse();
undefined
> a
LinkedList {
  head: { value: 2, next: { value: 1, next: null } },
    reverse: [Function] }
> 

答案 1 :(得分:0)

您的成员值this.head将被您在返回对象中定义的函数覆盖!

head: function() 
{
  return this.head;
}

被添加到原型中。

然后您实例化LinkedList,原型用于扩展this。然后将this.head替换为函数。

您可以做的最好的事情是将函数重命名为getHead。