2

我有什么办法可以通过使用指针来缩短这段代码?我需要创建一个与给定数组类 unshift、shift、push 和 pop 具有几乎相同功能但名称不同的类。

var makeDeque = function()
{
    var a= [], r=new Array(a);

    length = r.length=0;

    pushHead=function(v)
    {
        r.unshift(v);
    }

    popHead=function()
    {
        return r.shift();
    }

    pushTail=function(v)
    {
        r.push(v);
    }

    popTail=function()
    {
        return r.pop();
    }

    isEmpty=function()
    {
        return r.length===0;
    }

    return this;
};    

(function() {
   var dq = makeDeque();

   dq.pushTail(4);
   dq.pushHead(3);
   dq.pushHead(2);
   dq.pushHead("one");
   dq.pushTail("five");
   print("length " + dq.length + "last item: " + dq.popTail());
   while (!dq.isEmpty())
      print(dq.popHead());
})();

输出应该是

长度5最后一项:五一2 3 4

谢谢!

4

4 回答 4

1

也许我过于简单化了,但为什么不直接将所需的额外方法添加到 Array 原型中并直接调用它呢?

于 2013-08-31T03:53:15.193 回答
1

我需要创建一个与给定数组类 unshift、shift、push 和 pop 具有几乎相同功能但名称不同的类。

我想您可以将这些“新”方法添加到Array.prototype.

于 2013-08-31T03:53:38.830 回答
0

不知道你为什么需要这个,但我对最佳实践的建议是:

  1. 不要覆盖Array.prototype. 这样做的原因是因为其他库可能会尝试做同样的事情,如果你将这些库包含到你的库中,就会发生冲突。
  2. 不需要此代码。var a= [], r=new Array(a);. 你只需要a = [];......
  3. 确保您正在创建一个真实的课程。在您的代码中,makeDeque没有做您想做的事。它返回this的是当一个函数没有被new关键字调用时将与window对象相同(或者undefined如果你使用的是所谓的“严格模式”)。换句话说,你做了很多全局变量(这通常是禁忌,因为它们也可能与其他代码冲突)。
  4. 当您构建一个类时,最好将其添加到prototype您的自定义类中。这是因为这些方法只会被构建到内存中一次,并且将被所有此类对象共享。

所以我会首先重构成这样的东西:

var makeDeque = (function() { // We don't need this wrapper in this case, as we don't have static properties, but I've kept it here since we do want to encapsulate variables in my example below this one (and sometimes you do need static properties).

    function makeDeque () {
        if (!(this instanceof makeDeque)) { // This block allows you to call makeDeque without using the "new" keyword (we will do it for the person using makeDeque)
            return new makeDeque();
        }
        this.r = [];
        this.length = 0;
    }

    makeDeque.prototype.setLength = function () {
        return this.length = this.r.length;
    };

    makeDeque.prototype.pushHead=function(v) {
        this.r.unshift(v);
        this.setLength();
    };

    makeDeque.prototype.popHead=function() {
        return this.r.shift();
        this.setLength();
    };

    makeDeque.prototype.pushTail=function(v){
        this.r.push(v);
        this.setLength();
    };

    makeDeque.prototype.popTail=function() {
        return this.r.pop();
        this.setLength();
    };

    makeDeque.prototype.isEmpty=function() {
        return this.r.length === 0;
    };

    return makeDeque;
}());

现在您可以将其缩短如下,但我不建议这样做,因为正如 Donald Knuth 所说的那样,“过早的优化是万恶之源”。如果你试图缩短你的代码,它可能会变得不灵活。

var makeDeque = (function() {

    function makeDeque () {
        if (!(this instanceof makeDeque)) {
            return new makeDeque();
        }
        this.r = [];
        this.length = 0;
    }

    makeDeque.prototype.setLength = function () {
        return this.length = this.r.length;
    };


    for (var i=0, methodArray = [
        ['pushHead', 'unshift'], ['popHead', 'shift'], ['pushTail', 'push'], ['popTail', 'pop']
    ]; i < methodArray.length; i++) {

        makeDeque.prototype[methodArray[i][0]] = (function (i) { // We need to make a function and immediately pass in 'i' here because otherwise, the 'i' inside this function will end up being set to the value of 'i' after it ends this loop as opposed to the 'i' which varies with each loop. This is a common "gotcha" of JavaScript
            return function () {
                var ret = this.r[methodArray[i][1]].apply(this.r, arguments);
                this.setLength();
                return ret;
            };
        }(i));
    } 

    makeDeque.prototype.isEmpty=function() {
        return this.r.length === 0;
    };

    return makeDeque;
}());

如果您需要通过length属性获取长度,而不是像 setLength() 这样在每次更新后手动设置它的方法,上述代码示例都可以通过避免使用 setLength() 方法来缩短,但您需要在 IE < 9 等较旧的浏览器中使用Object.definePropertywhich 不起作用(或不能完全起作用)。

于 2013-08-31T04:25:36.353 回答
0

大概是这样?

var makeDeque = (function (ap) {
    var Deque = {
        length: 0,
        pushHead: ap.unshift,
        popHead: ap.shift,
        pushTail: ap.push,
        popTail: ap.pop,
        isEmpty: function () {
            return !this.length;
        }
    };

    return function () { 
        return Object.create(Deque); 
    };
})(Array.prototype);

演示

如果它仍然太长,您总是可以Array.prototype像其他已经提到的那样直接增加。我们同意这一切都是实验性的,唯一的目标是拯救角色。

!function (ap) {
    ap.pushHead = ap.unshift;
    ap.popHead = ap.shift;
    ap.pushTail = ap.push;
    ap.popTail = ap.pop;
    ap.isEmpty = function () {
        return !this.length;
    };
}(Array.prototype);

function makeDeque() {
    return [];
}

这可以压缩为 174 个字符:

function makeDeque(){return[]}!function(e){e.pushHead=e.unshift;e.popHead=e.shift;e.pushTail=e.push;e.popTail=e.pop;e.isEmpty=function(){return!this.length}}(Array.prototype)

演示

于 2013-08-31T04:19:23.230 回答