Nesne değişmezlerinde / başlatıcılarında öz referanslar


706

Aşağıdaki gibi bir şeyin JavaScript'te çalışmasını sağlamanın bir yolu var mı?

var foo = {
    a: 5,
    b: 6,
    c: this.a + this.b  // Doesn't work
};

Mevcut formda, bu kod, thisbaşvurmadığı için bir referans hatası atar foo. Ancak , bir nesne hazır bilgisinin özelliklerinde daha önce bildirilen diğer özelliklere bağlı değerlerin bulunmasının herhangi bir yolu var mı?

Yanıtlar:


744

Size anlatabileceğim tek şey alıcı :

var foo = {
  a: 5,
  b: 6,
  get c() {
    return this.a + this.b;
  }
}

console.log(foo.c) // 11

Bu, ECMAScript 5. Baskı Spesifikasyonu tarafından sunulan sözdizimsel bir uzantıdır, sözdizimi çoğu modern tarayıcı (IE9 dahil) tarafından desteklenir.


32
Çok yardımcı bir cevap. 'Get' hakkında daha fazla bilgiyi burada bulabilirsiniz: developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/…
jake

5
@FaustoR. Evet öyle.
Charlie Martin

48
Bu çözüm ile foo.aveya değerleri değiştirilirse, senkronizasyonda da foo.bdeğerin değişeceğine dikkat edin foo.c. Gerekli olan bu olabilir veya olmayabilir.
HBP

8
thisEn derin yuvalanmış nesneye bağlandığını unutmayın . Örn:... x: { get c () { /*this is x, not foo*/ } } ...
Z. Khullah

3
Çünkü benim yukarıdaki ifadeyi tamamlamak için foobir değişken olarak ilan beeing ve ckullanma, sadece çağrılır anda değerlendirilecektir fooiçini cçalışacak aksine, this(dikkatli gerçi)
Z. Khullah

316

Şöyle bir şey yapabilirsiniz:

var foo = {
   a: 5,
   b: 6,
   init: function() {
       this.c = this.a + this.b;
       return this;
   }
}.init();

Bu, nesnenin bir kez bir kez başlatılması olabilir.

Not aslında dönüş değeri atamak olduğunu init()için foobu yüzden zorunda return this.


95
Ayrıca edebilir delete this.initönce return thisböylece foopoluted edilmez
Billy Ay'ı

15
@BillyMoon: Evet, ancak bunu yapmak , o nesnedeki sonraki tüm özellik erişimlerinin performansını birçok motorda (örneğin V8) etkiler .
TJ Crowder

8
@MuhammadUmer: ES6 sınıflarının soruyla ne kadar alakalı olduğundan emin değilim.
Felix Kling

8
@MuhammadUmer: sınıflar sadece yapıcı işlevler için sözdizimsel şekerdir, bu yüzden gerçekten yeni bir şey sağlamazlar. Her iki durumda da, bu sorunun ana odağı nesne değişmezleridir.
Felix Kling

3
@akantoword: Harika :) nesne değişmezleri tek bir ifade olduğundan, init()çağrıyı doğrudan tek bir ifade tutmak için doğrudan değişmeze eklenir. Ama tabii ki fonksiyonu istediğiniz gibi ayrı ayrı arayabilirsiniz.
Felix Kling

181

Açık, basit cevap eksik, bu yüzden tamlık için:

Ancak , bir nesne hazır bilgisinin özelliklerinde daha önce bildirilen diğer özelliklere bağlı değerlerin bulunmasının herhangi bir yolu var mı?

Hayır. Buradaki tüm çözümler nesneyi oluşturulana kadar (çeşitli şekillerde) erteleyin ve sonra üçüncü özelliği atayın. En basit yol sadece bunu yapmaktır:

var foo = {
    a: 5,
    b: 6
};
foo.c = foo.a + foo.b;

