Как вы ссылаетесь на массив.прототип.ломтик.call()?

Я пишу сценарий, в котором мне нужно клонировать массивы во многих разных местах. По этой причине, я хотел бы сделать следующее, чтобы эмулировать функции клонирования:

var clone = [].slice.call;
var arr1 = [1,2,3,4,5,6,7,8,9,10];
var arr2 = clone(arr1, 0);

к сожалению, приведенный выше код приводит к: TypeError: object is not a function. Я понимаю, что есть много функций для глубокого клонирования и мелких копий, но я просто хочу использовать встроенный метод. Интересно, что работает следующее:

var clone = [].slice;
var arr1 = [1,2,3,4,5,6,7,8,9,10];
var arr2 = clone.call(arr1, 0);

кто-нибудь знает, почему первый блок не работает, пока работает второй? Есть ли способ ссылаться на вызов функций и применять функции без ошибок при вызове указанной функции?

5 ответов


Я, безусловно, согласен с Феликсом Король и pimvdb. Я думаю, что единственный недостаток в использовании функции.протойтпе.функция bind () заключается в том, что это не функция, доступная во всех браузерах (например, IE6). Альтернативой может быть использование библиотеки JavaScript, которая предоставляет функцию curry (). Другой альтернативой было бы определить функцию, которая дает вам возможность получить вызов функции для любой другой функции. Вот определение, которое я опубликовано в моем блоге для такой функции, которую я назвал getCall ():

Function.prototype.getCall = function() {
  var realFn = this;
  return function(objThis) {
    return realFn.apply(objThis, Array.prototype.slice.call(arguments, 1));
  };
};

теперь, с этим определением, вы можете сделать следующее, Чтобы получить ссылку на функцию вызова функции среза:

var slice = [].slice.getCall();

вы можете клонировать массив, по телефону slice напрямую:

var arr2 = arr1.slice();

если вы хотите


проблема в том, что whatever_function.call равна Function.prototype.call. Таким образом, вы эффективно сохраняете ссылку на Function.prototype.call и информацию о том, что это функция среза теряется.

сравните его с пользовательской функцией:

Function.prototype.custom = function() { console.log(this) };

[].slice.custom(); // logs slice function

var ref = [].slice.custom;
ref(); // logs window object

метод сохранения this значение с помощью Function.prototype.bind:

var ref = [].slice.call.bind([].slice);

теперь

ref([1,2,3], 1); // [2, 3]

потому что при вызове на this значение привязано к функции slice и все работает, как ожидалось.


разница заключается в объеме функции, то есть в том, что "это". Я не уверен, какие правильные технические термины, но "это "не то же самое, когда функция называется" автономно " или как свойство объекта.

var myObj = {};
myObj.foo = function () {
    console.log(this.bar);
};
myObj.bar = 1234;

var fooRef = myObj.foo;

myObj.foo(); // 1234
fooRef(); // undefined

однако вы можете создать функцию, которая обертывает вызов функции и передает все аргументы:

var fooEncapsulated = function () {
    return myObj.foo.apply(myObj, arguments);
}

fooEncapsulated(); // 1234

для сведения, самый распространенный способ сделать это:

Array.prototype.slice.call(myArray, other, arguments, here);

мило и просто:

slice = Function.prototype.call.bind(Array.prototype.slice);
slice([1,2,3]); // [1,2,3]
slice({length:3,0:1,1:2,2:3}); // [1,2,3]