array.splice = что это значит? - PullRequest
4 голосов
/ 24 мая 2019

Я хотел бы понять значение этого фрагмента кода.«saveTo» - это массив, программист назначил функцию () для метода соединения.Я не понимаю, что это значит.Это переопределение?Что означает возвращаемый аргумент? И почему функция не принимает аргументов, тогда как для сплайсинга требуется 2 или более аргументов?

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

Ответы [ 6 ]

5 голосов
/ 24 мая 2019

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 голосов
/ 24 мая 2019

Обратите внимание, что есть лучший способ расширить массивы в ES6:

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

Теперь, когда есть другие способы изменить длину массивов, .length, .pop, .shift и т. Д., Поэтому они также должны быть переопределены.Однако тогда все еще остается сомнительным, если код, вызывающий эти методы, не должен вызывать только побочный эффект.

2 голосов
/ 24 мая 2019

Программист, написавший этот код, знал, что какая-то другая часть программы вызывает 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

1 голос
/ 24 мая 2019

Хорошо, давайте разберем этот кусок по частям.

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 для соответствия вашим требованиям.

1 голос
/ 24 мая 2019

1) Да, программист переопределил метод соединения, его не рекомендуется

2) оператор return не что иное, как вызов Array.prototype.splice (оригинальный метод).

3) Да, для соединения требуются аргументы, но в JS вы не можете определять их как параметры функции. Вы получаете переданные параметры в виде массива, подобного объекту arguments внутри ваших функций, если присмотреться, они вызывают Array.prototype.splice с этим и arguments объектом.

1 голос
/ 24 мая 2019

Что он делает, так это добавляет некоторые проверки для saveTo.splice.Если вы позвоните anyOtherArray.splice, тогда он будет оценен как обычно.Причина, по которой он не принимает аргументов, заключается в том, что Array.prototype.splice принимает аргументы, а также контекст вызова saveTo, а также массоподобные объекты arguments, представляющие все аргументы, переданные saveTo.splice.Так что это просто добавление небольшого количества дополнительного кода на основе определенного условия - кроме этого, нет никакой разницы с нативным splice.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...