Diğerlerinin hepsi aynı şeyi yapmanın daha dolaylı yoludur. (Felix, özellikle zekidir, ancak geçici bir işlev oluşturmayı ve yok etmeyi, karmaşıklık eklemeyi gerektirir; ya da nesneye fazladan bir özellik bırakır veya [ deletebu özellik sizseniz ] söz konusu nesne üzerindeki sonraki özellik erişimlerinin performansını etkiler .)

Tümünün tek bir ifadede olması gerekiyorsa, bunu geçici özellik olmadan yapabilirsiniz:

var foo = function(o) {
    o.c = o.a + o.b;
    return o;
}({a: 5, b: 6});

Veya elbette, bunu bir kereden fazla yapmanız gerekiyorsa:

function buildFoo(a, b) {
    var o = {a: a, b: b};
    o.c = o.a + o.b;
    return o;
}

o zaman onu kullanmanız gereken yer:

var foo = buildFoo(5, 6);

Kendi akıl sağlığım için, temelde aynı şeyi söyleyen bir tür resmi belge bulmaya çalışıyorum - bir nesnenin thissadece söz konusu nesnenin yöntemleri için kullanılabilir ve başka tür özellikler yok. Bunu nerede bulabileceđime dair bir fikrin var mý? Teşekkürler!
David Kennell

1
@DavidKennell: Spesifikasyondan daha resmi olamaz . :-) Muhtemelen buradan başlayıp takip edersiniz . Oldukça garip bir dildir, ancak temel olarak Özellik Tanımlaması Değerlendirmesinin çeşitli alt maddelerinde , nesnenin özellik başlatıcılarının değerlerini belirleyen işlemler tarafından kullanılamadığını görürsünüz .
TJ Crowder

Burada browserscope sonuçlarını göremiyorum , ama artık durum böyle değil mi? Ortamımda v8: delete% 10 daha hızlı ve gecko: deletesadece% 1 daha yavaş.
TheMaster

1
@TheMaster - Evet, artık BrowserScope'un gerçekten bir şey olduğunu sanmıyorum. Silme, eskisi kadar kötü değil, en azından V8 (Chrome vb.) Veya SpiderMonkey'de değil. Hala daha yavaş, ama sadece küçük bir parça ve bu şeyler bu günlerde acayip hızlı.
TJ Crowder

63

Anonim bir işlevi başlatmanız yeterlidir:

var foo = new function () {
    this.a = 5;
    this.b = 6;
    this.c = this.a + this.b;
};

1
@Bergi, neden? Birisi aynı nesnenin bir başkasını ondan başlatabileceği için mi? Bir nesneyi gerçek anlamda klonlayamadıkları gibi değil. new Point(x, y)İşlevin yeniden kullanım için adlandırılmaması dışında bir argüman iletmekten farklı değildir.
zzzzBov

