Я хочу написать эффективную библиотеку классов JavaScript, но я не могу начать;
Попробуйте прочитать библиотеку других людей, но поймите ее так, как будто она понята;
Я планирую хорошо изучать функции Advanced JS, но содержание в авторитетной книге слишком разбросано.
Даже если вы помните «использование», вы не думаете о «методе», когда хотите «использовать».
Может быть, вы, как и я, у вас есть невидимая сила, которая сдерживает наши планы, заставляя нас неоднократно думать, что ограничения знаний заставили нас стоять на месте и трудно двигаться вперед.
В течение этого периода различные домашние задания, дизайн курса и экспериментальные отчеты удвоились. Редко можно выжать немного времени, никогда не спать и разобраться в книгах, которые я читал в прошлом, чтобы быть ближе к написанию моей собственной библиотеки.
На эту статью ссылается из "JavaScript Language Essence" и "Эффективного JavaScript". Все примеры были отлажены. Понимая их, я хочу сделать несколько «глубоких» принципов немного проще.
1. Переменная область
Прицел как кислород для программистов. Это везде, и вы даже не думаете об этом. Но когда он загрязнен (например, использование глобальных объектов), вы почувствуете удушье (например, медленный ответ применения). Правила основного объема JavaScript просты, тщательно спроектированы и очень мощные. Эффективное использование JavaScript требует освоения некоторых основных концепций переменной масштаба и понимания некоторых экстремальных ситуаций, которые могут привести к неуловимым, раздражающим проблемам.
1.1 Старайтесь использовать глобальные переменные как можно меньше
JavaScript легко создавать переменные в глобальном пространстве имен. Создание глобальных переменных является легким, поскольку он не требует какой -либо формы объявления и может быть доступен автоматически по всему коду всей программы.
Для нас, начинающих, при столкновении с определенными потребностями (например, при записи передаваемых данных, ожидая определенного времени, или когда часто используется определенная функция), мы, наконец, думаем о глобальных функциях. Даже языковое, ориентированное на процесс, мышление, которое я узнал на своем первом курсе, слишком глубоко укоренилась, и система аккуратно полна функций. Определение глобальных переменных может загрязнять общие общественные пространства имен и привести к неожиданным конфликтам именования. Глобальные переменные также не способствуют модульности, поскольку вызывает ненужную связь между независимыми компонентами в программе. Серьезно говоря, слишком много глобального (включая листы стилей, непосредственное определение стилей Div или а) и интеграция их в разработки нескольких людей, будет катастрофической ошибкой. Вот почему весь код jQuery завершен мгновенно выполненным анонимным выражением - самообвигающими анонимными функциями. Когда браузер загружает файл jQuery, он начинает выполнять сразу после вызова анонимной функции, инициализации различных модулей jQuery, чтобы избежать уничтожения и загрязнения глобальных переменных и влиять на другие коды.
Кода -копия выглядит следующим образом:
(функция (окно, неопределенное) {
var jquery = ...
// ...
window.jquery = window. $ = jQuery;
})(окно);
Кроме того, вы можете подумать, что более удобно «написать, как вы сначала и организовываете его позже», но превосходные программисты будут постоянно обращать внимание на структуру программы, непрерывно классифицировать связанные функции и отдельные неактуальные компоненты, и такое поведение является частью формулы программирования.
Поскольку глобальные пространства имен являются единственным способом взаимодействия независимых компонентов в программах JavaScript, использование глобальных элементов управления именования неизбежно. Компоненты или библиотеки должны определить некоторые глобальные переменные. Для использования другими частями программы. В противном случае лучше использовать локальные переменные.
Кода -копия выглядит следующим образом:
this.foo; // не определен
foo = "Global Foo";
this.foo; // "Global Foo"
var foo = "Global Foo";
this.foo = "изменилось";
foo; // изменилось
Глобальное пространство имен JavaScript также подвергается воздействию глобальных объектов, которые можно получить в глобальном объеме программы, которая служит первоначальным значением этого ключевого слова. В веб -браузере глобальный объект связан с глобальной переменной окна. Это означает, что существует два способа создания глобальной переменной: объявить ее VAR в глобальной области или добавить ее в глобальный объект. Преимущество использования объявлений VAR заключается в том, что они могут четко выразить влияние глобальных переменных в области программы.
Учитывая, что ссылки на связанные глобальные переменные могут вызвать ошибки времени выполнения, четкие и краткие сберегательные акции облегчат пользователям кода понимать те глобальные переменные, которые заявляет программа.
Поскольку глобальный объект обеспечивает механизм динамического отклика для глобальной среды, его можно использовать для запроса управляемой среды и обнаружения, какие функции доступны на этой платформе.
Например, вводит глобальный объект JSON для чтения и написания данных формата JSON.
Кода -копия выглядит следующим образом:
if (! this.json) {
this.json = {
Parse: ..,
stringify: ...
}
}
Если вы предоставите реализацию JSON, вы, конечно, можете просто и безоговорочно использовать свою собственную реализацию. Но встроенные реализации, предоставляемые средой хоста, являются почти более подходящими, потому что они записаны в браузер в C., потому что они строго проверяют точность и согласованность в соответствии с определенными стандартами и, как правило, обеспечивают лучшую производительность, чем сторонние реализации.
Основная работа структуры данных структуры данных требует, чтобы методы, предоставленные самим языком, не могли быть использованы. JavaScript очень хорошо реализует основные операции массивов. Если это просто для общих потребностей в обучении, идея методов моделирования, предоставленных самим языком, хороша, но если вы действительно инвестируете в разработку, вам не нужно рассматривать возможность использования встроенных методов JavaScript как можно скорее.
1.2 Избегайте использования с
В соответствии с утверждением предоставлено любое «удобство», которое делает ваше приложение ненадежным и неэффективным. Нам нужно вызовать серию методов на одном объекте по очереди. Использование оператора с помощью может легко избежать дублирующих ссылок на объекты:
Кода -копия выглядит следующим образом:
Статус функции (info) {
var widget = new Widget ();
с (виджет) {
Betbackground ("Blue");
setforeground ("белый");
setText ("status:"+info);
показывать();
}
}
Также очень заманчиво использовать оператор с оператором для «импорта» (импорт) из объекта модуля.
Кода -копия выглядит следующим образом:
функция f (x, y) {
с (математикой) {
вернуть мин (раунд (x), sqrt (y)); // абстрактная цитата
}
}
На самом деле JavaScript относится к всем переменным одинаково. JavaScript начинается с самой внутренней области и ищет переменные наружу. С языком относится к объекту так, как если бы он представляет вариант, поэтому внутри кодового блока кодовые поиски начинаются с поиска атрибутов заданного имени переменной. Если свойство не найдено в этом объекте, продолжайте поиск во внешней области. Ссылка на каждую внешнюю переменную в блоке с неявно предполагает, что нет атрибута с одним и тем же именем в объекте с (и любым из его объектов прототипа). Создание или изменение объекта с или его прототипом в другом месте программы не обязательно следует за такими предположениями. Двигатель JavaScript, безусловно, не читает локальный код, чтобы получить те локальные переменные, которые вы используете. Объем JavaScript может быть представлена в виде эффективных внутренних структур данных, а поиск переменных очень быстрые. Однако, поскольку блок с кодом должен искать цепочку прототипа объекта, чтобы найти все переменные в коде, его скорость работы намного ниже, чем у общего блока кода.
Вместо языка с языком легко привязать объект с именем с коротким переменным.
Кода -копия выглядит следующим образом:
Статус функции (info) {
var w = new Widget ();
w.setbackground ("Blue");
w.setforeground ("белый");
w.settext ("status:"+info);
w.show ();
}
В других случаях лучший способ - явно связывать локальные переменные с соответствующими свойствами.
Кода -копия выглядит следующим образом:
функция f (x, y) {
var min = math.min,
Round = math.round,
sqrt = math.sqrt;
вернуть мин (раунд (x), sqrt (y));
}
1.3 Опытный в закрытии
Есть единственная концепция, чтобы понять закрытие:
A) JavaScript позволяет ссылаться на переменные, определенные вне текущей функции.
Кода -копия выглядит следующим образом:
Функция MakeandWich () {
var MagicingRedient = "Арахисовое масло";
Функция сделает (наполнение) {
вернуть волшебные сечения + »и" + начинка;
}
вернуть Make ("желе");
}
Makesandwich (); // "Арахисовое масло и желе"
б) Даже если внешняя функция вернулась, текущая функция все еще может относиться к переменной, определенной внешней функцией.
Кода -копия выглядит следующим образом:
Функция MakeandWich () {
var MagicingRedient = "Арахисовое масло";
Функция сделает (наполнение) {
вернуть волшебные сечения + »и" + начинка;
}
вернуть сделай;
}
var f = sandwichmaker ();
F ("желе"); // "Арахисовое масло и желе"
F ("бананы"); // "Арахисовое масло и бананы"
F ("Маллоу"); // "Арахисовое масло и маллоу"
Значения функции Javascriptd содержат больше информации, чем код, необходимый для выполнения при их вызове. Более того, значения функций JavaScript также хранят внутренние переменные, которые они могут ссылаться на их приложено. Те функции, которые отслеживают переменные в рамках, которую они охватывают, называются закрытием.
Функция MAKE - это закрытие, код которого относится к двум внешним переменным: MagiceRedient и Filling. Всякий раз, когда называется функция создания, его код может ссылаться на эти две переменные, потому что закрытие хранит эти две переменные.
Функция может ссылаться на любую переменную в пределах своей области, включая переменные параметров и внешней функции. Мы можем использовать это, чтобы написать больше общих функций сэндвич -мастера.
Кода -копия выглядит следующим образом:
Функция делает и
Функция сделает (наполнение) {
вернуть волшебные сечения + »и" + начинка;
}
вернуть сделай;
}
var f = sandwichmaker ("ham");
F ("сыр"); // "ветчина и сыр"
f ("горчица"); // "ветчина и горчица"
Закрытие является одной из самых элегантных и выразительных особенностей JavaScript, а также являются ядром многих идиомов.
в) Закрытие может обновить значение внешней переменной. Фактически, закрытия хранят ссылки на внешние переменные, а не копии их значений. Следовательно, любое закрытие с доступом к этим внешним переменным может быть обновлено.
Кода -копия выглядит следующим образом:
Функция Box () {
var val = не определен;
возвращаться {
SET: FUNCTION (NEWVAL) {val = newval;},
get: function () {return val;},
Тип: function () {return typeof val;}
};
}
var b = box ();
b.type (); //неопределенный
B.Set (98.6);
b.get (); // 98.6
b.type (); // номер
Этот пример создает объект, содержащий три закрытия. Эти три закрытия устанавливаются, вводите и получают свойства, и все они разделяют доступ к переменным VAL, а установка обновляет значение Val. Затем вызовите Get и введите, чтобы просмотреть обновленные результаты.
1.4 Понять улучшение объявления переменной
JavaScript поддерживает этот метод (ссылки на переменную Foo будут связаны с объемом, который объявляет наиболее близкую к переменной Foo), но не поддерживает область на уровне блока (область сферы, определяемое переменной, не является наиболее близким закрытым оператором или блоком кода).
Не понимание этой функции приведет к некоторым тонким ошибкам:
Кода -копия выглядит следующим образом:
Функция iswinner (игрок, другие) {
var самая высокая = 0;
for (var i = 0, n = другие.length; i <n; i ++) {
var player = другие [i];
if (player.score> наивысший) {
самый высокий = player.score;
}
}
return Player.score> Высокий;
}
1.5 Остерегайтесь неуклюжих выражений функции именования
Кода -копия выглядит следующим образом:
Функция Double (x) {return x*2; }
var f = function (x) {return x*2; }
Тот же кусок функционального кода также может быть использован в качестве выражения, но имеет совершенно разные значения. Официальное различие между анонимными функциями и выражением именованной функции заключается в том, что последнее связано с переменной с тем же именем функции, что и имя ее функции, которая служит локальной переменной функции. Это может быть использовано для написания рекурсивных выражений функции.
Кода -копия выглядит следующим образом:
var f = function find (tree, key) {
// ...
вернуть найти (kree.left, key) ||
Найти (дерево. Право, ключ);
}
Стоит отметить, что объем находки переменной находится только в его собственной функции. В отличие от объявлений функции, выражения именованных функций не могут быть направлены извне через его внутреннее имя функции.
Кода -копия выглядит следующим образом:
найти (mytree, "foo"); // Ошибка: найти не определено;
var constructor = function () {return null; }
var f = function () {
вернуть конструктор ();
};
f (); // {} (в средах ES3)
Программа выглядит так, как будто будет производить NULL, но на самом деле будет создавать новый объект.
Поскольку именованная переменная функции наследует object.prototype.constructor (то есть конструктор Ouct), как и в случае с операторами, на этот объем будет влиять динамические изменения объекта. Прототип. Способ избежать загрязнения объекта в области выражений функций в системе состоит в том, чтобы избежать добавления свойств в объект.
Другим недостатком в популярном двигателе JavaScript является продвижение объявления именованных функций.
Кода -копия выглядит следующим образом:
var f = function g () {return 17;}
g (); // 17 (в неконформированной среде)
Некоторые среды Javascript даже используют две функции F и G в качестве разных объектов, что приводит к ненужному распределению памяти.
1.6 Остерегайтесь неуклюжей области для локальных блоков функций
Кода -копия выглядит следующим образом:
функция f () {return "global"; }
Функциональный тест (x) {
функция f () {return "local";}
var result = [];
if (x) {
result.push (f ());
}
result.push (f ());
результат результата;
}
тест (правда); // ["Local", "Local"]
тест (false); //["местный"]
Кода -копия выглядит следующим образом:
функция f () {return "global"; }
Функциональный тест (x) {
var result = [];
if (x) {
функция f () {return "local";}
result.push (f ());
}
result.push (f ());
результат результата;
}
тест (правда); // ["Local", "Local"]
тест (false); //["местный"]
JavaScript не имеет сферы на уровне блока, поэтому область внутренней функции F должна быть всей тестовой функцией. Некоторые среды JavaScript делают, но не все среды JavaScript. Реализации JavaScript сообщают о таких функциях, как ошибки в строгом режиме (программы в строгом режиме с объявлениями функции локального блока будут сообщать в виде синтаксической ошибки), что помогает обнаружить невозможно-портативный код, что дает более мудрую и возможную семантику для локальных объявлений функций блока для будущих стандартных версий. В этом случае можно рассмотреть возможность объявления локальной переменной в функции теста, чтобы указывать на глобальную функцию f.