Почему библиотеки Javascript имеют локальные ссылки на методы массива (push, slice и т.д.)?
Я читал код нескольких библиотек javascript. Я заметил, что AngularJS и Backbone.js сохраняют локальную ссылку на функции массива. например:
var push = [].push // or array.push
в чем смысл делать это, когда массивы являются конструкцией языка и должны быть доступны глобально?
Ответы
Ответ 1
Поскольку функции прототипа Array могут применяться к не-массивам.
Например, push
'элементы в массив-подобный объект:
var o = { length: 0 };
[].push.call(o, 'hi');
o; //Object {0: "hi", length: 1}
Другой распространенной практикой является slice
'включение объекта arguments
в собственный массив:
(function() {
return [].slice.call(arguments); //[1, 2]
}(1, 2));
Как вы можете видеть, сохранение ссылок на эти функции уменьшает накладные расходы, делает код меньшим и дружественным к минимуму.
По-моему, это в основном для удобства и удобочитаемости, поскольку многократное написание [].arrayMethod
выглядит довольно неуклюжим. Повышения производительности и минимизации являются дополнительными.
Просматривая Angular источник, вот случаи, которые я нашел:
Backbone также slice
объекты аргументов (События # триггер и Подчеркивая методы проксирования), он также использует slice
в фрагмент коллекции #.
Ответ 2
Я думаю, что разработчики библиотек особенно заинтересованы в том, чтобы сделать их библиотеки устойчивыми к случайным вещам, которые могут происходить на странице. Если вы на ранней стадии получаете ссылку на правильный Array.prototype.push и используете закрытие, чтобы не допустить ее досягаемости от другого кода, о котором вы, как писатель библиотеки, не знаете, это уменьшило шансы (и значительно облегчает устранять неполадки, когда) что-то неожиданное происходит, если другой код на странице решает захватить этот встроенный метод, который Javascript очень разрешительный.
Рассмотрим:
function Library(){
var push=[].push;
var data=[];
this.save1=function(x){push.call(data, x);}
this.save2=function(x){data.push(x);}
this.get=function(){console.log(data);}
}
var o=new Library();
//Random on-page code
Array.prototype.push=function(x){console.info("doSomethingCrazy!");}
//Lets use the library functionality!
o.save1(1);
o.save2(2);
Ответ 3
Одна из причин, отмеченная Дугласом Крокфордом в его лекции Метаморфоза Ajax, заключается в том, что разработчики библиотек JavaScript могут условно добавлять методы утилиты для например, что-то вроде string.split, так что он будет добавлен только к прототипу объекта, если он еще не определен стандартными библиотеками, предоставленными браузером.