1
@zzzzBov: Tabii ki nesneyi klonlayabilirler, ancak IEFE çözümüyle (TJCrowder'ın cevabında olduğu gibi) karşılaştırıldığında çözümünüz yapıcı işlevinden sızar ve gereksiz bir prototip nesnesi oluşturur.
Bergi

5
@zzzzBov: Sadece var foo = function() { this.…; return this; }.call({});sözdizimsel olarak çok farklı değil, anlamsal olarak aklı başında olanı kullanın .
Bergi

1
@ Bergi, bunun önemli olduğunu düşünüyorsanız, neden karışıma kendi cevabınızı eklemiyorsunuz?
zzzzBov

3
Buna sahipsiniz. Gerçekten newanahtar kelimeyi fark etmedim .
Randy

26

Şimdi ES6'da tembel önbellek özellikleri oluşturabilirsiniz. İlk kullanımda, özellik normal statik özellik haline gelmek için bir kez değerlendirilir. Sonuç: Matematik işlevi ek yükü ikinci kez atlandığında.

Sihir alıcıda.

const foo = {
    a: 5,
    b: 6,
    get c() {
        delete this.c;
        return this.c = this.a + this.b
    }
};

Ok getter olarak thisalır çevreleyen sözcük kapsamını .

foo     // {a: 5, b: 6}
foo.c   // 11
foo     // {a: 5, b: 6 , c: 11}  

1
es5 ayrıca Object.defineProperty(foo, 'c', {get:function() {...}})bunları tanımlamak için kullanmanız gereken özelliklere de sahiptir . Bu, böyle bir fabrikada kolayca mütevazi bir şekilde yapılır. Tabii ki getşekeri kullanabiliyorsanız daha kolay okunabilir ama yeteneği orada.
Aluan Haddad

21

Bazı kapanmalar bununla başa çıkmalıdır;

var foo = function() {
    var a = 5;
    var b = 6;
    var c = a + b;

    return {
        a: a,
        b: b,
        c: c
    }
}();

Değişkenler içinde bildirilen tüm fooözeldir fooEğer herhangi bir işlev bildirimiyle beklediğiniz gibi ve onlar kapsamda tüm çünkü, hepsi başvurmak zorunda kalmadan birbirlerine erişebilir thisbir işlevle bekleneceği gibi,. Fark, bu işlevin özel değişkenleri ortaya çıkaran ve o nesneyi atayan bir nesneyi döndürmesidir foo. Sonunda, yalnızca return {}ifade ile nesne olarak göstermek istediğiniz arabirimi döndürürsünüz .

Daha sonra fonksiyon, sonunda ()tüm foo nesnesinin değerlendirilmesine, somutlaştırılmış tüm değişkenlerin ve dönüş nesnesi'nin özellikleri olarak eklenmesine neden olan sonunda yürütülür foo().


14
Buna "kapanış" demek kafa karıştırıcı ve yanıltıcıdır. Her ne kadar bir işlevden ojbect değeri döndürmek kesin anlamlar üzerine düşünceler farklılık gösterse de kimsenin kitabında bir kapanış oluşturmaz.

16

Böyle yapabilirsin

var a, b
var foo = {
    a: a = 5,
    b: b = 6,
    c: a + b
}

Bir işlevin başlangıçta bildirildiği nesneye başvurmam gerektiğinde bu yöntemin benim için yararlı olduğu kanıtlanmıştır. Aşağıdaki nasıl kullandığımın minimal bir örneğidir:

function createMyObject() {
    var count = 0, self
    return {
        a: self = {
            log: function() {
                console.log(count++)
                return self
            }
        }
    }
}

Kendini yazdırma işlevini içeren nesne olarak tanımlayarak, işlevin bu nesneye başvurmasına izin verirsiniz. Bu, başka bir yere geçirmeniz gerekiyorsa yazdırma işlevini bir nesneye 'bağlamanız' gerekmeyeceği anlamına gelir.

Bunun yerine, thisaşağıda gösterildiği gibi kullanın

function createMyObject() {
    var count = 0
    return {
        a: {
            log: function() {
                console.log(count++)
                return this
            }
        }
    }
}

Ardından aşağıdaki kod 0, 1, 2'yi kaydeder ve bir hata verir

var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!

Self yöntemini kullanarak, işlevin hangi bağlamda çalıştırıldığına bakılmaksızın, baskının her zaman aynı nesneyi döndüreceğini garanti edersiniz. Yukarıdaki kod iyi çalışır ve kendi sürümünü kullanırken 0, 1, 2 ve 3 günlüğünü işler createMyObject().


3
Tüm noktalı virgülleri hariç tutmanız dışında iyi örnekler.

1
Hiçbir noktalı virgül - It en ince Gerçekten!
Kerem Baydoğan

9

Tamamlama için, ES6'da sınıflarımız var (bunu yalnızca en yeni tarayıcılar tarafından yazılırken desteklenir, ancak Babel, TypeScript ve diğer transpillerde kullanılabilir)

class Foo {
  constructor(){
    this.a = 5;
    this.b = 6;
    this.c = this.a + this.b;
  }  
}

const foo = new Foo();

7

Modül desenini kullanarak yapabilirsiniz. Tıpkı:

var foo = function() {
  var that = {};

  that.a = 7;
  that.b = 6;

  that.c = function() {
    return that.a + that.b;
  }

  return that;
};
var fooObject = foo();
fooObject.c(); //13

Bu desen ile birkaç foo nesnesini ihtiyacınıza göre başlatabilirsiniz.

http://jsfiddle.net/jPNxY/1/


2
Bu modül modeline bir örnek değil, sadece bir fonksiyon. Eğer foo tanımının son satırı, }();bir fonksiyonu değil, bir nesneyi kendi kendine çalıştırır ve döndürür. Ayrıca, foo.cbir işlevdir, bu yüzden ona çalışan clobbers ve bir sonraki çağırma fooObject.c()başarısız olur. Belki de bu keman , ne istediğinize daha yakındır (aynı zamanda somutlaştırılmak üzere tasarlanmamış bir singleton).
Hollister

