Najlepszy cukier składniowy javascript


81

Oto kilka perełek:

Literały:

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');

Wartości domyślne:

arg = arg || 'default'; // if arg evaluates to false, use 'default', which is the same as:
arg = !!arg ? arg : 'default';

Oczywiście znamy funkcje anonimowe, ale możliwość traktowania ich jako literałów i wykonywania ich na miejscu (jako zamknięcie) jest świetna:

(function() { ... })(); // Creates an anonymous function and executes it

Pytanie: Jaki inny wspaniały cukier składniowy jest dostępny w javascript?


2
Nie byłem tego świadomy || domyślna składnia wartości. Ładny i kompaktowy, choć nie tak intuicyjny. (Może nie widać go, ale nigdy go nie zrozumiał.)
— Chris Noe

1
O wiele trudniej mi było uchwycić trójskładnikową składnię. Po kilkukrotnym napisaniu będzie to wyglądało na drugą naturę. Jeśli chodzi o miejsca, w których mogłeś to zobaczyć, myślę, że używają go zarówno jquery.js, jak i prototype.js.
— powiek

1
Co powiesz na wyjaśnienie każdego z przykładów?
— pc1oad1etter

2
Nie wiedziałem o "arg || 'default'". Spodziewałbym się, że zwróci wartość logiczną, ale zwraca pierwszą wartość (od lewej), której wynikiem jest prawda (podobnie jak w Pythonie)! Jest dużo lepsze niż "arg = arg? Arg: 'default'"!
— Jamol

Chris Noe zastawił ten wątek!
— Mahesh Velaga

Odpowiedzi:


58

Pobieranie aktualnej daty i godziny w milisekundach:

Date.now()

Na przykład, aby określić czas wykonania sekcji kodu:

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

W rzeczywistości jest to najlepszy cukier składniowy javascript. A winnar si yuo.
— powiek

3
OrbMan, to prawdopodobnie zależy od kontekstu; jeśli przekazujesz go jako argument, może być wymuszony na Object, a nie na Number lub String, w którym to przypadku + wymusiłby już to na Number. W rzeczywistości + wydaje się działać jako skrót dla parseInt (value, 10).
— powiek

Korekta: ma pewną różnicę w stosunku do parseInt (wartość, 10). Na przykład + [3] i parseInt ([3], 10) są równe liczbie 3, ale + [3, 4] == NaN i parseInt ([3, 4], 10) == 3.
— bez powiek

Er ... wszystkie te wystąpienia parseInt (wartość, 10) powinny być parseFloat (wartość). I Chris Noe, przepraszam za spam w komentarzach;)
— powiek.

1
Ciekawość popchnęła mnie do wypróbowania tego w jsperf i wydaje się, że najbardziej wydajna jest kanoniczna getTime () :) (ref. Jsperf.com/millisecondsdate )
— sirLisko

33

Test członkostwa obiektu:

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

(„a” we właściwościach) // prawda
(„b” we właściwościach) // prawda
(„c” we właściwościach) // false

Jest to z pewnością bardziej zwięzłe niż props.a === undefined Dzięki.
— powiek

15
I to prawda, nawet jeśli props = {a: undefined}.
— ephemient

FYI - Firefox generuje błąd TypeError podczas próby użycia „in” na obiekcie XPCNativeWrapper. Począwszy od Firefoksa 4, wiele obiektów jest opakowanych. Wracamy więc do props.a === undefined w tych przypadkach.
— Chris Noe,

26

W Mozilli (i podobno IE7) możesz stworzyć stałą XML używając:

var xml = <elem> </elem>;

Możesz również podstawiać zmienne:

var elem = "html";
var text = "Jakiś tekst";
var xml = <{elem}> {text} </ {elem}>;

Naprawdę? Czy są inne silniki, które to obsługują?
— powiek,

1
Zastanawiam się tylko: co możesz zrobić ze zmienną „xml” po jej utworzeniu? Po prostu bawię się nim teraz w firebug, wygląda na to, że nie ma żadnych metod ani właściwości i nie można go dodać do DOM.
— nickf


8
Literały E4X to katastrofa bezpieczeństwa spowodowana atakami z włączaniem skryptów między lokacjami i naprawdę niezauważalnie lepsza niż zwykła możliwość powiedzenia IMO „var xml = new XML ('<elem> </elem>')”.
— bobince

