Лучший синтаксический сахар javascript

81

Вот несколько жемчужин:

Литералы:

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?

век
источник
2
Я не знал об этом || синтаксис значения по умолчанию. Красиво и компактно, хотя и не так интуитивно понятно. (Может быть , я уже видел, но никогда не понимал его.)
Chris Noe
1
Мне было намного труднее понять тернарный синтаксис. Это будет казаться вашей второй натурой после того, как вы напишете это несколько раз. Насколько вы могли это видеть, я думаю, что и jquery.js, и prototype.js используют его.
век
1
Как насчет объяснения каждого из примеров?
pc1oad1etter
2
Я не знал об "arg || 'default'". Я ожидал, что он вернет логическое значение, но он вернет первое значение (слева), которое оценивается как истина (аналогично python)! Это намного лучше, чем "arg = arg? Arg: 'default'"!
Jamol
Крис Ноу заложил эту тему!
Махеш Велага

Ответы:

58

Получение текущего даты и времени в миллисекундах:

Date.now()

Например, чтобы рассчитать время выполнения раздела кода:

var start = Date.now();
// some code
alert((Date.now() - start) + " ms elapsed");
Крис Ноэ
источник
Фактически, это лучший синтаксический сахар javascript. Виннар си юо.
век
3
OrbMan, это, вероятно, зависит от контекста; если передать его как аргумент, он может быть приведен к объекту, а не к числу или строке, и в этом случае знак + уже привел бы его к числу. Фактически, +, похоже, служит сокращением для parseInt (value, 10).
век
Исправление: есть некоторые отличия от parseInt (value, 10). Например, + [3] и parseInt ([3], 10) равны числу 3, но + [3, 4] == NaN и parseInt ([3, 4], 10) == 3.
Eyelidness
Э ... все эти экземпляры parseInt (value, 10) должны быть parseFloat (value). И Крис Ноу, извините за спам в комментариях;)
слепота
1
Мое любопытство подтолкнуло меня попробовать его в jsperf, и кажется, что наиболее производительным является канонический getTime () :) (исх. Jsperf.com/millisecondsdate )
sirLisko
33

Тест на принадлежность к объекту:

var props = {a: 1, b: 2};

("a" в props) // истина
("b" в реквизитах) // истина
("c" в реквизитах) // ложь
Крис Ноэ
источник
Это определенно более лаконично, чем props.a === undefined Спасибо.
век
15
И это правда, даже если props = {a: undefined}.
ephemient
К вашему сведению - Firefox выдает ошибку TypeError, когда вы пытаетесь использовать «in» для объекта XPCNativeWrapper. И начиная с Firefox 4, множество объектов обернуто. Так что вернемся к props.a === undefined в этих случаях.
Крис Ноэ
26

В Mozilla (и, как сообщается, в IE7) вы можете создать константу XML, используя:

var xml = <elem> </elem>;

Вы также можете заменять переменные:

var elem = "html";
var text = "Немного текста";
var xml = <{elem}> {text} </ {elem}>;
Крис Ноэ
источник
В самом деле? Есть ли другие движки, которые это поддерживают?
век
1
Просто интересно: что вы можете сделать с этой переменной "xml" после ее создания? Просто поиграв с ним сейчас в firebug, похоже, что у него нет никаких методов или свойств, и вы не можете добавить его в DOM.
nickf
Полезная ссылка: developer.mozilla.org/index.php?title=En/…
Крис Ноэ
8
Литералы E4X представляют собой катастрофу для безопасности из-за атак с включением межсайтовых сценариев, и на самом деле не намного лучше, чем просто возможность сказать «var xml = new XML ('<elem> </elem>')» IMO.
bobince 06
2
@CharlieSomerville Это не риск. E4X потенциально превращает «безопасные» [X] [HT] ML-файлы в активные JS. Прочтите code.google.com/p/doctype/wiki/ArticleE4XSecurity, чтобы узнать об этой проблеме.
bob с
26

Использование анонимных функций и закрытия для создания частной переменной (скрытие информации) и связанных методов get / set:

var getter, setter;

(function()
{
   var _privateVar=123;
   getter = function() { return _privateVar; };
   setter = function(v) { _privateVar = v; };
})()
Ясень
источник
заняло у меня мгновение, но я понял. это аккуратно.
Мэтт Лохкамп,
Я обнаружил похожую технику некоторое время назад, просматривая исходный код swfobject. Использование замыканий для создания частных переменных / методов - это то, о чем я, вероятно, никогда бы не подумал. Это круто.
Herms,
С новой версией JS мы можем использовать более простуюif(true) { let _privateVar=123; }
Kulvar
Помните о стилистической потенциальной проблеме "собачьих мячей". См .: twitter.com/paul_irish/status/176187448420864000?lang=en
Jonathan.Brink
22