2
"Modül modeli başlangıçta geleneksel yazılım mühendisliğindeki sınıflar için hem özel hem de genel kapsülleme sağlamanın bir yolu olarak tanımlanmıştır". Gönderen: JavaScript Tasarım Desenlerini Öğrenme . Bu nesne yukarıda açıklanan modül modelini takip eder, ancak kamu ve özel mülkleri / yöntemleri göstermediği için bunu açıklamak en iyisi olmayabilir. Bu bir jsfiddle.net/9nnR5/2 genel ve özel mülkler / yöntemler ile aynı nesnedir. Yani her ikisi de bu modeli takip ediyor
Rafael Rocha

6

Bunu başarmanın birkaç yolu vardır; Ben kullanacağım budur:

function Obj() {
 this.a = 5;
 this.b = this.a + 1;
 // return this; // commented out because this happens automatically
}

var o = new Obj();
o.b; // === 6

2
Bu çalışır, ancak nesne değişmez gösteriminin avantajlarını ortadan kaldırır.
kpozin

Doğru, özür dilerim başlangıçta nesne değişmez etiketi özledim. Çoğunlukla sadece veri yapıları için nesne değişmezleri kullanın ve herhangi bir ek mantık istediğiniz zaman (ki bu bir sınıfa benzeyebilir) ben bu nedenle bu nedenle bir işlev sonucu olarak nesne oluşturun.
ken

6

sadece düşünce uğruna - nesnenin özelliklerini bir zaman çizelgesinin dışına yerleştirin:

var foo = {
    a: function(){return 5}(),
    b: function(){return 6}(),
    c: function(){return this.a + this.b}
}

console.log(foo.c())

yukarıda da daha iyi cevaplar var . Sorguladığınız örnek kodu bu şekilde değiştirdim.

GÜNCELLEME:

var foo = {
    get a(){return 5},
    get b(){return 6},
    get c(){return this.a + this.b}
}
// console.log(foo.c);

2
ES6'da bu genel yaklaşımı çok daha zarif hale getirebilirsiniz: var foo = { get a(){return 5}, get b(){return 6}, get c(){return this.a + this.b} }şimdi şimdi foo.cyerine yapabilirsiniz foo.c():) (Biçimlendirmeyi daha iyi yapmak için cevabınıza yapıştırmaktan çekinmeyin!)

5

Nesnenizde yeni bir işlev oluşturmak ve bir kurucu çağırmak, orijinal problemden radikal bir çıkış gibi görünüyor ve gereksiz.

Nesne hazır bilgisi başlatma sırasında bir kardeş özelliğine başvuramazsınız.

var x = { a: 1, b: 2, c: a + b } // not defined 
var y = { a: 1, b: 2, c: y.a + y.b } // not defined 

Hesaplanan özellikler için en basit çözüm şu şekildedir (yığın yok, fonksiyon yok, kurucu yok):

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

x.c = x.a + x.b; // apply computed property

