Javascript'te, bunu ne zaman kullanmak istersiniz:
(function(){
//Bunch of code...
})();
bunun üzerinde:
//Bunch of code...
Javascript'te, bunu ne zaman kullanmak istersiniz:
(function(){
//Bunch of code...
})();
bunun üzerinde:
//Bunch of code...
Yanıtlar:
Her şey değişken kapsam belirleme ile ilgilidir. Otomatik yürütme işlevinde bildirilen değişkenler varsayılan olarak yalnızca otomatik yürütme işlevi içindeki kod için kullanılabilir. Bu, değişkenlerin diğer JavaScript kod bloklarında nasıl adlandırıldığından endişe etmeden kodun yazılmasına izin verir.
Örneğin, Alexander tarafından yapılan bir yorumda belirtildiği gibi :
(function() {
var foo = 3;
console.log(foo);
})();
console.log(foo);
Bu, ilk günlüğe kaydeder 3
ve ardından sonraki bir hata atmak console.log
NEDENİYLE foo
tanımlı değil.
var
böyle: ...function(){ foo=3;}
? Global değişken belirleyecekti, değil mi?
function(){ var foo = 3; alert(foo); }; alert(foo);
Bu yüzden hala anlamıyorum
Basit. Çok normal bir görünüm, neredeyse rahatlatıcı:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
Ancak, sayfama gelişmiş karakterleri temel düzey gösterimlerine çeviren gerçekten kullanışlı bir javascript kitaplığı eklersem ne olur?
Bir dakika ne?
Demek istediğim, birisi üzerinde aksanı olan bir karakter yazıyorsa, ama sadece programımda AZ 'İngilizce' karakterler istiyorum? Şey ... İspanyolca 'ñ' ve Fransızca 'é' karakterleri 'n' ve 'e' nin temel karakterlerine çevrilebilir.
Bu yüzden iyi biri, siteme ekleyebileceğim kapsamlı bir karakter dönüştürücü yazdı ... Ben de dahil ediyorum.
Bir sorun: İçinde benim işlevimle aynı 'isim' adlı bir işlevi var.
Çarpışma denen şey budur. Aynı bildirilen iki işlevi var kapsamı aynı adla. Bundan kaçınmak istiyoruz.
Bu yüzden kodumuzu bir şekilde kapsamamız gerekiyor.
Javascript kod kapsamı için tek yolu bir işlevde sarmak için:
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Bu bizim sorunumuzu çözebilir. Artık her şey kapalı ve sadece açılış ve kapanış parantezlerimizden erişilebilir.
Bir fonksiyonda bir fonksiyonumuz var ... bakmak garip ama tamamen yasal.
Sadece bir sorun. Kodumuz çalışmıyor. UserName değişkenimiz asla konsola yansıtılmaz!
Mevcut kod bloğumuzdan sonra fonksiyonumuza bir çağrı ekleyerek bu sorunu çözebiliriz ...
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
main();
Ya da önce!
main();
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
İkincil bir endişe: 'Ana' isminin henüz kullanılma ihtimali nedir? ... çok, çok ince.
DAHA FAZLA kapsam belirlemeye ihtiyacımız var. Ve ana () işlevimizi otomatik olarak yürütmenin bir yolu.
Şimdi otomatik yürütme işlevlerine (veya kendi kendine, kendi kendine çalışan, her neyse) geliyoruz.
((){})();
Sözdizimi günah olarak gariptir. Ancak işe yarıyor.
Bir işlev tanımını parantez içine aldığınızda ve bir parametre listesi (başka bir küme veya parantez!) Eklediğinizde, işlev çağrısı olarak işlev görür .
Bu yüzden, kendi kendini yürüten sözdizimi ile kodumuza tekrar bakalım:
(function main() {
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
)();
Yani, okuduğunuz çoğu öğreticide, artık 'anonim kendi kendini yürütme' terimi veya benzer bir şeyle bombardıman olacaksınız.
Yıllarca süren mesleki gelişimden sonra, hata ayıklama amacıyla yazdığınız her işlevi adlandırmanızı şiddetle tavsiye ediyorum .
Bir şeyler ters gittiğinde (ve olacak), tarayıcınızdaki geri izlemeyi kontrol edeceksiniz. Öyle her zaman yığın izleme girişleri ada sahip olduklarında kodunuzu sorunları daraltmak için daha kolay!
Çok uzun soluklu ve umarım yardımcı olur!
:)
Kendi kendine çağırma (otomatik çağırma olarak da bilinir), bir işlev tanımının hemen ardından yürütülür. Bu temel bir modeldir ve diğer birçok JavaScript geliştirme modelinin temelini oluşturur.
Ben büyük bir hayranıyım :) çünkü:
Muazzam bir şekilde - (Neden iyi olduğunu söylemelisin?)
Daha burada .
Ad alanlarının. JavaScript'in kapsamları işlev düzeyindedir.
Cevapların hiçbirinin ima edilen küresellerden bahsettiğine inanamıyorum.
(function(){})()
Yapı bkz bana büyük endişe olduğunu ima globaller, karşı koruma sağlamaz http://yuiblog.com/blog/2006/06/01/global-domination/
Temel olarak işlev bloğu, tanımladığınız tüm bağımlı "global değişkenler" in programınızla sınırlı olmasını sağlar, sizi örtülü globalleri tanımlamaya karşı korumaz. JSHint veya benzerleri, bu davranışa karşı nasıl savunma yapılacağına dair öneriler sağlayabilir.
Daha özlü var App = {}
sözdizimi benzer bir koruma düzeyi sağlar ve 'genel' sayfalardayken işlev bloğuna sarılabilir. ( bu yapıyı kullanan kütüphanelerin gerçek dünya örnekleri için Ember.js veya SproutCore'a bakın )
Mülklere gelince private
, kamusal bir çerçeve veya kütüphane oluşturmadığınız sürece biraz abartılıyorlar, ancak bunları uygulamanız gerekiyorsa, Douglas Crockford'un bazı iyi fikirleri var.
Bütün cevapları okudum, burada çok önemli bir şey eksik , Öpeceğim. Neden kendi kendini yürüten anonim işlevlere ihtiyacım veya daha iyi " Hemen çağırılan işlev ifadesi (IIFE) " dedi 2 ana nedeni vardır :
İlki çok iyi açıklandı. İkincisi için lütfen aşağıdaki örneği inceleyin:
var MyClosureObject = (function (){
var MyName = 'Michael Jackson RIP';
return {
getMyName: function () { return MyName;},
setMyName: function (name) { MyName = name}
}
}());
Dikkat 1: Daha MyClosureObject
fazla bu işlevi çağırmanın sonucu olarak bir işlev atamıyoruz . ()
Son satırdan haberdar olun .
Dikkat 2: Javascript'teki işlevler hakkında ek olarak bilmeniz gerekenler, iç işlevlerin, içinde tanımlandıkları işlevlerin parametrelerine ve değişkenlerine erişebilmesidir .
Bazı deneyleri deneyelim:
Ben alabilirim MyName
kullanarak getMyName
ve çalışır:
console.log(MyClosureObject.getMyName());
// Michael Jackson RIP
Aşağıdaki ustaca yaklaşım işe yaramaz:
console.log(MyClosureObject.MyName);
// undefined
Ama başka bir isim ayarlayabilir ve beklenen sonucu elde edebilirim:
MyClosureObject.setMyName('George Michael RIP');
console.log(MyClosureObject.getMyName());
// George Michael RIP
Düzenleme: Yukarıdaki örnekte önek MyClosureObject
olmadan kullanılmak üzere tasarlanmıştır new
, bu nedenle konvansiyon ile büyük harfle yazılmamalıdır.
Bir parametre var mı ve "Kod grubu" bir işlev döndürüyor mu?
var a = function(x) { return function() { document.write(x); } }(something);
Kapanış. something
Atanan işlev tarafından kullanılan değeri a
. something
(döngü için) bazı değişken değerlere sahip olabilir ve a'nın her yeni işlevi olduğunda.
var x = something;
de dış fonksiyonda x
parametre olarak açık bir şekilde tercih ederim : imo bu şekilde daha okunabilir ...
x
ve doğrudan sözcüksel kapsama bağlı kalırsanız yeni değer kullanılır , yani document.write(something)
...
Belki kapsam izolasyonu. Böylece işlev bildirimindeki değişkenler dış ad alanını kirletmez.
Tabii ki, orada JS uygulamalarının yarısında, yine de yapacaklar.
Kendini çağıran anonim bir işlevin nasıl yararlı olabileceğine dair sağlam bir örnek.
for( var i = 0; i < 10; i++ ) {
setTimeout(function(){
console.log(i)
})
}
Çıktı: 10, 10, 10, 10, 10...
for( var i = 0; i < 10; i++ ) {
(function(num){
setTimeout(function(){
console.log(num)
})
})(i)
}
Çıktı: 0, 1, 2, 3, 4...
let
yerine var
birinci durumda düzelecek.
Javascript'teki işlevler birinci sınıf nesne olduğundan, onu bu şekilde tanımlayarak, C ++ veya C # gibi bir "sınıfı" etkili bir şekilde tanımlar.
Bu işlev yerel değişkenleri tanımlayabilir ve içinde işlevlere sahip olabilir. Dahili işlevler (etkin örnek yöntemleri) yerel değişkenlere (etkin örnek değişkenleri) erişebilir, ancak komut dosyasının geri kalanından yalıtılır.
Javascript kendinden çağrılan fonksiyonu:
Kendini çağıran bir ifade çağrılmadan otomatik olarak çağrılır (başlatılır). Kendini çağıran bir ifade, oluşturulduktan hemen sonra çağrılır. Bu, temel olarak, adlandırma çatışmasını önlemek ve kapsüllemeyi sağlamak için kullanılır. Değişkenlere veya bildirilen nesnelere bu işlevin dışında erişilemez. Minimizasyon (filename.min) problemlerinden kaçınmak için her zaman kendi kendine yürütülen işlevi kullanın.
Kendi kendini yürütme işlevi, bir Değişkenin kapsamını yönetmek için kullanılır.
Bir değişkenin kapsamı, programınızın tanımlandığı bölgesidir.
Küresel bir değişkenin küresel kapsamı vardır; JavaScript kodunuzun her yerinde tanımlanır ve komut dosyasındaki herhangi bir yerden, hatta işlevlerinizden erişilebilir. Öte yandan, bir işlev içinde bildirilen değişkenler yalnızca işlevin gövdesi içinde tanımlanır. Yerel değişkenlerdir, yerel kapsama sahiptirler ve yalnızca bu işlev içinde erişilebilirler. İşlev parametreleri de yerel değişkenler olarak sayılır ve yalnızca işlevin gövdesi içinde tanımlanır.
Aşağıda gösterildiği gibi, işleviniz içindeki global değişken değişkene erişebilir ve ayrıca bir işlev gövdesi içinde yerel bir değişkenin aynı ada sahip bir global değişkene göre öncelikli olduğunu unutmayın.
var globalvar = "globalvar"; // this var can be accessed anywhere within the script
function scope() {
alert(globalvar);
localvar = "localvar" //can only be accessed within the function scope
}
scope();
Temel olarak kendi kendini yürüten bir işlev, değişkenlerin diğer javascript kod bloklarında nasıl adlandırıldığından endişe etmeden kodun yazılmasına izin verir.
(function(){
var foo = {
name: 'bob'
};
console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error
Aslında, yukarıdaki fonksiyon isimsiz fonksiyon ifadesi olarak değerlendirilecektir.
Bir işlevi yakın ve açık parantez ile sarmanın temel amacı, küresel alanı kirletmekten kaçınmaktır.
İşlev ifadesinin içindeki değişkenler ve işlevler özel hale geldi (yani) işlevin dışında kullanılamayacaklar.
Kısa cevap: Küresel (veya daha yüksek) kapsamın kirlenmesini önlemek.
IIFE (Hemen Çağırılan İşlev İfadeleri), komut dosyalarını eklenti, eklenti, kullanıcı komut dosyası veya diğer komut dosyalarıyla çalışması beklenen komut dosyaları olarak yazmak için en iyi uygulamadır . Bu, tanımladığınız herhangi bir değişkenin diğer komut dosyaları üzerinde istenmeyen etkiler vermemesini sağlar.
Bu, IIFE ifadesini yazmanın diğer yoludur. Şahsen bu yöntemi tercih ederim:
void function() {
console.log('boo!');
// expected output: "boo!"
}();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
Yukarıdaki örnekten, IIFE'nin verimliliği ve performansı da etkileyebileceği çok açıktır, çünkü sadece bir kez çalıştırılması beklenen fonksiyon bir kez yürütülür ve daha sonra iyilik için boşluğa atılır . Bu, işlev veya yöntem bildiriminin bellekte kalmadığı anlamına gelir.
void
önce bu kullanımı görmemiştim . Bunu sevdim.
Önce MDN IIFE'yi ziyaret etmelisiniz , Şimdi bununla ilgili bazı noktalar
Görünüşe göre bu soru tamamen cevaplandı, ama yine de girdimi göndereceğim.
Kendini yürütme işlevlerini ne zaman kullanmayı sevdiğimi biliyorum.
var myObject = {
childObject: new function(){
// bunch of code
},
objVar1: <value>,
objVar2: <value>
}
İşlev, childObjects özniteliklerini ve daha sık kullanılan değişkenlerin ayarlanması veya matematik denklemlerinin yürütülmesi; Ah! veya hata kontrolü. iç içe nesne örnekleme sözdizimi ile sınırlı olmanın aksine ...
object: {
childObject: {
childObject: {<value>, <value>, <value>}
},
objVar1: <value>,
objVar2: <value>
}
Genel olarak kodlamanın, aynı şeyleri yapmak için çok belirsiz yöntemleri vardır, "Neden rahatsız oluyorsunuz?" Ancak artık yalnızca temel / çekirdek prensiplere güvenemeyeceğiniz yeni durumlar ortaya çıkıyor.
Basit sorunuz varsa: "Javascript'te, bunu ne zaman kullanmak istersiniz: ..."
@Ken_browning ve @ sean_holding'in cevaplarını seviyorum, ancak burada bahsetmediğim başka bir kullanım örneği:
let red_tree = new Node(10);
(async function () {
for (let i = 0; i < 1000; i++) {
await red_tree.insert(i);
}
})();
console.log('----->red_tree.printInOrder():', red_tree.printInOrder());
Burada Node.insert bazı eşzamansız eylemlerdir.
Ben sadece benim işlev beyanında async anahtar sözcüğü olmadan bekleyemezsiniz, ve daha sonra kullanmak için adlandırılmış bir işleve gerek yok, ama bu arama eklemek için beklemek gerekir veya ben (kim bilir?) Bazı daha zengin özelliklere ihtiyacım var .
IIRC özel özellikler ve yöntemler oluşturmanıza olanak sağlar.