İşlevleri oluşturan standart formların özeti: (Başlangıçta başka bir soru için yazılmıştır, ancak kanonik soruya taşındıktan sonra uyarlanmıştır.)
Şartları:
Hızlı liste:
İşlev Beyanı
"Anonim" function
İfadesi (terime rağmen, bazen adlarla işlevler oluşturur)
Adlandırılmış function
İfade
Accessor Fonksiyon Başlatıcı (ES5 +)
Ok İşlev İfadesi (ES2015 +) (anonim işlev ifadeleri gibi açık bir ad içermez ve yine de adlarla işlevler oluşturabilir)
Nesne Başlatıcıda Yöntem Bildirimi (ES2015 +)
class
(ES2015 +) 'da Yapıcı ve Yöntem Bildirimleri
İşlev Beyanı
İlk form, şuna benzer bir işlev bildirimidir :
function x() {
console.log('x');
}
İşlev bildirimi bir bildiridir ; bir ifade veya ifade değil. Bu nedenle, bir ile takip etmiyorsunuz ;
(bunu yapmak zararsız olsa da).
Herhangi bir adım adım kod yürütülmeden önce , yürütme göründüğü bağlama girdiğinde bir işlev bildirimi işlenir . Oluşturduğu işleve uygun bir ad verilir ( x
yukarıdaki örnekte) ve bu ad bildirimin göründüğü kapsama girilir.
Aynı bağlamda herhangi bir adım adım koddan önce işlendiğinden, bunun gibi şeyler yapabilirsiniz:
x(); // Works even though it's above the declaration
function x() {
console.log('x');
}
ES2015 kadar, spec gibi bir kontrol yapısı içinde bir işlevi bildirimi koyarsanız bir JavaScript motoru ne yapması gerektiğini kapağı yoktu try
, if
, switch
, while
böyle, vb:
if (someCondition) {
function foo() { // <===== HERE THERE
} // <===== BE DRAGONS
}
Ve adım adım kod çalıştırılmadan önce işlendikleri için, bir kontrol yapısında olduklarında ne yapılacağını bilmek zor.
Bu yapmıyordu rağmen belirtilen ES2015 kadar, bir oldu izin verilen uzatma bloklar halinde destek işlevi beyanlarına. Ne yazık ki (ve kaçınılmaz olarak), farklı motorlar farklı şeyler yaptı.
ES2015 itibariyle, spesifikasyon ne yapacağını söylüyor. Aslında, yapmak için üç ayrı şey verir:
- Gevşek modda bir web tarayıcısında değilse , JavaScript motorunun bir şey yapması gerekir
- Bir web tarayıcısında gevşek moddaysa, JavaScript motorunun başka bir şey yapması gerekir
- İçinde ise katı modda (tarayıcı veya değil), JavaScript motoru henüz başka bir şey yapmak gerekiyordu
Gevşek modlar için kurallar zor, ancak katı modda, bloklardaki işlev bildirimleri kolaydır: Blok için yereldirler ( ES2015'te de yeni olan blok kapsamına sahiptirler) ve üste çekilirler blok. Yani:
"use strict";
if (someCondition) {
foo(); // Works just fine
function foo() {
}
}
console.log(typeof foo); // "undefined" (`foo` is not in scope here
// because it's not in the same block)
"Anonim" function
İfadesi
İkinci ortak forma anonim işlev ifadesi denir :
var y = function () {
console.log('y');
};
Tüm ifadeler gibi, kodun adım adım yürütülmesinde ulaşıldığında değerlendirilir.
ES5'te, bunun oluşturduğu işlevin adı yoktur (anonimdir). ES2015'te, işleve mümkünse bağlamdan çıkarım yaparak bir ad atanır. Yukarıdaki örnekte, ad olacaktır y
. İşlev bir özellik başlatıcısının değeri olduğunda benzer bir şey yapılır. (Bunun ne zaman ve kurallarla ilgili ayrıntılar SetFunctionName
için , spesifikasyonda arayın - her yerde görünür .)
Adlandırılmış function
İfade
Üçüncü form, adlandırılmış bir işlev ifadesidir ("NFE"):
var z = function w() {
console.log('zw')
};
Bu işlemin oluşturduğu işlevin uygun bir adı vardır ( w
bu durumda). Tüm ifadeler gibi bu da kodun adım adım yürütülmesinde ulaşıldığında değerlendirilir. Fonksiyon adıdır olmayan ifadesi göründüğü kapsamına dahil; ad , işlevin kendi kapsamındadır:
var z = function w() {
console.log(typeof w); // "function"
};
console.log(typeof w); // "undefined"
NFE'lerin sık sık JavaScript uygulamaları için bir hata kaynağı olduğunu unutmayın. Örneğin IE8 ve önceki sürümleri, NFE'leri tamamen yanlış işleyerek iki farklı zamanda iki farklı işlev yaratır. Safari'nin ilk sürümlerinde de sorunlar vardı. İyi haber şu ki tarayıcıların mevcut sürümleri (IE9 ve üstü, mevcut Safari) artık bu sorunlara sahip değil. (Ancak bu yazı itibariyle, IE8 yaygın olarak kullanılmaya devam etmektedir ve bu nedenle genel olarak web için kodlu NFE'leri kullanmak hala sorunludur.)
Accessor Fonksiyon Başlatıcı (ES5 +)
Bazen fonksiyonlar büyük ölçüde fark edilmeden gizlenebilir; erişimci işlevlerinde durum böyledir . İşte bir örnek:
var obj = {
value: 0,
get f() {
return this.value;
},
set f(v) {
this.value = v;
}
};
console.log(obj.f); // 0
console.log(typeof obj.f); // "number"
İşlevi kullandığımda kullanmadım ()
! Bunun nedeni , bir özellik için bir erişimci işlevidir . Özelliği normal şekilde alıp ayarlıyoruz, ancak sahne arkasında fonksiyon çağrılıyor.
Ayrıca erişimcisinin işlevleri oluşturabilir Object.defineProperty
, Object.defineProperties
ve daha az bilinen ikinci argüman Object.create
.
Ok İşlev İfadesi (ES2015 +)
ES2015 bize ok işlevini getiriyor . İşte bir örnek:
var a = [1, 2, 3];
var b = a.map(n => n * 2);
console.log(b.join(", ")); // 2, 4, 6
Gördün n => n * 2
içinde şey saklanırken map()
çağrısı? Bu bir işlev.
Ok işlevleri ile ilgili birkaç şey:
Kendilerine ait değiller this
. Bunun yerine, yakın üzerindethis
onlar tanımlanmışlarsa bağlamın. (Ayrıca kapanırlar arguments
ve ilgili oldukları yerde super
.) Bu, this
içlerinde oluşturuldukları yerle aynı olduğu this
ve değiştirilemeyeceği anlamına gelir.
Yukarıdakilerle fark edeceğiniz gibi, anahtar kelimeyi kullanmazsınız function
; bunun yerine kullanırsınız =>
.
Yukarıdaki n => n * 2
örnek bunlardan biri. İşlevi iletmek için birden fazla bağımsız değişkeniniz varsa, parens kullanırsınız:
var a = [1, 2, 3];
var b = a.map((n, i) => n * i);
console.log(b.join(", ")); // 0, 2, 6
( Array#map
Girişin ilk argüman olarak ve dizinin ikincisi olarak geçtiğini unutmayın .)
Her iki durumda da, fonksiyonun gövdesi sadece bir ifadedir; işlevin dönüş değeri otomatik olarak bu ifadenin sonucu olur (açık bir şekilde kullanmazsınız return
).
Yalnızca tek bir ifadeden daha fazlasını yapıyorsanız , normal olarak {}
ve bir açık return
(bir değer döndürmeniz gerekiyorsa) kullanın:
var a = [
{first: "Joe", last: "Bloggs"},
{first: "Albert", last: "Bloggs"},
{first: "Mary", last: "Albright"}
];
a = a.sort((a, b) => {
var rv = a.last.localeCompare(b.last);
if (rv === 0) {
rv = a.first.localeCompare(b.first);
}
return rv;
});
console.log(JSON.stringify(a));
Olmayan sürüme ifade ifadesi veya kısa gövdeli{ ... }
bir ok işlevi denir . (Ayrıca: Kısa bir ok işlevi.) Vücudu tanımlayan, işlev gövdesine sahip bir ok işlevidir . (Ayrıca: Ayrıntılı bir ok işlevi.){ ... }
Nesne Başlatıcıda Yöntem Bildirimi (ES2015 +)
ES2015, yöntem tanımı adı verilen bir işleve başvuran bir özelliği bildirmenin daha kısa bir biçimine izin verir ; şuna benzer:
var o = {
foo() {
}
};
ES5 ve önceki sürümlerde neredeyse eşdeğer:
var o = {
foo: function foo() {
}
};
fark (ayrıntı düzeyi dışında) bir yöntemin kullanabileceği super
, ancak bir fonksiyonun kullanamayacağıdır. Örneğin, valueOf
yöntem sözdizimini kullanarak (örneğin) tanımlayan bir nesneniz varsa super.valueOf()
, değerin Object.prototype.valueOf
döndürülmesini (muhtemelen onunla başka bir şey yapmadan önce) almak için kullanabilirsiniz , oysa ES5 sürümü bunu yapmak zorundaydı Object.prototype.valueOf.call(this)
.
Yöntem bu nesne geçici ise, bu şekilde (mesela, içine geçerken, bu tanımlandı nesnesine bir referans vardır Bu da aracı Object.assign
, kaynak nesnelerden biri olarak), yöntem söz dizimi olabilir nesnenin muhafaza edildiği anlamına aksi takdirde çöp toplanabiliyorsa (JavaScript motoru bu durumu algılamazsa ve yöntemlerden hiçbiri kullanılmıyorsa işleyebilir super
).
class
(ES2015 +) 'da Yapıcı ve Yöntem Bildirimleri
ES2015, class
beyan edilen kurucular ve yöntemler de dahil olmak üzere bize sözdizimini getiriyor :
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return this.firstName + " " + this.lastName;
}
}
Yukarıda iki işlev bildirimi vardır: Biri adı alan yapıcı Person
için getFullName
, diğeri ise atanan bir işlevdir Person.prototype
.