Лучший синтаксический сахар 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


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;
}

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.

1
Сэр, я считаю, что это должен быть самый важный ответ на SO. pushДля меня больше нет , хе-хе. Огромное спасибо.
aefxx

4
на самом деле созданные таким образом элементы на самом деле не существуют (они также не имеют значения undefined, но доступ к ним приведет вас к неопределенному). Вы также не можете перебирать их с помощью for..in.
yorick

16

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

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

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


15

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

answer = obj && obj.property

в отличие от

if (obj) {
    answer = obj.property;
}
else {
    answer = null;
}

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;

4
Скобки не нужны. Тернарные операторы также являются общими для многих других языков.
Атес Горал

1
Скобки помогают при синтаксической неоднозначности в условном операторе (например, при определении того, к какому компоненту условного оператора применяется знак?).
век


4

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

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


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



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;

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";

Выглядит потрясающе, каково это техническое название?
TrySpace


0
element.innerHTML = "";  // Replaces body of HTML element with an empty string.

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


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

0

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

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

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


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.