2
@CharlieSomerville To nie jest ryzyko. E4X potencjalnie zamienia „bezpieczne” pliki [X] [HT] ML w aktywny JS. Zapoznaj się z code.google.com/p/doctype/wiki/ArticleE4XSecurity, aby zapoznać się z podstawowymi informacjami na temat tego problemu.
— bobince

26

Korzystanie z funkcji anonimowych i domknięcia do tworzenia zmiennej prywatnej (ukrywanie informacji) i powiązanych metod get / set:

var getter, setter;

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

zajęło mi to chwilę, ale rozumiem. to jest fajne.
— Matt Lohkamp

Podobną technikę odkryłem jakiś czas temu, przeglądając źródło swfobject. Używanie domknięć do tworzenia prywatnych zmiennych / metod jest czymś, o czym prawdopodobnie nigdy bym nie pomyślał. To całkiem fajne.
— Herms

Dzięki nowej wersji JS możemy skorzystać z prostszego if(true) { let _privateVar=123; }
— Kulvar

Należy pamiętać o potencjalnym problemie stylistycznym „psich piłek”. Zobacz: twitter.com/paul_irish/status/176187448420864000?lang=en
— Jonathan.Brink

22

Możliwość rozszerzania natywnych typów JavaScript poprzez dziedziczenie prototypowe.

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

6
Po prostu unikaj robienia tego w Array: stackoverflow.com/questions/61088/ ...
— Chris Noe

To prawda, ale tylko wtedy, gdy używasz pętli for (a in b). Zwykle używam frameworków, tak jak na pewno wszyscy. W konsekwencji zazwyczaj używam
— .each

Jest to potencjalny problem, jeśli jakikolwiek kod w twoim kontenerze używa (a in b). A kiedy tym kontenerem jest przeglądarka, możesz łamać inny kod w swojej przeglądarce (np. Ten framework). Zostałem oszukany przez jednego.
— Chris Noe,

Tak. Dobre punkty, Chris. Nadal uważam dziedziczenie prototypów za jedną z najlepszych cech JavaScript :)
— steve_c

for (var i in obj) {if (! obj.hasOwnProperty (i)) {kontynuuj; } ...}
— powiek

21

Użyj ===do porównania wartości i wpisz:

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

if (i == s) // prawda

if (i === s) // fałsz

W rzeczywistości jest to określane jako ścisłe równe - w zasadzie unika wszystkich konwersji typów, które w przeciwnym razie musiałyby mieć miejsce podczas robienia ==
— olliej

inne języki (PHP) również nazywają to sprawdzaniem tożsamości, tj .: czy te dwie wartości są identyczne ?
— nickf

@nickf, to trochę myląca nazwa. $var1 = 'string'; $var2 = 'string'; $var1 === $var2; // true, chociaż $var1i $var2nie są identyczne (odniesienia do tej samej wartości przechowywanej w pamięci), tylko tego samego typu i tej samej wartości.
— powiek

@eyelidlessness, nie jestem pewien, czy javascript działa w ten sposób ... ciągi są (zwykle) przechowywane i przekazywane przez wartość. Jednakże obiekty są przechowywane jako odniesienie: var1 = {a : 'b'}; var2 = {a : 'b'}; var1 === var2 // false.
— nickf

@nickf, rozumiem to. Ale możesz usunąć sigil w kodzie PHP i uzyskać ten sam wynik w JavaScript. Te ciągi nie są identyczne , ale ich wartości są.
— powiek

21

Ciągi wieloliniowe:

var str = "To jest \
wszystko jedno \
strunowy.";

Ponieważ nie można wciskać kolejnych wierszy bez dodawania białych znaków do łańcucha, ludzie zazwyczaj wolą łączyć z operatorem plus. Ale to zapewnia przyjemną możliwość tworzenia dokumentów .


2
Uczciwe ostrzeżenie - wyjątek zostanie zgłoszony, jeśli po znaku \ 'znajdują się spacje końcowe.
— Daniel Szabo

21

Zmień rozmiar tablicy

length nie jest tylko do odczytu . Możesz go użyć do zwiększenia lub zmniejszenia rozmiaru tablicy.

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
Sir, to chyba najważniejsza odpowiedź na SO, jak sądzę. Nigdy więcej pushdla mnie, hehe. Wielkie dzięki.
— aefxx