3

Burada yayınlanan diğer cevaplar daha iyidir, ancak burada bir alternatif var:

  • Başlatma sırasında değeri ayarlar (alıcı, türetilmiş vb. Değil)
  • init()Nesne hazır bilgisi dışında herhangi bir tür veya kod gerektirmez
  • Bir fabrika fonksiyonu veya başka bir nesne oluşturma tamircisi değil, bir nesne değişmezidir.
  • Performans etkisi olmamalıdır (başlatma hariç)

Kendi kendini yürüten anonim işlevler ve pencere saklama

var foo = {
    bar:(function(){
        window.temp = "qwert";
        return window.temp;
    })(),
    baz: window.temp
};

Sipariş garantilidir ( barönce baz).

windowElbette kirletiyor , ancak birisinin window.tempkalıcı olması gereken bir senaryo yazdığını hayal edemiyorum . Belki tempMyAppparanoyaksan.

Aynı zamanda çirkin ama bazen de faydalıdır. Bunun bir örneği, katı başlatma koşullarına sahip bir API kullandığınızda ve yeniden düzenleme gibi hissetmemenizdir, bu nedenle kapsam belirleme doğrudur.

Ve elbette kuru.


3

Tüm bunların anahtarı KAPSAM .

Kendi somutlaştırılmış nesne olarak tanımlamak istediğiniz özelliğin "üst" öğesini (üst nesne) kapsüllemeniz gerekir ve ardından anahtar kelimeyi kullanarak kardeş özelliklerine başvurular yapabilirsiniz this

İlk önce yapmadan başvurursanız , o zaman nesne olacak dış kapsama atıfta bulunacağını hatırlamak çok, çok önemlidir .thisthiswindow

var x = 9   //this is really window.x
var bar = {
  x: 1,
  y: 2,
  foo: new function(){
    this.a = 5, //assign value
    this.b = 6,
    this.c = this.a + this.b;  // 11
  },
  z: this.x   // 9 (not 1 as you might expect, b/c *this* refers `window` object)
};

2
Bu geçerli bir JS bile değil.

2

nesneniz bir nesneyi döndüren bir işlev olarak yazılırsa VE ES6 nesne özniteliği 'yöntemleri' kullanırsanız, bu mümkündür:

const module = (state) => ({
  a: 1,
  oneThing() {
    state.b = state.b + this.a
  },
  anotherThing() {
    this.oneThing();
    state.c = state.b + this.a
  },
});

const store = {b: 10};
const root = module(store);

root.oneThing();
console.log(store);

root.anotherThing();
console.log(store);

console.log(root, Object.keys(root), root.prototype);

2

Alternatif olarak aşağıdaki kodu kullanın ve çalışır. Ve değişken de dizi olabilir. (@ Fausto R.)

var foo = {
  a: 5,
  b: 6,
  c: function() {
    return this.a + this.b;
  },

  d: [10,20,30],
  e: function(x) {
    this.d.push(x);
    return this.d;
  }
};
foo.c(); // 11
foo.e(40); // foo.d = [10,20,30,40]

2

İşte düzgün bir ES6 yolu:

var foo = (o => ({
    ...o,
    c: o.a + o.b
  }))({
    a: 5,
    b: 6
  });
  
console.log(foo);

Ben böyle bir şey yapmak için kullanın:

const constants = Object.freeze(
  (_ => ({
    ..._,
    flag_data: {
      [_.a_flag]: 'foo',
      [_.b_flag]: 'bar',
      [_.c_flag]: 'oof'
    }
  }))({
    a_flag: 5,
    b_flag: 6,
    c_flag: 7,
  })
);

console.log(constants.flag_data[constants.b_flag]);


1

