2

Uzun yıllara dayalı programlama programım var (birçok dilde), arka planım Javascript değil. Buna ek olarak, bugünün Javascript'i, ilk yıllar önce oynadığım Javascript değil. Çok daha sofistike ve güçlü. Dedi ki, bazı fonksiyon yükü dinamiklerini anlamak için uğraşıyorum.Javascript işlev yükleme (referans olarak?)

İşlev gerçekten bir şey döndürdüğü işlev çağrıları sezgiseldir, ancak Javascript, kafamı alamadığım işlevlerle ilgili bir şey yapar gibi görünüyor. Kodu kopyalayıp yapıştırabilirim veya bu modeli kendi kodumda nasıl yeniden kullanabileceğimi deneyebilirim. Örneğin, aşağıdaki Mongoose çağrısı, Kullanıcı modelindeki tüm kayıtların bir bulgusunu yapar ve bir şekilde, aramanın sonucu, geçirilen işlevin ikinci argümanında biter (referans olarak?).

User.find({}, function(err, users) { // Get all the users 
    if (err) throw err; 

    console.log(users); // Show the JSON Object  
}); 

Dizide basit bir forEach kullanarak başka bir örnek. Her nasılsa, forEt 'kullanıcı' argümanını doldurur.

users.forEach(function(user) { 
     console.log(user.username, ': Admin = ', (user.admin ? 'Yes' : 'No')); 
}); 

Bunu açıklayan ve/veya bunun nasıl/neden işe yaradığına dair iyi bir rehbere işaret edebilir miyim?

Aynı örüntüyü Node.js'de gördüm ve biraz tökezleyen bir blok.

Açık bir şey mi özledim yoksa bu sadece işlevsel programlama etrafında bir özellik midir?

Jon

+3

Araştırma 'javascript callbacks'. Tekniğin daha genel bir şekilde anlaşılmasını istiyorsanız – charlietfl

+1

Veya [Devam Eden Geçiş Tarzı] (https://en.wikipedia.org/wiki/Continuation-passing_style). – naomik

+0

Bu stilde gerçekten yeni bir şey yok. En eski javascript sürümleri, olay işleyicileri olarak geri aramaları kullandı. – Bergi

cevap

1

Buna Continuation Passing Style adı verilir. Bazen sağladığınız Mongoose örneğindeki gibi eşzamansız davranışları kapsüllemek için kullanılır, ancak diğer zamanlar .forEach örneği gibi senkronize şekilde kullanılabilir. Bunun nasıl çalıştığını

o biz kendi forEach yukarı yaparsanız kolay, görmek için.
function forEach(xs, f) 
    for (var i=0, len=xs.length; i<len; i++) { 
    f(x[i]); 
    } 
} 

forEach([1,2,3], function(x) { console.log(x); }) 

Yani bu işler böyle görmek oldukça kolay olmalıdır: Biz işlevi içinde düzenli for döngü yapmak nerede xs bizim diziye [1,2,3] ayarlandığını görebilirsiniz. Sonra döngünün içinde eleman başına f bir kez çağrıldığını görüyoruz.

burada gerçek güç işlevi JavaScript first-class members olmasıdır ve bu higher-order functions kullanımını sağlar. Bu, .forEach'un bir üst sıra işlevi olarak kabul edildiğini gösterir çünkü bir argüman olarak bir işlevi kabul eder.

Sonradan anlaşıldı ki

, forEach farklı şekillerde bir çok uygulanabilir. Burada başka bir şeydir.

forEach(xs, f) { 
    if (xs.length > 0) { 
    f(xs[0]); 
    forEach(xs.slice(1), f); 
    } 
} 

Buradaki fikir, JavaScript'in etrafındaki işlevleri gönderme konusunda rahat olmanızdır. İşlevleri başka bir işlevin sonucu olarak da döndürebilirsiniz.

function add(x) { 
    return function(y) { 
    return x + y; 
    } 
} 

function map(xs, f) { 
    function loop(ys, xs) { 
    if (xs.length === 0) 
     return ys; 
    else 
     return loop(ys.concat(f(xs[0])), xs.slice(1)); 
    } 
    return loop([], xs); 
} 

map([1,2,3], add(10)); //=> [11,12,13] 

Çok geçmeden, diz boyu functional paradigm ve diğer yeni her türlü şeyi öğrenme olmak olacak.

İşlevler!

+1

'forEach' CPS ile çok fazla ilgisi yok mu? – Bergi

+0

Dolayısıyla geri aramalara odaklanmak kafa karıştırıcı. Benim sorudaki forEach örneğiyle, kullanıcı bir işlev değildir, bir nesnedir, ancak bir Sayı kadar kolay olabilir. CPS biraz aydınlatıcı, ama geri aramalara odaklanma bana yardımcı olmuyor. –

+0

Doğru! Anladığım kadarıyla, kullanıcının bir değer atanmasına kafa karıştırıcı oldum, kullanıcı bir geri arama kapsamında bir değere sahip. Geri arama gizlenmiş olsa da, tamamen açık değildi. –