4
w rzeczywistości utworzone w ten sposób elementy tak naprawdę nie istnieją (nie mają też niezdefiniowanej wartości, ale dostęp do nich spowoduje niezdefiniowanie). Nie możesz też ich iterować za pomocą for..in.
— yorick

16

Powtarzanie ciągu, takiego jak „-”, określoną liczbę razy, wykorzystując metodę join w przypadku pustej tablicy:

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

Wyniki w postaci „---”, gdy powtórz == 3.


15

Podobnie jak w przypadku operatora domyślnym ||jest operatorem strażnik &&.

answer = obj && obj.property

w przeciwieństwie do

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

1
Nie musi tak być null. Dzieje się tak tylko wtedy, gdy obj === null.
— pimvdb

1
Może być również używany w połączeniu z || w celu zapewnienia kopii zapasowej w przypadku, gdy albo obj w ogóle nie istnieje LUB obiekt istnieje, ale właściwość klucza nie istnieje. W ten sposób odpowiedź jest zawsze definiowana: 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];
});

wywołanie zwrotne do zamiany napisów jest po prostu przydatne.


12

Programy pobierające i ustawiające :

function Foo(bar)
{
    this._bar = bar;
}

Foo.prototype =
{
    get bar()
    {
        return this._bar;
    },

    set bar(bar)
    {
        this._bar = bar.toUpperCase();
    }
};

Daje nam:

>>> var myFoo = new Foo("bar");
>>> myFoo.bar
"BAR"
>>> myFoo.bar = "Baz";
>>> myFoo.bar
"BAZ"

Tak, będzie trochę ładniej niż moje obecne podejście.
— Ash

@eyelidlessness znajduje się w Object.defineProperty ECMAScript 5, który implementuje IE, a inne przeglądarki mogą używać defineGetter .
— Eli Gray

IE8 implementuje tylko metody pobierające / ustawiające obiekty DOM, więc jest bezużyteczne, jeśli chodzi o tworzenie własnych interfejsów API obiektów: - /
— Jonny Buchanan

5

To nie jest wyłączne dla javascript, ale zapisuje jak trzy linie kodu:

check ? value1 : value2

Czy istnieje odpowiednik tego, gdy nie przypisujesz wartości (np. FnName? FnName: defaultFn;)?
— powiek,

1
Nie, operator trójskładnikowy służy wyłącznie do wyrażeń; brak wypowiedzi
— Josh Hinman

1
możesz go użyć do oceny funkcji anonimowych, takich jak ta: "var myFunc = (browserIsIE? function () {...}: function () {...})". osobiście nie polecałbym tego, ponieważ jest to dość zagmatwane, ale przynajmniej jest to możliwe.
— nickf

„oceniać” prawdopodobnie nie jest najlepszym słowem w tym poprzednim komentarzu. Umm .. przypisać?
— nickf

@eyelidlessness: Yes: fnName? fnName (): defaultFn (); // na własnej linii, działa
— Ates Goral

4

Trochę więcej na przykładzie Levika:

var foo = (condition) ? value1 : value2;

4
Nie potrzebujesz nawiasów. Operatory trójskładnikowe są również wspólne dla wielu innych języków.
— Ates Goral

1
Nawiasy pomagają, gdy występuje niejednoznaczność składniowa w instrukcji warunkowej (np. Określenie, do którego składnika instrukcji warunkowej?).
— powiek


4

Po obj || Składnia {domyślna: prawda}:

wywołując swoją funkcję w ten sposób: hello (requiredOne && requiredTwo && needThree) jeśli jeden parametr jest niezdefiniowany lub fałszywy, wywoła hello (false), czasami przydatne


4

W sytuacjach analizowania ze stałym zestawem części składowych:

var str = "John Doe";

Możesz przypisać wyniki bezpośrednio do zmiennych, używając synatx "przypisania destrukturyzacji":

var [fname, lname] = str.split(" ");
alert(lname + ", " + fname);

Co jest nieco bardziej czytelne niż:

var a = str.split(" ");
alert(a[1] + ", " + a[0]);

Na przemian:

var [str, fname, lname] = str.match(/(.*) (.*)/);

