Вот несколько жемчужин:
Литералы:
var obj = {}; // Object literal, equivalent to var obj = new Object();
var arr = []; // Array literal, equivalent to var arr = new Array();
var regex = /something/; // Regular expression literal, equivalent to var regex = new RegExp('something');
По умолчанию:
arg = arg || 'default'; // if arg evaluates to false, use 'default', which is the same as:
arg = !!arg ? arg : 'default';
Конечно, мы знаем анонимные функции, но возможность рассматривать их как литералы и выполнять их на месте (как закрытие) - это здорово:
(function() { ... })(); // Creates an anonymous function and executes it
Вопрос: Какой еще замечательный синтаксический сахар доступен в javascript?
Мне было намного труднее понять тернарный синтаксис. После того, как вы напишете это несколько раз, это будет казаться вашей второй натурой. Насколько вы могли это видеть, я думаю, что и jquery.js, и prototype.js используют его.
Как насчет объяснения каждого из примеров?
Я не знал об "arg || 'default'". Я ожидал, что он вернет логическое значение, но он возвращает первое значение (слева), которое оценивается как истинное (аналогично python)! Это намного лучше, чем "arg = arg? Arg: 'default'"!
Крис Ноу заложил эту тему!
Вы должны добавить в (function () {}) (); что он в основном используется для букмарклетов, поэтому браузер не будет перенаправлять на результат выражения lsat.
Синтаксис arg || 'default' также немного (на 15%) быстрее, я добавил здесь быстрый тест: jsperf.com/boolean-conditionals-vs-ternary
аргумент || 'default' не работает, если вам нужен 'ложный' аргумент определенного типа. arg === undefined? по умолчанию: arg намного безопаснее.
@Gregg, я полагаю, это зависит от ожидаемого ввода. Обычно, если я пишу функцию, в которой аргумент может быть более чем одним из возможных «ложных» значений, я считаю это проблемой дизайна и попытаюсь провести рефакторинг. Тем не менее, я поясню сахар, чтобы было понятно, что он означает.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В Mozilla (и, как сообщается, IE7) вы можете создать константу XML, используя:
var xml = <elem></elem>;
Вы также можете заменять переменные:
var elem = "html";
var text = "Some text";
var xml = <{elem}>{text}</{elem}>;
Действительно? Есть ли другие движки, которые это поддерживают?
Просто интересно: что вы можете сделать с этой переменной "xml" после ее создания? Просто поиграв с ним сейчас в firebug, похоже, что у него нет никаких методов или свойств, и вы не можете добавить его в DOM.
Полезная ссылка: developer.mozilla.org/index.php?title=En/…
Вы можете сделать это и в scala!
Rhino также поддерживает это (движок Javascript с открытым исходным кодом для Java): mozilla.org/rhino
@nickf: e4x великолепен !!! Некоторое время я использовал его с JSDB для вывода HTML-страниц и обработки XML. var x = <q> <a> b </a> </q>; x.a + = <a c="1"> cc </a>; x.a [0]. @ n = 3; для каждого (var c в x.children ()) print ("вау:" + c.toXMLString ()); (выводит это: wow: <a n="3"> b </a> wow: <a c="1"> cc </a>)
Литералы E4X представляют собой катастрофу для безопасности из-за атак с включением межсайтовых сценариев, и на самом деле не намного лучше, чем просто возможность сказать «var xml = new XML ('<elem> </elem>')» IMO.
@bobince Если злоумышленник может внедрить Javascript, вы уйдете, независимо от того, включен ли E4X или нет
@CharlieSomerville Это не риск. E4X потенциально превращает "безопасные" [X] [HT] ML-файлы в активные JS. Пожалуйста, прочтите code.google.com/p/doctype/wiki/ArticleE4XSecurity для получения информации по этой проблеме.
Используйте === для сравнения значения и type:
var i = 0; var s = "0"; if (i == s) // true if (i === s) // false
Фактически это называется строгим равенством - в основном он позволяет избежать всех преобразований типов, которые в противном случае должны были бы произойти при выполнении ==
другие языки (PHP) также называют это «проверкой идентичности», то есть: являются ли эти два значения идентичный?
@nickf, это неправильно. $var1 = 'string'; $var2 = 'string'; $var1 === $var2; // true, даже несмотря на то, что $var1 и $var2 не идентичны (ссылки на одно и то же сохраненное значение в памяти), это один и тот же тип и одно и то же значение.
@eyelidlessness, я не уверен, что javascript так работает ... строки (как правило) хранятся и передаются по значению. Однако объекты хранятся как ссылка: var1 = {a : 'b'}; var2 = {a : 'b'}; var1 === var2 // false.
@nickf, я это понимаю. Но вы можете удалить сигил в коде PHP и получить тот же результат в JavaScript. Эти строки не идентичный, но их значения.
Это не эксклюзивный javascript, но сохраняет как три строчки кода:
check ? value1 : value2
Есть ли аналог этого, если значение не присваивается (например, fnName? FnName: defaultFn;)?
Нет, тернарный оператор предназначен только для выражений; нет заявлений
вы можете использовать его для оценки анонимных функций, например: "var myFunc = (browserIsIE? function () {...}: function () {...})". лично я бы не рекомендовал это, так как это довольно запутанно, но, по крайней мере, это возможно.
«оценивать», вероятно, не лучшее слово в предыдущем комментарии. Эмм .. назначить?
@eyelidlessness: Да: fnName? fnName (): defaultFn (); // на отдельной строке, работает
Добавляя к моему комментарию выше, вы могли бы даже сделать: (fnName? FnName: defaultFn) ();
@Ates Goral: "работает", но выдает ошибку ReferenceError, если fnName не определено. Это вряд ли синтаксический сахар.
Конечно, вы сделаете это только тогда, когда знаете, какие переменные будут объявлены. Вы даже можете пойти: (fnName || defaultFn)()
Еще немного на примере Левика:
var foo = (condition) ? value1 : value2;
Скобки не нужны. Тернарные операторы также характерны для многих других языков.
Скобки помогают при синтаксической неоднозначности условного оператора (например, при определении того, к какому компоненту условного оператора применяется знак?).
Возможность расширять собственные типы JavaScript с помощью прототипного наследования.
String.prototype.isNullOrEmpty = function(input) {
return input === null || input.length === 0;
}
Просто не делайте этого с массивом: stackoverflow.com/questions/61088/…
Это правда, но только если вы используете цикл for (a in b). Обычно я использую фреймворки, как, уверен, и все остальные. Как следствие, я обычно использую .each ()
Это потенциальная проблема, если код Любые в вашем контейнере использует for (a in b). И когда этот контейнер является браузером, вы можете нарушить другой код в своем браузере (например, этот фреймворк). Я был поражен этим.
Ага. Хорошие замечания, Крис. Я до сих пор считаю прототипное наследование одной из лучших особенностей JavaScript :)
for (var i in obj) {if (! obj.hasOwnProperty (i)) {продолжить; } ...}
Да, вы всегда должны использовать hasOwnProperty, иначе цикл будет перебирать все свойства вверх по цепочке прототипов.
Это больше, чем метод расширения в .NET
Многострочные струны:
var str = "This is \ all one \ string.";
Поскольку вы не можете делать отступ в последующих строках, не добавляя пробелов в строку, люди обычно предпочитают объединять с помощью оператора плюс. Но это дает хорошую возможность здесь документ.
Честное предупреждение - будет выдано исключение, если после \ будут конечные пробелы.
Использование анонимных функций и закрытия для создания частной переменной (скрытие информации) и связанных методов get / set:
var getter, setter;
(function()
{
var _privateVar=123;
getter = function() { return _privateVar; };
setter = function(v) { _privateVar = v; };
})()
заняло у меня мгновение, но я понял. это аккуратно.
Я обнаружил похожую технику некоторое время назад, просматривая исходный код swfobject. Использование замыканий для создания частных переменных / методов - это то, о чем я, вероятно, никогда бы не подумал. Это круто.
В новой версии JS мы можем использовать более простой if (true) { let _privateVar=123; }
Помните о стилистической потенциальной проблеме "собачьих мячей". См .: twitter.com/paul_irish/status/176187448420864000?lang=en
Тест на принадлежность к объекту:
var props = { a: 1, b: 2 };
("a" in props) // true
("b" in props) // true
("c" in props) // false
Это определенно более лаконично, чем props.a === undefined Спасибо.
И это правда, даже если props = {a: undefined}.
К вашему сведению - Firefox выдает ошибку TypeError, когда вы пытаетесь использовать "in" в объекте XPCNativeWrapper. А начиная с Firefox 4 множество объектов обернуто. Так что вернемся к props.a === undefined в этих случаях.
Мне нравится иметь возможность eval () json-строки и получить обратно полностью заполненную структуру данных. Ненавижу писать все по крайней мере дважды (один раз для IE, снова для Mozilla).
function Foo(bar)
{
this._bar = bar;
}
Foo.prototype =
{
get bar()
{
return this._bar;
},
set bar(bar)
{
this._bar = bar.toUpperCase();
}
};
Дает нам:
>>> var myFoo = new Foo("bar");
>>> myFoo.bar
"BAR"
>>> myFoo.bar = "Baz";
>>> myFoo.bar
"BAZ"
Да, это будет немного лучше, чем нынешний подход, который я использовал.
@eyelidlessness - это объект Object.defineProperty из ECMAScript 5, который реализует IE, а другие браузеры могут использовать defineGetter.
IE8 реализует геттеры / сеттеры только для объектов DOM, поэтому он бесполезен, когда дело доходит до создания более аккуратных собственных объектных API: - /
Массив # forEach в Javascript 1.6
myArray.forEach(function(element) { alert(element); });
Я забыл:
(function() { ... }).someMethod(); // Functions as objects
Получение текущего даты и времени в миллисекундах:
Date.now()
Например, чтобы рассчитать время выполнения раздела кода:
var start = Date.now();
// some code
alert((Date.now() - start) + " ms elapsed");
Фактически, это лучший синтаксический сахар javascript. Виннар - это ты.
OrbMan, это, вероятно, зависит от контекста; если передать его в качестве аргумента, он может быть приведен к объекту, а не к числу или строке, и в этом случае знак + уже привел бы его к числу. Фактически, +, похоже, служит сокращением для parseInt (value, 10).
Исправление: есть некоторые отличия от parseInt (value, 10). Например, + [3] и parseInt ([3], 10) равны числу 3, но + [3, 4] == NaN и parseInt ([3, 4], 10) == 3.
Э ... все эти экземпляры parseInt (value, 10) должны быть parseFloat (value). И Крис Ноу, извините за спам в комментариях;)
предупреждение (новая дата () + новая дата ()); // удваиваем годы с 0 года до настоящего момента.
Мое любопытство подтолкнуло меня попробовать его в jsperf, и кажется, что наиболее производительным является канонический getTime () :) (ref. jsperf.com/millisecondsdate)
Разве не лучше (или «слаще») просто определить функцию, чтобы можно было написать now()?
Повторение строки, такой как «-», определенное количество раз, используя метод соединения для пустого массива:
var s = new Array(repeat+1).join("-");
Результат "---" при повторении == 3.
var tags = {
name: "Jack",
location: "USA"
};
"Name: {name}<br>From {location}".replace(/\{(.*?)\}/gim, function(all, match){
return tags[match];
});
обратный вызов для замены строки просто полезен.
int для строкового приведения
var i = 12;
var s = i+"";
Мне это не кажется более "сладким", чем выполнение прямого i.toString () или String (i). Коротко! = Сахар.
После obj || {default: true} синтаксис:
вызов вашей функции с помощью этого: hello (requiredOne && requiredTwo && needThree), если один параметр undefined или false, тогда он вызовет hello (false), иногда полезно
Назначение часто используемых ключевых слов (или любых методов) простым переменным, подобным этой
var $$ = document.getElementById;
$$('samText');
Это не сработает (по крайней мере, в Chrome), потому что значение this потеряно. Вместо этого вы должны использовать document.getElementById.bind(document). Без bind он просто назначает функцию HTMLDocument.prototype.getElementById без информации о том, что она должна вызываться на document.
Изменить размер массива
Свойство length - это не только для чтения. Вы можете использовать его для увеличения или уменьшения размера массива.
var myArray = [1,2,3];
myArray.length // 3 elements.
myArray.length = 2; //Deletes the last element.
myArray.length = 20 // Adds 18 elements to the array; the elements have the empty value. A sparse array.
Сэр, я считаю, что это должен быть самый важный ответ на SO. Мне больше не нужен push, хе-хе. Огромное спасибо.
на самом деле созданные таким образом элементы на самом деле не существуют (у них тоже нет значения undefined, но доступ к ним приведет к вам undefined). Вы также не можете перебирать их с помощью for..in.
element.innerHTML = ""; // Replaces body of HTML element with an empty string.
Ярлык для удаления всех дочерних узлов элемента.
Это не совсем Javascript, это DOM, и в настоящее время он нестандартен.
Класс Date в JavaScript, обеспечивающий полу- "Свободный интерфейс". Это компенсирует невозможность напрямую извлечь часть даты из класса Date:
var today = new Date((new Date()).setHours(0, 0, 0, 0));
Это не полностью свободный интерфейс, потому что следующее даст нам только числовое значение, которое на самом деле не является объектом Date:
var today = new Date().setHours(0, 0, 0, 0);
Резервный вариант по умолчанию:
var foo = {}; // empty object literal
alert(foo.bar) // will alert "undefined"
alert(foo.bar || "bar"); // will alert the fallback ("bar")
Практический пример:
// will result in a type error
if (foo.bar.length === 0)
// with a default fallback you are always sure that the length
// property will be available.
if ((foo.bar || "").length === 0)
Как и оператор по умолчанию, || является оператором охраны, &&.
answer = obj && obj.property
в отличие от
if (obj) {
answer = obj.property;
}
else {
answer = null;
}
Это не обязательно должен быть null. Это только в случае, когда obj === null.
Также может использоваться вместе с || для обеспечения резервного копирования в случае, если объект obj вообще не существует, ИЛИ объект существует, а свойство key - нет. Таким образом всегда определяется ответ: answer = (obj && obj.property) || 'backupprop';
Создайте анонимный литерал объекта с помощью простого: ({})
Пример: нужно знать, есть ли у объектов метод valueOf:
var hasValueOf = !! ({}). valueOf
Дополнительный синтаксический сахар: двойное не "!!" для очень лаконичного преобразования почти всего в логическое значение.
В ситуациях парсинга с фиксированным набором комплектующих:
var str = "John Doe";
Вы можете присвоить результаты непосредственно переменным, используя synatx «деструктурирующее присвоение»:
var [fname, lname] = str.split(" ");
alert(lname + ", " + fname);
Что немного читабельнее, чем:
var a = str.split(" ");
alert(a[1] + ", " + a[0]);
Альтернативно:
var [str, fname, lname] = str.match(/(.*) (.*)/);
Обратите внимание, что это функция Javascript 1.7. Итак, на данный момент это браузеры Mozilla 2.0+ и Chrome 6+.
Я попробовал это в консоли Safari Javascript, и это привело к ошибке синтаксического анализа.
Snap, думаю, я использовал это только в Firefox. Я добавил примечание о совместимости с браузером.
Не работает в Chrome 6. Отдает SyntaxError: Unexpected token [.
Небольшое исследование показывает, что версия Chrome 1.7 не совсем стандартная. Сообщается также о проблеме с let: stackoverflow.com/questions/300185/…
Он по-прежнему не работает в Chrome 13. Есть какие-нибудь подсказки относительно того, когда это будет реализовано?
Мне нравится, как просто работать со списками:
var numberName = ["zero", "one", "two", "three", "four"][number];
И хеши:
var numberValue = {"zero":0, "one":1, "two":2, "three":3, "four":4}[numberName];
На большинстве других языков это будет довольно тяжелый код. Значения по умолчанию тоже хороши. Например, сообщение о коде ошибки:
var errorDesc = {301: "Moved Permanently",
404: "Resource not found",
503: "Server down"
}[errorNo] || "An unknown error has occurred";
Выглядит потрясающе, каково это техническое название?
Вот одно, что я только что обнаружил: проверка нуля перед вызовом функции:
a = b && b.length;
Это более короткий эквивалент:
a = b ? b.length : null;
Самое приятное то, что вы можете проверить цепочку свойств:
a = b && b.c && b.c.length;
Немедленно вызываемая стрелочная функция:
var test = "hello, world!";
(() => test)(); //returns "hello, world!";
Преобразование строки в целое число, по умолчанию на 0, если это невозможно,
0 | "3" //result = 3
0 | "some string" -> //result = 0
0 | "0" -> 0 //result = 0
Может быть полезно в некоторых случаях, в основном, когда 0 считается плохим результатом.
var a = 10;
var b = 20;
var text = `${a} + ${b} = ${a+b}`;
тогда переменная текст будет такой, как показано ниже!
10 + 20 = 30
Я не знал об этом || синтаксис значения по умолчанию. Красиво и компактно, хотя и не так интуитивно понятно. (Возможно, я имеют видел это, но так и не понял.)