Bu çözüm, dizi içeren iç içe nesnelerle de çalışır

      Object.prototype.assignOwnProVal
     = function (to,from){ 
            function compose(obj,string){ 
                var parts = string.split('.'); 
                var newObj = obj[parts[0]]; 
                if(parts[1]){ 
                    parts.splice(0,1);
                    var newString = parts.join('.'); 
                    return compose(newObj,newString); 
                } 
                return newObj; 
            } 
            this[to] = compose(this,from);
     } 
     var obj = { name : 'Gaurav', temp : 
                  {id : [10,20], city:
                        {street:'Brunswick'}} } 
     obj.assignOwnProVal('street','temp.city.street'); 
     obj.assignOwnProVal('myid','temp.id.1');

0

Tam olarak bu senaryoyu görmediğim için bir seçenek fırlatmak. Eğer varsa yok istediğiniz czaman güncellenen aveya bgüncelleme, daha sonra bir ES6 hayatını iyi çalışır.

var foo = ((a,b) => ({
    a,
    b,
    c: a + b
}))(a,b);

Benim ihtiyaçları için, ben bir döngüde kullanılan sona erecek bir dizi ile ilgili bir nesne var, bu yüzden sadece bir kez bazı ortak kurulum hesaplamak istiyorum, bu yüzden ne var:

  let processingState = ((indexOfSelectedTier) => ({
      selectedTier,
      indexOfSelectedTier,
      hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
                             .some(t => pendingSelectedFiltersState[t.name]),
  }))(tiers.indexOf(selectedTier));

Ben bir özellik ayarlamanız indexOfSelectedTiergerektiğinden ve hasUpperTierSelectionözelliği ayarlarken bu değeri kullanmam gerektiğinden , önce bu değeri hesaplayıp IIFE'ye bir param olarak iletiyorum


0

Diğer yaklaşım, nesneyi özellikleri atamadan önce ilk olarak bildirmek olacaktır:

const foo = {};
foo.a = 5;
foo.b = 6;
foo.c = foo.a + foo.b;  // Does work
foo.getSum = () => foo.a + foo.b + foo.c;  // foo.getSum() === 22

Bununla, önceden atanmış değerlere erişmek için nesne değişkeni adını kullanabilirsiniz.
config.jsDosya için en iyisi .


Bu bir öz referans değil foo, söz konusu nesneyi gösteren beyan edilen değişkene bir referanstır .
Derek Henderson

0
var x = {
    a: (window.secreta = 5),
    b: (window.secretb = 6),
    c: window.secreta + window.secretb
};

Bu, @ slicedtoad'ın cevabı ile neredeyse aynıdır, ancak bir işlev kullanmaz.


-1

Not: Bu çözüm, Typcript kullanır (gerekirse TS'nin derlediği vanilya JS'yi kullanabilirsiniz)

class asd {
    def = new class {
        ads= 'asd';
        qwe= this.ads + '123';
    };

    // this method is just to check/test this solution 
    check(){
        console.log(this.def.qwe);
    }
}

// these two lines are just to check
let instance = new asd();
instance.check();

İstediğimiz iç içe nesne değişmez arabirimini elde etmek için sınıf ifadeleri kullanıyorduk. Bu, IMHO'nun oluşturma sırasında bir nesnenin özelliklerine başvurabilmesi için en iyi şeydir.

Dikkat edilmesi gereken en önemli şey, bu çözümü kullanırken, bir nesne hazır bilgisinden aldığınız arayüzle tamamen aynıdır. Sözdizimi, bir nesne değişmezinin kendisine oldukça yakındır (işlev kullanma, vs kullanma gibi).

Aşağıdakileri karşılaştırın

Önerdiğim çözüm