Zauważ, że jest to funkcja Javascript 1.7 . W tej chwili są to przeglądarki Mozilla 2.0+ i Chrome 6+.


Wypróbowałem to w konsoli Safari Javascript i powoduje to błąd analizy.
— powiek

Snap, chyba używałem tego tylko w Firefoksie. Dodałem informację o kompatybilności przeglądarki.
— Chris Noe

To nie działa w Chrome 6. Daje SyntaxError: Unexpected token [.
— RaYell,

Trochę badań zaczyna ujawniać, że wersja 1.7 Chrome nie jest całkowicie standardowa. Podobno jest też problem z let: stackoverflow.com/questions/300185/…
— Chris Noe

Nadal nie działa w Chrome 13. Masz jakąś wskazówkę, kiedy to zostanie wdrożone?
— pimvdb

3

Funkcja natychmiastowego wywołania strzałki:

var test = "hello, world!";
(() => test)(); //returns "hello, world!";

2

Zapomniałem:

(function() { ... }).someMethod(); // Functions as objects

2

Utwórz anonimowy literał obiektu za pomocą prostego: ({})

Przykład: musisz wiedzieć, czy obiekty mają metodę valueOf:

var hasValueOf = !! ({}). valueOf

Dodatkowy cukier syntaktyczny: podwójne nie „!!” za bardzo zwięzłe przekształcenie prawie wszystkiego w Boolean.


1

Uwielbiam móc eval () string JSON i odzyskać w pełni wypełnioną strukturę danych. Nienawidzę pisać wszystkiego co najmniej dwa razy (raz dla IE, znowu dla Mozilli).


1

Przypisywanie często używanych słów kluczowych (lub dowolnych metod) do prostych zmiennych, takich jak ths

  var $$ = document.getElementById;

  $$('samText');

3
To nie zadziała (przynajmniej w Chrome), ponieważ thisutracono wartość. Zamiast tego powinieneś użyć document.getElementById.bind(document). Bez bindtego jest po prostu przypisaniem HTMLDocument.prototype.getElementByIdfunkcji, bez informacji, że należy ją wywołać document.
— pimvdb

1

Klasa Date w JavaScript zapewniająca półpłynny interfejs. To rekompensuje brak możliwości bezpośredniego wyodrębnienia części daty z klasy Date:

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

Nie jest to w pełni płynny interfejs, ponieważ poniższe informacje dają nam tylko wartość liczbową, która w rzeczywistości nie jest obiektem Date:

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

1

Domyślna kreacja zastępcza:

var foo = {}; // empty object literal

alert(foo.bar) // will alert "undefined"

alert(foo.bar || "bar"); // will alert the fallback ("bar")

Praktyczny przykład:

// 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

Oto jeden, który właśnie odkryłem: zerowe sprawdzenie przed wywołaniem funkcji:

a = b && b.length;

To jest krótszy odpowiednik:

a = b ? b.length : null;

Najlepsze jest to, że możesz sprawdzić łańcuch nieruchomości:

a = b && b.c && b.c.length;

1

Uwielbiam to, jak łatwo jest pracować z listami:

var numberName = ["zero", "one", "two", "three", "four"][number];

I skróty:

var numberValue = {"zero":0, "one":1, "two":2, "three":3, "four":4}[numberName];

W większości innych języków byłby to dość ciężki kod. Wartości domyślne są również piękne. Na przykład raportowanie kodów błędów:

var errorDesc = {301: "Moved Permanently",
                 404: "Resource not found",
                 503: "Server down"
                }[errorNo] || "An unknown error has occurred";

To wygląda niesamowicie, jaka jest techniczna nazwa tego?
— TrySpace

0

int do rzutowania stringów

var i = 12;
var s = i+"";

3
Nie wygląda to dla mnie bardziej „słodko” niż wykonanie prostej i.toString () lub String (i). Krótki! = Cukier.
— Ates Goral

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

Skrót do usuwania wszystkich węzłów potomnych elementu.


6
To nie jest tak naprawdę Javascript, to DOM i obecnie jest niestandardowy.
— powiek

0

Konwertuj ciąg na liczbę całkowitą, domyślnie 0 jeśli jest to niemożliwe,

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

Może być przydatne w niektórych przypadkach, głównie wtedy, gdy 0 jest uważane za zły wynik


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.