Найкращий синтаксичний цукор 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
Я цього не знав || синтаксис значення за замовчуванням. Гарний і компактний, хоча і не такий інтуїтивно зрозумілий. (Можливо, я це бачив, але ніколи цього не розумів.)
Кріс Ное

1
Мені було набагато важче зрозуміти потрійний синтаксис. Це буде здаватися другою натурою після того, як ви напишете це кілька разів. Що стосується місць, які ви, можливо, бачили, я думаю, що і jquery.js, і prototype.js використовують це.
безвічність

1
Як щодо пояснення кожного з прикладів?
pc1oad1etter

2
Я не знав про "arg || 'за замовчуванням'". Я би очікував, що він поверне логічне значення, але він повертає перше значення (зліва), яке обчислюється як true (подібно до python)! Це набагато краще, ніж "arg = arg? Arg: 'за замовчуванням'"!
Jamol

Кріс Ное заклав цю нитку!
Махеш Велага,

Відповіді:


58

Отримання поточного часу в мілісекундах:

Date.now()

Наприклад, щоб визначити час виконання розділу коду:

var start = Date.now();
// some code
alert((Date.now() - start) + " ms elapsed");

Насправді це найкращий синтаксичний цукор у JavaScript. Віннар сі юо.
безвічність

3
OrbMan, що, ймовірно, залежить від контексту; якщо передавати його як аргумент, він може бути примушений до Об'єкта, а не до Числа або Рядка, і в цьому випадку + вже примусило б його до Числа. Насправді + видається функцією скорочення для parseInt (значення, 10).
безвічність

Виправлення: воно має певну відмінність від parseInt (значення, 10). Наприклад, + [3] і parseInt ([3], 10) дорівнюють числу 3, але + [3, 4] == NaN і parseInt ([3, 4], 10) == 3.
безвічність

Е-е ... всі ці екземпляри parseInt (value, 10) повинні бути parseFloat (value). І Кріс Ное, вибачте за спам-коментарі;)
безвічність

1
Моя цікавість підштовхнула спробувати його в jsperf, і, здається, найефективнішим є канонічний getTime () :) (посилання jsperf.com/millisecondsdate )
sirLisko

33

Перевірка членства в об'єкті:

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

("a" в реквізиті) // true
("b" у реквізиті) // true
("c" у реквізиті) // false

Це, звичайно, коротше, ніж реквізит. A === Не визначено Дякую.
безвічність

15
І це правда, навіть якщо реквізит = {a: undefined}.
ефемієнт

FYI - Firefox видає помилку TypeError, коли ви намагаєтесь використовувати "in" на об'єкті XPCNativeWrapper. А починаючи з Firefox 4, багато об’єктів загортаються. Тож повернімось до реквізиту. A === у цих випадках не визначено.
Chris Noe

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.03.09

2
@CharlieSomerville Це не ризик. E4X потенційно перетворює "безпечні" файли [X] [HT] ML в активні JS. Будь ласка, прочитайте code.google.com/p/doctype/wiki/ArticleE4XSecurity, щоб дізнатись про основи цієї проблеми.
bobince

26

Використання анонімних функцій та закриття для створення приватної змінної (приховування інформації) та пов’язаних методів get / set:

var getter, setter;

(function()
{
   var _privateVar=123;
   getter = function() { return _privateVar; };
   setter = function(v) { _privateVar = v; };
})()

зайняв у мене хвилинку, але я зрозумів. це Є акуратно.
matt lohkamp

Я виявив подібну техніку деякий час тому, переглядаючи джерело swfobject. Використання закриття для створення приватних змінних / методів - це те, про що я, мабуть, ніколи не думав. Це якось круто.
Гермс

З новою версією JS ми можемо використовувати простішуif(true) { let _privateVar=123; }
Кульвар

Зверніть увагу на проблему стилістичного потенціалу "собачих кульок" тут. Дивіться: twitter.com/paul_irish/status/176187448420864000?lang=en
Джонатан.

22

Можливість розширити власні типи JavaScript за допомогою прототипового успадкування.

String.prototype.isNullOrEmpty = function(input) {
    return input === null || input.length === 0;
}

6
Просто уникайте робити це з Array: stackoverflow.com/questions/61088/…
Кріс Ное

Це правда, але лише якщо ви використовуєте цикл for (a in b). Зазвичай я використовую фреймворки, як я впевнений, що і всі інші. Як наслідок, я зазвичай використовую .each ()
steve_c

Це потенційна проблема, якщо будь-який код у вашому контейнері використовує для (a в b). І коли цей контейнер є браузером, ви можете зламати інший код у своєму браузері (наприклад, цей фреймворк). Мене намочив той.
Chris Noe,

Так. Хороші бали, Кріс. Я все ще вважаю прототипне успадкування однією з найкращих функцій 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) // false

Насправді його називають строгим рівним - в основному він уникає всіх перетворень типів, які в іншому випадку повинні відбутися при виконанні ==
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
насправді створені елементи, використовуючи цей спосіб, насправді не існують (вони також не мають невизначеного значення, але доступ до них призведе до невизначеності). Ви також не можете переглядати їх за допомогою for..in.
yorick

16

Повторення рядка, наприклад "-", певну кількість разів, використовуючи метод join на порожньому масиві:

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 взагалі не існує, АБО об'єкт існує, але властивість ключа не існує. Таким чином відповідь завжди визначається: 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 - це в ECMAScript 5 Object.defineProperty, який 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 (); // на лінії самостійно, працює
Ates Goral

4

Трохи більше на прикладі Левіка:

var foo = (condition) ? value1 : value2;

4
Вам не потрібні дужки. Тернарні оператори також є спільними для багатьох інших мов.
Ates Goral,

1
Дужки допомагають, коли в умовному висловлюванні є синтаксична неоднозначність (наприклад, визначення, до якого компоненту умовного висловлення стосується?).
безвічність


4

Після об’єкту || синтаксис {за замовчуванням: true}:

виклик вашої функції за допомогою цього: hello (neededOne && neededTwo && needThree), якщо один параметр є невизначеним або хибним, тоді він буде викликати hello (false), іноді корисно


4

У ситуаціях розбору з фіксованим набором складових частин:

var str = "John Doe";

Ви можете призначити результати безпосередньо у змінні, використовуючи синатик "призначення деструктуризації":

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. Я додав примітку про сумісність браузера.
Chris Noe,

Це не працює в Chrome 6. Це дає SyntaxError: Unexpected token [.
RaYell,

Невелике дослідження починає виявляти, що хром 1.7 не є цілком стандартним. Як повідомляється, існує проблема і з let: stackoverflow.com/questions/300185/…
Кріс Ное

Він все ще не працює в Chrome 13. Будь-яка підказка щодо того, коли це буде застосовано?
pimvdb



2

Створіть анонімний літерал об’єкта за допомогою просто: ({})

Приклад: потрібно знати, чи мають об’єкти метод valueOf:

var hasValueOf = !! ({}). valueOf

Бонусний синтаксичний цукор: подвійне не "!!" для дуже короткого перетворення майже будь-чого у логічну форму.


1

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


1

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

  var $$ = document.getElementById;

  $$('samText');

3
Це не спрацює (принаймні в Chrome), оскільки thisзначення втрачено. Натомість вам слід використовувати document.getElementById.bind(document). Без bindнього HTMLDocument.prototype.getElementByIdнеможливо лише присвоїти функцію, без інформації про те, до якої її слід викликати document.
pimvdb

1

Клас дати 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

Ось одна, яку я щойно виявив: null check перед викликом функції:

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, і наразі це нестандартно.
безвічність

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.