Возможность расширения собственных типов JavaScript с помощью прототипного наследования.

String.prototype.isNullOrEmpty = function(input) {
    return input === null || input.length === 0;
}
steve_c
источник
6
Просто не делайте этого с массивом: stackoverflow.com/questions/61088/…
Крис Ной,
Это правда, но только если вы используете цикл for (a in b). Обычно я использую фреймворки, как и все остальные. Как следствие, я обычно использую .each ()
steve_c
Это потенциальная проблема, если какой-либо код в вашем контейнере использует for (a in b). И когда этот контейнер является браузером, вы можете нарушить другой код в своем браузере (например, эту структуру). Я был поражен этим.
Крис Ной
Ага. Хорошие замечания, Крис. Я до сих пор считаю прототипное наследование одной из лучших особенностей JavaScript :)
steve_c
for (var i in obj) {if (! obj.hasOwnProperty (i)) {продолжить; } ...}
век
21

Используйте ===для сравнения значения и типа:

var i = 0;
var s = "0";

if (i == s) // правда

if (i === s) // ложь
Крис Ноэ
источник
На самом деле это называется строгим равенством - по сути, он позволяет избежать всех преобразований типов, которые в противном случае должны были бы произойти при выполнении ==
olliej
другие языки (PHP) также называют это «проверкой идентичности», то есть: идентичны ли эти два значения ?
nickf
@nickf, это неправильно. $var1 = 'string'; $var2 = 'string'; $var1 === $var2; // true, даже если $var1и $var2не идентичны (ссылки на одно и то же сохраненное значение в памяти), просто одного типа и одного и того же значения.
век
@eyelidlessness, я не уверен, что javascript так работает ... строки (обычно) хранятся и передаются по значению. Объекты , однако сохраняются в виде ссылки: var1 = {a : 'b'}; var2 = {a : 'b'}; var1 === var2 // false.
nickf
@nickf, я это понимаю. Но вы можете удалить сигил в PHP-коде и получить тот же результат в JavaScript. Эти строки не идентичны , но их значения идентичны .
век
21

Многострочные струны:

var str = "Это \
все один \
строка. ";

Поскольку вы не можете делать отступ в последующих строках, не добавляя пробелов в строку, люди обычно предпочитают объединять с помощью оператора плюс. Но это дает прекрасную возможность документирования .

Крис Ноэ
источник
2
Честное предупреждение - будет выдано исключение, если после \ будут конечные пробелы.
Даниэль Сабо
21

Изменить размер массива

Свойство 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.
pramodc84
источник
1
Сэр, я считаю, что это должен быть самый важный ответ на SO. pushДля меня больше нет , хе-хе. Огромное спасибо.
aefxx
4
на самом деле созданные таким образом элементы на самом деле не существуют (они также не имеют значения undefined, но доступ к ним приведет вас к неопределенному). Вы также не можете перебирать их с помощью for..in.
yorick
16

Повторение строки, такой как «-», определенное количество раз, используя метод соединения для пустого массива:

var s = new Array(repeat+1).join("-");

При повторении == 3 будет получено "---".

J c
источник
15

Как и оператор по умолчанию, ||это оператор-охранник &&.

answer = obj && obj.property

в отличие от

if (obj) {
    answer = obj.property;
}
else {
    answer = null;
}
оборота Skilldrick
источник
1
Это не обязательно должно быть null. Это только тот случай, когда obj === null.
pimvdb
1
Также может использоваться вместе с || для обеспечения резервного копирования в случае, если объект obj вообще не существует, ИЛИ объект существует, а свойство key - нет. Таким образом всегда определяется ответ: answer = (obj && obj.property) || 'backupprop';
Dtipson
13
var tags = {
    name: "Jack",
    location: "USA"
};

"Name: {name}<br>From {location}".replace(/\{(.*?)\}/gim, function(all, match){
    return tags[match];
});

обратный вызов для замены строки просто полезен.

Серкан Йерсен
источник
12

Геттеры и сеттеры :

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: - /
Джонни Бьюкенен
5

Это не эксклюзивный javascript, но сохраняет как три строки кода:

check ? value1 : value2
левик
источник
Есть ли аналог этого, если значение не присваивается (например, fnName? FnName: defaultFn;)?
век
1
Нет, тернарный оператор предназначен только для выражений; никаких заявлений
Джош Хинман
1
вы можете использовать его для оценки анонимных функций, например: "var myFunc = (browserIsIE? function () {...}: function () {...})". Лично я бы не рекомендовал это, поскольку это довольно запутанно, но, по крайней мере, это возможно.
nickf
«оценивать», вероятно, не лучшее слово в предыдущем комментарии. Эмм .. назначить?
nickf
@eyelidlessness: Да: fnName? fnName (): defaultFn (); // на отдельной линии, работает
Атес Горал
4

Еще немного на примере Левика:

var foo = (condition) ? value1 : value2;
VirtuosiMedia
источник
4
Скобки не нужны. Тернарные операторы также являются общими для многих других языков.
Атес Горал
1
Скобки помогают при синтаксической неоднозначности в условном операторе (например, при определении того, к какому компоненту условного оператора применяется знак?).
век
4

После obj || {default: true} синтаксис:

вызов вашей функции с помощью этого: hello (requiredOne && requiredTwo && needThree), если один параметр не определен или false, тогда он вызовет hello (false), иногда полезно

vvo
источник
4

В ситуациях парсинга с фиксированным набором комплектующих:

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 [.
RaYell
Небольшое исследование показывает, что версия Chrome 1.7 не совсем стандартная. Сообщается, что есть проблема и с let: stackoverflow.com/questions/300185/…
Крис Ной,
Это все еще не работает в Chrome 13. Есть какие-нибудь подсказки относительно того, когда это будет реализовано?
pimvdb
3

Немедленно вызываемая стрелочная функция:

var test = "hello, world!";
(() => test)(); //returns "hello, world!";
Джерард Симпсон
источник
2

Я забыл:

(function() { ... }).someMethod(); // Functions as objects
оборота без век
источник
2

Создайте анонимный литерал объекта с помощью простого: ({})

Пример: нужно знать, есть ли у объектов метод valueOf:

var hasValueOf = !! ({}). valueOf

Дополнительный синтаксический сахар: двойное не "!!" для очень краткого преобразования почти всего в логическое значение.

Мкойстинен
источник
1

Мне нравится иметь возможность eval () json-строки и получить обратно полностью заполненную структуру данных. Ненавижу писать все по крайней мере дважды (один раз для IE, снова для Mozilla).

дикрокосия
источник
1

Присвоение часто используемых ключевых слов (или любых методов) простым переменным, таким как ths

  var $$ = document.getElementById;

  $$('samText');
РамешВел
источник
3
Это не сработает (по крайней мере, в Chrome), потому что thisзначение потеряно. Вместо этого вы должны использовать document.getElementById.bind(document). Без bindэтого просто назначается HTMLDocument.prototype.getElementByIdфункция, без информации о том, что она должна быть вызвана document.
pimvdb
1

Класс Date в JavaScript, обеспечивающий полу- "Свободный интерфейс". Это компенсирует невозможность напрямую извлечь часть даты из класса Date:

var today = new Date((new Date()).setHours(0, 0, 0, 0));

Это не полностью свободный интерфейс, потому что следующее даст нам только числовое значение, которое на самом деле не является объектом Date:

var today = new Date().setHours(0, 0, 0, 0);
приятель
источник
1

Резервный вариант по умолчанию:

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) 
петушиная кислота
источник
1

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

a = b && b.length;

Это более короткий эквивалент:

a = b ? b.length : null;

Самое приятное то, что вы можете проверить цепочку свойств:

a = b && b.c && b.c.length;
Lightblade
источник
1

Мне нравится, как просто работать со списками:

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";
manixrock
источник
Выглядит потрясающе, каково это техническое название?
TrySpace
0

int для преобразования строки

var i = 12;
var s = i+"";
Мартейн Лаарман
источник
3
Мне это не кажется более «приторным», чем выполнение прямого i.toString () или String (i). Коротко! = Сахар.
Атес Горал,
0
element.innerHTML = "";  // Replaces body of HTML element with an empty string.

Ярлык для удаления всех дочерних узлов элемента.

pramodc84
источник
6
Это не совсем Javascript, это DOM, и в настоящее время он нестандартен.
век 01
0

Преобразование строки в целое число, по умолчанию на 0, если это невозможно,

0 | "3" //result = 3
0 | "some string" -> //result = 0
0 | "0" -> 0 //result = 0

Может быть полезно в некоторых случаях, в основном, когда 0 считается плохим результатом

Раймондс
источник
0

Литералы шаблона

var a = 10;
var b = 20;
var text = `${a} + ${b} = ${a+b}`;

тогда текстовая переменная будет такой, как показано ниже!

10 + 20 = 30

Мохан Кумар
источник