使用 top_of_stack(n).value 访问像堆栈一样的数组

Access an array like a stack using top_of_stack(n).value

本文关键字:堆栈 一样 数组 value of top stack 使用 访问      更新时间:2023-09-26

TOS表示堆栈顶部。预期用法的示例,

 read: var xx = tos(3).value;
write: tos(4).value = 12345678;

给定一个数组

var mystack = [11, 22, 33, 44, 55];  // 55 is tos(0), 22 is tos(3)

读取mystack很容易,tos(0).value返回 55,tos(1).value返回 44,如下所示功能做得很好,

function tos(n){
    arguments.callee.value = mystack[mystack.length - 1 - n];
    return arguments.callee;
}

但是我想将数据写入mystack

tos(2).value = 3333;  // How to make tos() work this way?

mystack应该变得[11, 22, 3333, 44, 55];如何为此重写tos()

为什么要问这个问题?

Microsoft办公 Excel 自动化允许 objExcel.workbooks(1(.worksheets(1(.cells(1,1(.value 位于 = 的两侧,例如,objExcel.workbooks(1(.worksheets(1(.cells(1,1(.value = 11223344;WScript.echo(objExcel.workbooks(1(.worksheets(1(.cells(1,1(.value(;打印11223344

我尝试以这种方式访问数组,但发现这对我来说很困难。

预期的函数 tos(( 是一个避免暴露 mystack 本身的封装。

如果你真的想这样做,坦率地说我不明白这一点,那么你可以这样做:

function tos (n) {
    var i = mystack.length - n - 1;
    return Object.defineProperty ({}, "value", {
       get : function() { return mystack[i]; },
       set : function(v) { mystack[i] = v; }
    });
}

当然,你需要 ECMAScript 5。没有其他方法可以实现tos(2).value=999设置数组元素所需的语义,因为在 JS 中,.value语法要求左侧的对象是对象,而数组元素本身不是具有可以设置的值的对象。所以上面的本质上构造了一个对象,并在其上定义了一个getter和setter。

要使其独立于mystack,请执行显而易见的操作:

function as_stack (array) {
    return {
        tos : function (n) {
            var i = array.length - n - 1;
            return Object.defineProperty ({}, "value", {
                get : function() { return array[i]; },
                set : function(v) { array[i] = v; }
            };
        }
    };
}

现在你可以做

as_stack (array).tos (2).value=999;

var tos = as_stack (array).tos; 
tos (2).value = 999;

如果那漂浮你的船。

根据你对这些事情的宗教信仰,你也可以把它添加到Array.prototype

Array.prototype.tos = function (n) {
    var i = this.length - n - 1, array = this;
    return Object.defineProperty ({}, "value", {
        get : function() { return array[i]; },
        set : function(v) { array[i] = v; }
    };
};

现在你可以做

array.tos (2).value=999;

另一种方法

如果您专注于使用 .value 语法来获取和设置值,而不使用 Object.defineProperty ,那么我能想到的唯一其他选择是使用 DOM 作为数组的代理。我们将数组存储为文档片段中的文本节点列表。但是,您将必须使用 nodeValue ,而不是 value .

首先,从真实数组创建一个基于 DOM 的数组:

function dom_array (array) {
    this.frag = document.createDocumentFragment ();
    for (var i=0; i<array.length; i++) {
        this.frag.appendChild (document.createTextNode (array[i]);
    }
}

现在,你可以做

my_dom_array = new dom_array ([1,2,3]);

接下来,我们将添加一个返回特定元素的方法:

dom_array.prototype.tos = function (n) {
    return this.frag.childNodes.item (this.frag.childNodes.length - n -1 );
}.

此函数实际上返回一个 DOM 文本节点,您现在可以使用它来执行以下操作:

my_dom_array.tos (2).nodeValue = "bar";
alert (my_dom_array.tos (2).nodeValue);

你可能想要添加一个成员函数来获取一个真实的数组:

dom_array.prototype.to_array = function () {
    var array=[];
    for (var i=0; i<this.frag.childNodes.length; i++) {
        array.push (this.frag.childNodes[i].nodeValue);
    }
    return array;
};

现在您可能还想在这个准数组上实现所有其他数组方法,如 pushpop 或其他任何方法。

你有它 - 一个tos函数,它允许您获取和设置数组中的值,尽管使用 nodeValue 而不是 value 。然而,它使你无法想象为什么你想要这样做,而不是像世界上所有其他JS程序员一样说array[2]=999;

请注意,这在非 DOM 环境中不起作用,例如 node.js。

假设你控制mystack变量,只需以不同的方式构建它,生活就会变得容易得多。

利用 JavaScript.Array 的 shiftunshift 运算符。 从堆栈为空开始: mystack = [];

当您添加它时,只需移动值:

mystack.shift(11);
mystack.shift(22);
mystack.shift(33);
mystack.shift(44);
mystack.shift(55);

然后它将是一个 0 索引堆栈,mystack[2] 会给你 33,你可以简单地mystack[2] = 3333来设置你的值。

要"弹出"堆栈,请使用 unshift 。 它将删除 0 元素。

正如之前的评论者指出的那样,您上面的代码非常奇怪。若要使代码看起来更好,如果确实mystack用作Stack数据类型意义上的Stack,请使用以下命令:

mystack.push(11);
mystack.push(22);
mystack.push(33);
mystack.push(44);
mystack.push(55);

当然,那么你将在堆栈中拥有[11, 22, 33, 44, 55]。要查看堆栈顶部,您可能需要这样的函数:

function peek(stack) {
  return stack[stack.length - 1];
}

或者,您可以在Array.prototype中将其定义为:

Array.prototype.peek = function () {
  return this[this.length - 1];
};

然后,您可以使用mystack.peek()访问堆栈顶部。现在您拥有了stack的正确语义。虽然您不应该真正直接访问堆栈中的元素,但如果确实有必要,您仍然可以选择使用 mystack[2] = 2222 修改它们。