class asd {
    def = new class {
        ads= 'asd';
        qwe= this.ads + '123';
    };

Nesne hazır bilgileri yeterli olsaydı çözüm

var asd = {
    def : {
        ads:'asd',
        qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
    }
}

Başka bir örnek

Burada bu sınıfta, bir nesne değişmezi ile mümkün olmayan çoklu göreli yolu kendi aralarında birleştirebilirsiniz.

class CONSTANT {
    static readonly PATH = new class {
        /** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
         *
         */
        private readonly RELATIVE = new class {
            readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
            readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
            readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
            readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
            readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
            readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
        };
    }
}

2
Cevabınız tamamen alakasız olduğu için olabilir mi? Ben downvoters açıklamak gerektiğini kabul ediyorum, ama cevabın net soruyla hiçbir ilgisi yoktur…
Manngo

@Manngo işaret ettiğin için teşekkürler. Dürüst olmak gerekirse, OP ile aynı soruyu soruyorum ve önerdiğim çözümü kullanıyorum. Emin, neden alakasız olduğu düşünülüyor. Eğer vaktiniz varsa, cevabı daha iyi yapabilmem veya en azından nerede olduğumu bilmem için lütfen açıklayınız. Ne yazık ki, bunun neden makul bir çözüm olmadığını anlamıyorum.
Dheeraj Bhaskar

-2

Yerel JS kullanmak istiyorsanız, diğer yanıtlar iyi çözümler sunar.

Ancak aşağıdaki gibi kendinden referanslı nesneler yazmaya istekli iseniz:

{ 
  a: ...,
  b: "${this.a + this.a}",
}

Ben sözdizimini destekleyen ve yerel bir nesne döndüren self-reference-object adlı bir npm kütüphanesi yazdım .


1
Lütfen yalnızca bağlantı yanıtlarından kaçının . "Harici bir siteye link ancak daha fazla” olan Cevapları silinebilir .
Quentin

@Quentin Cevabımı nasıl geliştirebileceğim konusunda herhangi bir öneriniz var mı? Bu sorunun diğer yanıtları, yerel javascript'te kendinden referanslı nesneleri nasıl yazabileceğinizi kapsar, ancak kendinden referanslı nesneleri, posterlerin orijinal sorusundaki sözdizimine benzer bir sözdizimiyle yazmak istiyorsanız, Bir çözüm arayan başkaları için yararlı olabileceğini yazdım. Biraz geri bildirim almaktan mutluluk duyuyorum.
alex-e-leon

Burada iyileştirilecek birkaç şey var. İlk olarak ve en açık şekilde, arka keneler olmadan şablon değişmez sözdizimini kullanıyorsunuz. Kişisel btesisin değeri olmalıdır: ${this.a + this.a}. İkincisi, ancak daha az önemlisi, bir şey kullanarak bir dize değil, bir sayı döndürmek istersiniz parseInt. Son ve en önemlisi, bu örneği denediğimde, OP'nin istediği aynı sebepten, işe yaramaz. thisKendi nesne beyanı kullanıldığında döner tanımsız. @ alex-e-leon
Alec Donald Mather

@AlecDonaldMather - Bir göz atmak ve geri bildirimde bulunmak için zaman ayırdığınız için teşekkür ederiz! Projeyle ilgileniyorsanız, bu tartışmayı github'a taşımak daha iyi olabilir, ancak geri bildirimlerinizden bazılarını yanıtlamak daha iyi olabilir: - Geri uçları kullanma: Önceki yorumlarda belirtildiği gibi, bu sözdizimi JS tarafından desteklenmez ve bunun yerine dize kullanılır js, obj tanımlanmadan önce "this" i çözmeye çalışmaktan kaçınmak için burada gereklidir; bir sayı döndürmek, a + b zaten sayılarsa bu işe yaramalıdır, çünkü a + b hem a hem de b ise bir sayı döndürür zaten sayılar.
alex-e-leon

Bu geri dönen tanımsız, kütüphaneyi nasıl kullanmaya çalıştığınızı açıklayabilir misiniz? Bu olmamalı, ama belki de dışarıda bıraktığım bir uç dava var mı? Bununla birlikte, bu kütüphane sorunu tamamen çözmüyor ve kendi ödünleri var, ancak geliştirmeme / kullanmama yardım etmekle ilgileniyorsanız bana bildirin!
alex-e-leon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.