【问题标题】:array.splice = what does it means?array.splice = 是什么意思?
【发布时间】:2019-10-10 22:13:00
【问题描述】:

我想了解该代码片段的含义。 “saveTo”是一个数组,程序员为拼接方法分配了一个函数()。我不明白这是什么意思。那是超载吗? return 参数的含义是什么?为什么函数不带参数而 splice 需要 2 个或多个参数?

    saveTo.splice = function() {
        if (saveTo.length == 1) {
            $("#send").prop("disabled", true);
        }
        return Array.prototype.splice.apply(this, arguments);
    };

【问题讨论】:

  • 看来他正在为splice 方法添加他在Array.prototype 中所做的一切。他基本上将他的新 if 语句应用于 Array.prototype 中的 splice 方法。 Check this out

标签: javascript jquery arrays function


【解决方案1】:

Javascript 允许您在运行时重新分配方法。在这种情况下,程序员所做的是在这个数组的特定实例上重新分配splice,以便调用jQuery 方法。除此之外,它的工作方式与调用return Array.prototype.splice.apply(this, arguments); 的现有拼接完全相同——这意味着这个方法只是传递arguments 传递给它的任何东西。

这是一个演示:

var myArray = [1,2,3,4];
console.log("Splice before re-assing: ", myArray.splice(1,1));

// reset it.
myArray = [1,2,3,4];
myArray.splice = function(){
    console.log("From inside new splice function");
    
    return Array.prototype.splice.apply(this, arguments);
}


console.log("Splice after re-assiging: ", myArray.splice(1,1));

这是否是一件好事是值得商榷的。它打破了一些编程原则。

【讨论】:

    【解决方案2】:

    编写此代码的程序员知道程序的其他部分正在此数组上调用splice,他想将一个事件附加到该数组上,以更新用户界面(因此调用了 jQuery) .

    这通常称为“猴子修补”。你可以在https://www.audero.it/blog/2016/12/05/monkey-patching-javascript/阅读它

    不是一个好的做法,因为它混淆了正在发生的事情:没有程序员会期望调用数据操作函数会在其他地方产生副作用。

    您可以运行此示例以了解其工作原理:

    const myArray = [];
    
    // Patch push method only for this instance of array.
    myArray.push = function() {
       // log event
       console.log('myArray.push was called with the following arguments', arguments);
    
       // Call the original push function with the provided arguments.
       return Array.prototype.push.apply(this, arguments);
    }
    
    myArray.push(1);
    

    您还可以为给定类的所有实例修补方法:

    // Patch push method on all arrays
    const originalPush = Array.prototype.push;
    Array.prototype.push = function() {
       // log event
       console.log('.push was called with the following arguments', arguments);
    
       // Call the original push function with the provided arguments.
       return originalPush.apply(this, arguments);
    }
    
    const myArray = [];
    myArray.push(1);
    

    关于arguments 的问题,在javascript 中,所有函数都可以访问arguments 类数组对象,该对象包含调用函数时使用的参数,这与原始声明中指定的参数无关.

    function doSomething(arg1) {
       console.log(arguments[2]);
    }
    
    doSomething(1, 2, 3); // outputs "3"
    

    这里是关于它的 MDN 文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments

    【讨论】:

      【解决方案3】:

      请注意,在 ES6 中扩展数组有更好的方法:

       class CustomArray extends Array {
         splice(...args) {
            if(this.length === 1) {
               $("#send").prop("disabled", true);
            }
            super.splice(...args);
         }
      }
      

      现在还有其他方法可以更改数组长度,.length.pop.shift 等,所以这些也应该被覆盖。然而,调用这些方法的代码是否不应该只是造成副作用仍然值得怀疑。

      【讨论】:

      • 感谢您的注意,这种方式更具可读性和清晰性。
      【解决方案4】:

      它的作用是添加一些专门针对saveTo.splice 的检查。如果你打电话给anyOtherArray.splice,那么它只会被正常评估。它不带参数的原因是因为Array.prototype.splice 带参数,还有saveTo 的调用上下文,以及类数组对象arguments,代表传递给saveTo.splice 的所有参数。所以它只是根据特定的条件添加了一点额外的代码——除此之外,与原生的splice没有区别。

      【讨论】:

        【解决方案5】:

        1) 是的,程序员重写了拼接方法,不推荐

        2) return 语句只不过是调用 Array.prototype.splice(原始方法)。

        3) 是的,splice 需要参数,但是在 JS 中,您可能不会将它们定义为函数参数。您在函数中将传递的参数作为对象arguments 之类的数组获取, 如果您仔细观察,他们会使用 this 和 arguments 对象调用 Array.prototype.splice。

        【讨论】:

          【解决方案6】:

          好的,让我们一块一块地剖析。

          saveTo.splice = function() {
              if (saveTo.length == 1) {
                  $("#send").prop("disabled", true);
              }
              return Array.prototype.splice.apply(this, arguments);
          };
          

          众所周知,JavaScript 中的函数是first class objects,所以如果我们有一个对象,我们可以说saveTo 是这样的:

          const saveTo = {};
          

          然后我们可以将一个函数分配给它的一个属性,例如:

           saveTo.splice = function() {
           };
          

          或类似的东西:

          const saveTo = {
             splice: function() {
             }
          };
          

          除此之外,您只需调用Array#prototype#splice 方法从数组中创建一个浅拷贝,并将iterable 传递给它。

          所以总的来说,您已经覆盖了原生 Array#prototype#splice 以满足您的要求。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-08-12
            • 2017-06-11
            • 2018-03-05
            • 2023-03-27
            • 1970-01-01
            • 2013-03-09
            • 2020-05-01
            相关资源
            最近更新 更多