1

Temel fikir, başka bir işleve argüman olarak bir işlev geçmek ve ne zaman ihtiyacınız sonra diyoruz ki javascript callbacks

gerekir.

function basic(callback){ 
    console.log('do something here'); 

    var result = 'i am the result of `do something` to be past to the callback'; 

    // if callback exist execute it 
    callback && callback(result); 
} 

Bu, javascript'in temel kavramlarından biridir. Ama ajax http istekleri gibi async işlemleri için Promises'a da göz atmanızı tavsiye ederim. Mevcut ES5 spesifikasyonunun bir parçası değil, bunun için birçok kitaplık ve polifiliz bulabilirsiniz.

function get(url) { 
    // Return a new promise. 
    return new Promise(function(resolve, reject) { 
    // Do the usual XHR stuff 
    var req = new XMLHttpRequest(); 
    req.open('GET', url); 

    req.onload = function() { 
     // This is called even on 404 etc 
     // so check the status 
     if (req.status == 200) { 
     // Resolve the promise with the response text 
     resolve(req.response); 
     } 
     else { 
     // Otherwise reject with the status text 
     // which will hopefully be a meaningful error 
     reject(Error(req.statusText)); 
     } 
    }; 

    // Handle network errors 
    req.onerror = function() { 
     reject(Error("Network Error")); 
    }; 

    // Make the request 
    req.send(); 
    }); 
} 

// Use it! 
get('story.json').then(function(response) { 
    console.log("Success!", response); 
}, function(error) { 
    console.error("Failed!", error); 
}); 
+0

Sözler bile geri aramaları kullanır, bu nedenle genel olarak ilk başta geri arama kavramını anlamalısınız. – Bergi

+0

Teşekkürler - çok yararlı –

1

Bu geri aramalar benzer görünmektedir, ancak tamamen farklı amaçlar sunmaktadır. İlk örnekte, geri arama, sonucu almak için kullanılır çünkü User.find, eşzamansız bir işlevdir. Async doğası da Nodejs geri arama argümanları düzeni sözleşmesinin arkasındaki nedendir. Geri aramaların ilk argümanları her zaman hata içindir.

İkinci örnekte, geri aramayı kullanmanın birincil nedeni, döngü içinde bazı zaman uyumsuz işlemleri yürütmek istediğinizde oldukça kullanışlı olan yerel bir kapsam oluşturmaktır. Örneğin: OtherModle.find çalıştırıldığında var ile tanımlanan değişkenler zaten dizinin son öğeden tarafından overwrited edilecektir beri

users.forEach(function(user) { 
    Model.find({},function(er,rows){ 
     if(er){ 
      return handle(er); 
     } 
     OtherModel.find({userid: user.id},function(er,result){ 
      if(er){ 
       return handle(er); 
      } 
      console.log(result); 
     }); 
    }); 
}); 

Yukarıdaki örnek C tarzı döngü ile çalışmaz ısırıyorlar.

+0

Ayrıca yararlı - teşekkürler –

2

Javascript'te, işlevler de nesnelerdir ve değişkenlerde saklanabilir. Başka bir işleve iletilen bir işlev genellikle "geri arama" olarak adlandırılır (bu başka dillerde de kullanılır, ancak oraya gitmeyeceğiz).

Özellikle Array.prototype.forEach için polyfill'a bakmak yararlı olabilir, özellikle de geri çağrıyı tetikleyen satır. Yana

, JavaScript fonksiyonları onlar fonksiyonunu tetiklemek ve hatta o işlev için this değeri özellikle call ve apply, kendi yöntemleri vardır, ayrıca nesneler vardır.

Geri arama örneği (o İşte ... Biliyorum saçma fiddle):

function callIf(val, callbackFn) { 
    // "arguments" is special in javascript, and it's not an array (although it does have an index selector). 
    // I can call Array's slice method passing "arguments" as the "this" of the function 
    var args = Array.prototype.slice.call(arguments, 2); 
    if(val) { 
     callbackFn.apply(this, args); 
    } 
} 

var values = [ 
    "Hop", 
    "on", 
    "Pop", 
    "Sam", 
    "I", 
    "Am" 
]; 


values.forEach(function(val) { 
    // note: referencing inner "log" function instead of "console.log" because "console.log" require's the "this" to be "console". 

    callIf(val.length < 3, log, val + " is a small word."); 

    function log(val) { 
     console.log(val); 
    } 
}); 

Yan not:

statik tip dil ​​arka plandan geliyorlar ve sıra Javascript karşılaşıyorsanız Dinamik olarak yazılan bir dil ilk kez size tavsiyem: Javascript'in getirdiği esnekliği endişelendirme ve benimseme, ama yine de tutarlılığı ve iyi programlama disiplini sağlama. Sadeliği ve okunabilirliği vurgulayın. İyi eğlenceler :)

+0

Teşekkürler - çok yararlı –