2015-03-31 18 views
8

Düğüm içinde bazı işlevleri birlikte toplamak için bir ES6 sınıfı kullanıyorum. İşte (temelde) gibi görünüyor: Ben ES6 sınıfları ile, yol, ortak değişkenler basitçe this referans oldu ve bir yapıcı aracılığıyla bu değişkenleri başlatmak için bir yol atamak düşündümES6 yöntemleri null olsun "this" ve sınıf değişkenlerine erişilemiyor

class processDocs { 
    constructor(id) { 
    this.id = id; 
    // console.log(this) returns { id: id } 
    } 

    getDocs(cb) { 
    // console.log(this) returns null 
    docs 
     .query(qb => { 
     qb.where('id', this.id); 
     }) 
     .fetch() 
     .then(function(documents) { 
     cb(null, documents); 
     }) 
    ; 
    } 

    alterDocs(documents, cb) { 
    //some logic 
    } 

    reindexSearch(cb) { 
    //some logic 
    } 

    process() { 
    // console.log(this) returns { id: id } 
    async.waterfall([ 
     this.getDocs, 
     this.alterDocs, 
     this.reindexSearch 
    ]); 
    } 
} 


export default processDocs; 

o nasıl görüneceği tam olarak sınıf tanımımda. Ben yapıcı dan this dışarı console.log zaman, İşte

var Processor = require('./processDocs'); 

var pr = new Processor(id); 
var docs; 
pr.process(); 

mesele, ben tahmin olarak benim { id: id } değeri elde;: I (ayrı bir dosyada) sınıfı çağırıyorum nasıl İşte

var Ancak, process çalıştığında this oturumunu kapattığımda, process çalışıyor, null. AMA, process() içinde this çıkışım hemen önce şelaleden önce, orijinal nesneyi alıyorum.

Bunun için herhangi bir sebep var mı? v0.10.33 ve babel-düğümünü 4.6.6 ve ben --harmony bayrağıyla babel-düğümü çalıştırın:

Btw, ben düğüm kullanıyorum. Herhangi biri sormadan önce, v0.10.x adresinde sıkışmış olan büyük bir bağımlılık nedeniyle daha yeni bir Düğüm versiyonunu güncelleyemiyorum.

EDIT Bir geçici çözüm oluşturmayı başardım ancak çok es6 benzeri değil. Sorun, async.waterfall ile görünüyor. Bunu düzeltmek için bir .bind kullanmak zorunda kaldı:

async.waterfall([ 
     this.getDocs.bind(this), 
     this.alterDocs.bind(this), 
     this.reindexSearch.bind(this) 
    ]); 
+0

sana "çok ES6 benzeri olmayan" ile ne demek alamadım bu konuda okuyabilir? Yöntemler, kendilerine ait değildir, değildir ve kendilerine bağlı olmayacaktır. Btw, eğer gerçek bir ES6 kodu istiyorsanız, o zaman “async” öğesini not edin ve vaatleri kullanın. – Bergi

+0

Ben çok "es6-like" demiyorum çünkü ".bind (this)" 'i kullanmam gerektiğinde kullanmam gerekiyordu. Yani bir dersten bir metot çağırırsam, “bu” nın kaybolacağını mı söylüyorsun? Çünkü bu bana mantıklı gelmiyor. Pr.process() 'yi kullandığımda, bu doğruydu ve this.process()' den this.getDocs 'i çağırdığımda,' bu 'özelliğini de korudu. Bu bir "async" sorunu gibi görünüyor. Ayrıca, Çok ES6 gibi olmak isteseydim, jeneratörler kullanırdım :) Vaatler ES5'tir ve yine de 'async' kullanarak engellemeye çalıştığım şey olan geri arama cehennemine neden olur. – antjanus

+0

Neden .bind() 'i kullanmaya ihtiyacınız olmadığını düşünüyorsunuz? Geçiş referanslarınız başka bir yerdedir. Siz onları * sınıfınızın içinden davet etmiyorsunuz! Vaatler burada uygun çözümdür (çok fazla ES6! Jeneratörler asenkron bir özellik değildir!): 'Process() {return this.getDocs(). Sonra (docs => this.alterDocs (docs)). alteredDocs => his.redindexSearch (alteredDocs)); } ' – Bergi

cevap

3

ES6, "bu" nın nasıl çalıştığını DEĞİŞTİRMEDİ, bu nedenle "her zaman aynı" değer yerine "onu nerede aradığınız" bağlamına bağlıdır. Oldukça anormal değildir ve diğer dillerde yaygın değildir.doğrudan o işlevi çağırmak yoktu çünkü, "docsAsFunction" çağırıyor hangi

class processDocs { 
    constructor(id) { 
    this.id = id; 
    console.log(this) 
    } 

    getDocs(cb) { 
    console.log(this) 
    } 

    alterDocs(documents, cb) { 
    //some logic 
    } 

    reindexSearch(cb) { 
    //some logic 
    } 

    process() { 
    console.log(this) 
    } 
} 

var process = new processDocs(10); 
var docs = process.getDocs(function(){}); 
var processInstance = process.process(); 

var docsAsFunction = process.getDocs; 
docsAsFunction(function(){}); 

çıktı Gördüğünüz gibi

processDocs {id: 10} 
processDocs {id: 10} 
processDocs {id: 10} 
undefined 

bu örneği düşünün, sonuncusu, undefines olduğunu sınıfından, bu nedenle bağlam farklıdır.

Örneğin here

+0

, söylediklerinizi almak için aylarımı aldı ama şimdi anladım. Cevap için teşekkürler! – antjanus

0

Kendimi aşağıdaki işlevleri yarattı.

let bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; //from coffeescript's => operator 

//use in a class's constructor to make the this pointer always refer to the object in which a function resides 
function fixThisPointer(_this, func){ 
    _this[func.name] = bind(_this[func.name], _this); 
} 

function fixThisPointer2(_this, funcNameArray){ 
    for (name of funcNameArray){ 
    _this[name] = bind(_this[name], _this); 
    } 
} 

Ve sonra, ihtiyacınız olduğunda, benim kurucular

fixThisPointer(this, foo) 

Veya onlar otomatik olarak sınıf içinde ok işlevlerini kullanabilirsiniz

fixThisPointer2(this, ['foo', 'foo2', 'foo3']) 
+0

Daha fazlasını es6 benzeri bir yolla incelemek zorundayım Bergi'nin bahsettiği sözleri. –

0

bu komut bu komutu kullanın Bunu bağla.

getDocs = (cb) => { 
    // console.log(this) will not returns null 
    docs 
     .query(qb => { 
     qb.where('id', this.id); 
     }) 
     .fetch() 
     .then(function(documents) { 
     cb(null, documents); 
     }) 
    ; 
} 

this MDN article bkz: gibi sınıf yöntemleri yazabilirsiniz

+0

Son zamanlarda bu modelin yaygınlaştığını gördüm. Nedenini merak ettim. Teşekkürler! – antjanus

0

Buna process() gövdesini güncellemeyi düşünün "Ok fonksiyonları kapsayan bağlamın bu değeri yakalamak":

process() { 
    // console.log(this) returns { id: id } 
    async.waterfall([ 
    (cb)=>{this.getDocs(cb);}, 
    (documents,cb)=>{this.alterDocs(documents,cb);}, 
    (cb)=>{this.reindexSearch(cb);} 
    ]); 
} 

Ok işlevlerini kullanmak, sınıfın üye işlevlerinin doğru bağlamla çağrılmasını sağlar.

İlgili konular