Referensi-sendiri dalam literal objek / inisialisasi

705

Apakah ada cara untuk mendapatkan sesuatu seperti berikut ini berfungsi di JavaScript?

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

Dalam bentuk saat ini, kode ini jelas melempar kesalahan referensi karena thistidak merujuk foo. Tetapi apakah ada cara untuk memiliki nilai dalam properti literal objek tergantung pada properti lain yang dinyatakan sebelumnya?

kpozin
sumber

Jawaban:

744

Ya, satu-satunya hal yang bisa saya ceritakan adalah pengambil :

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

console.log(foo.c) // 11

Ini adalah ekstensi sintaksis yang diperkenalkan oleh Spesifikasi ECMAScript Edisi 5, sintaksinya didukung oleh sebagian besar browser modern (termasuk IE9).

CMS
sumber
32
Jawaban yang sangat membantu. Info lebih lanjut tentang 'dapatkan' dapat ditemukan di sini: developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/…
jake
5
@ FaustoR. Ya itu.
Charlie Martin
48
Hati-hati dengan solusi ini jika nilai foo.aatau foo.bdiubah maka nilai foo.csinkronisasi juga akan berubah. Ini mungkin atau mungkin tidak apa yang diperlukan.
HBP
8
Perhatikan bahwa thismengikat ke objek bersarang terdalam. Misalnya:... x: { get c () { /*this is x, not foo*/ } } ...
Z. Khullah
3
Untuk melengkapi pernyataan saya di atas, karena foobeeing dinyatakan sebagai variabel dan chanya akan dievaluasi pada saat itu dipanggil, menggunakan foodi dalam cakan bekerja, sebagai lawan this(hati-hati meskipun)
Z. Khullah
316

Anda dapat melakukan sesuatu seperti:

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

Ini akan menjadi semacam inisialisasi satu kali objek.

Perhatikan bahwa Anda benar-benar menetapkan nilai kembali dari init()ke foo, karena itu Anda harus return this.

Felix Kling
sumber
95
Anda juga bisa delete this.initsebelum return thissehingga footidak terpolusi
Billy Moon
15
@BillyMoon: Ya memang, meskipun demikian berdampak pada kinerja semua akses properti selanjutnya pada objek itu, pada banyak mesin (V8, misalnya).
TJ Crowder
8
@MuhammadUmer: Tidak yakin bagaimana kelas ES6 relevan dengan pertanyaan.
Felix Kling
8
@MuhammadUmer: kelas hanyalah gula sintaksis untuk fungsi konstruktor, sehingga mereka tidak benar-benar memberikan sesuatu yang baru. Either way, fokus utama dari pertanyaan ini adalah objek literal.
Felix Kling
3
@akantoword: Hebat :) karena objek literal adalah ekspresi tunggal, init()panggilan itu langsung ditambahkan literal untuk mempertahankannya menjadi ekspresi tunggal. Tetapi tentu saja Anda dapat memanggil fungsi secara terpisah yang Anda inginkan.
Felix Kling
181

Jawaban yang jelas dan sederhana tidak ada, jadi untuk kelengkapan:

Tetapi apakah ada cara untuk memiliki nilai dalam properti literal objek tergantung pada properti lain yang dinyatakan sebelumnya?

Tidak. Semua solusi di sini menundanya sampai setelah objek dibuat (dengan berbagai cara) dan kemudian menetapkan properti ketiga. Cara paling sederhana adalah dengan melakukan ini:

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

Semua yang lain hanyalah cara tidak langsung untuk melakukan hal yang sama. (Felix's sangat pintar, tetapi membutuhkan membuat dan menghancurkan fungsi sementara, menambah kompleksitas; dan baik meninggalkan properti tambahan pada objek atau [jika Anda deleteproperti itu] berdampak pada kinerja akses properti selanjutnya pada objek itu.)

Jika Anda membutuhkan semuanya dalam satu ekspresi, Anda dapat melakukannya tanpa properti sementara:

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

Atau tentu saja, jika Anda perlu melakukan ini lebih dari sekali:

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

maka di mana Anda perlu menggunakannya:

var foo = buildFoo(5, 6);
TJ Crowder
sumber
Untuk kewarasan saya sendiri, saya mencoba untuk menemukan beberapa dokumentasi resmi yang pada dasarnya mengatakan hal yang sama - bahwa suatu objek thishanya tersedia untuk metode objek tersebut, dan tidak ada jenis properti lainnya. Ada ide di mana saya bisa menemukan itu? Terima kasih!
David Kennell
1
@ Davidvidenn: Tidak mendapatkan lebih resmi daripada spesifikasi . :-) Anda mungkin akan mulai di sini dan ikuti terus. Ini bahasa yang cukup aneh, tetapi pada dasarnya Anda akan melihat di berbagai subclauses Penilaian Definisi Properti bahwa objek tidak tersedia untuk operasi yang menentukan nilai-nilai dari inisialisasi properti.
TJ Crowder
Saya tidak bisa melihat hasil browserscope di sini , tetapi ini tidak ada lagi kan? Di lingkungan saya, v8: delete10% lebih cepat dan tokek: deletehanya 1% lebih lambat.
TheMaster
1
@TheMaster - Ya, saya tidak berpikir BrowserScope benar-benar suatu hal lagi. Sepertinya menghapus tidak seburuk dulu, setidaknya tidak di V8 (Chrome, dll.) Atau SpiderMonkey. Masih lebih lambat, tetapi hanya sedikit, dan hal-hal ini sangat cepat akhir-akhir ini.
TJ Crowder
63

Cukup instantiate fungsi anonim:

var foo = new function () {
    this.a = 5;
    this.b = 6;
    this.c = this.a + this.b;
};
zzzzBov
sumber
1
@Bergi, mengapa? Karena seseorang mungkin membuat instantiate objek lain yang sama darinya? Ini tidak seperti mereka tidak bisa hanya mengkloning objek literal. Ini tidak berbeda dengan memberikan argumen seperti new Point(x, y)kecuali bahwa fungsi tersebut tidak dinamai untuk digunakan kembali.
zzzzBov
1
@zzzzBov: Tentu saja mereka hanya dapat mengkloning objek, tetapi dibandingkan dengan solusi IEFE (seperti dalam jawaban TJCrowder) solusi Anda bocor fungsi konstruktor dan membuat objek prototipe yang berlebihan.
Bergi
5
@zzzzBov: Cukup gunakan var foo = function() { this.…; return this; }.call({});yang secara sintaksis tidak jauh berbeda tetapi secara waras waras.
Bergi
1
@Bergi, jika Anda merasa itu penting, mengapa tidak menambahkan jawaban Anda sendiri ke dalam campuran?
zzzzBov
3
Anda punya ini. Saya memang tidak memperhatikan newkata kunci.
Randy
26

Sekarang di ES6 Anda dapat membuat properti cache malas. Pada penggunaan pertama properti mengevaluasi sekali untuk menjadi properti statis normal. Hasil: Kedua kalinya overhead fungsi matematika dilewati.

Keajaiban ada di pengambil.

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

Pada pengambil panah thismengambil lingkup leksikal sekitarnya .

foo     // {a: 5, b: 6}
foo.c   // 11
foo     // {a: 5, b: 6 , c: 11}  
voscausa
sumber
1
ES5 juga memiliki properti yang hanya perlu Anda gunakan Object.defineProperty(foo, 'c', {get:function() {...}})untuk mendefinisikannya. Ini mudah dilakukan dengan cara yang tidak mencolok di pabrik seperti ini. Tentu saja jika Anda dapat menggunakan getgula itu lebih mudah dibaca tetapi kemampuannya sudah ada.
Aluan Haddad
21

Beberapa penutupan harus berurusan dengan ini;

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

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

Semua variabel yang dideklarasikan di dalamnya fooadalah milik pribadi foo, seperti yang Anda harapkan dengan deklarasi fungsi apa pun dan karena semuanya ada dalam ruang lingkup, semuanya memiliki akses satu sama lain tanpa perlu merujuk kethis , sama seperti yang Anda harapkan dengan suatu fungsi. Perbedaannya adalah bahwa fungsi ini mengembalikan objek yang memperlihatkan variabel pribadi dan menetapkan objek itu foo. Pada akhirnya, Anda mengembalikan hanya antarmuka yang ingin Anda tampilkan sebagai objek dengan return {}pernyataan.

Fungsi ini kemudian dieksekusi di akhir dengan ()yang menyebabkan seluruh objek foo dievaluasi, semua variabel dalam instantiated dan objek kembali ditambahkan sebagai properti foo().

Henry Wrightson
sumber
14
Sangat membingungkan dan menyesatkan untuk menyebut ini "penutupan". Meskipun pendapat berbeda tentang makna yang tepat mengembalikan nilai ojbect dari suatu fungsi tidak merupakan penutupan dalam buku siapa pun.
16

Anda bisa melakukannya seperti ini

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

Metode itu telah terbukti bermanfaat bagi saya ketika saya harus merujuk ke objek yang awalnya dideklarasikan fungsi. Berikut ini adalah contoh minimal bagaimana saya menggunakannya:

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

Dengan mendefinisikan diri sebagai objek yang berisi fungsi cetak Anda mengizinkan fungsi untuk merujuk ke objek itu. Ini berarti Anda tidak perlu 'mengikat' fungsi cetak ke objek jika Anda harus meneruskannya di tempat lain.

Jika Anda mau, gunakan thisseperti yang diilustrasikan di bawah ini

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

Kemudian kode berikut akan mencatat 0, 1, 2 dan kemudian memberikan kesalahan

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!

Dengan menggunakan metode mandiri Anda menjamin bahwa pencetakan akan selalu mengembalikan objek yang sama terlepas dari konteks di mana fungsi dijalankan. Kode di atas akan berjalan dengan baik dan log 0, 1, 2 dan 3 saat menggunakan versi self createMyObject().

davedambonite
sumber
3
Contoh yang bagus, kecuali Anda telah meninggalkan semua titik koma.
1
Tanpa titik koma - Tidak apa - apa Sungguh!
Kerem Baydoğan
9

Untuk penyelesaiannya, di ES6 kami memiliki kelas (didukung pada saat penulisan ini hanya oleh browser terbaru, tetapi tersedia dalam Babel, TypeScript dan transpiler lainnya)

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

const foo = new Foo();
Monzonj
sumber
7

Anda dapat melakukannya menggunakan pola modul. Seperti:

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

Dengan pola ini Anda dapat instantiate beberapa objek foo sesuai dengan kebutuhan Anda.

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

Rafael Rocha
sumber
2
Ini bukan contoh dari pola modul, hanya sebuah fungsi. Jika baris terakhir dari definisi foo adalah }();, itu akan mengeksekusi sendiri dan mengembalikan objek, bukan fungsi. Juga, foo.cadalah suatu fungsi, jadi menulis kepadanya itu berfungsi dan doa berikutnya fooObject.c()akan gagal. Mungkin biola ini lebih dekat dengan apa yang Anda tuju (itu juga singleton, tidak dirancang untuk dipakai instantiated).
Hollister
2
"Pola Modul awalnya didefinisikan sebagai cara untuk menyediakan enkapsulasi pribadi dan publik untuk kelas dalam rekayasa perangkat lunak konvensional". Dari: Mempelajari Pola Desain JavaScript . Objek itu mengikuti pola modul yang dijelaskan di atas, tetapi mungkin bukan yang terbaik untuk menjelaskannya karena tidak menunjukkan properti / metode publik dan pribadi. Ini jsfiddle.net/9nnR5/2 adalah objek yang sama dengan properti / metode publik dan pribadi. Jadi keduanya mengikuti pola ini
Rafael Rocha
6

Ada beberapa cara untuk mencapai ini; inilah yang akan saya gunakan:

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
ken
sumber
2
Ini berfungsi, tetapi menghilangkan keuntungan dari notasi objek secara literal.
kpozin
Benar, maaf saya melewatkan tag objek-literal awalnya. Saya kebanyakan hanya menggunakan objek literal untuk struktur data, dan kapan saja saya ingin logika tambahan (yang mungkin menyerupai kelas) saya membuat objek sebagai hasil dari fungsi karena alasan ini.
ken
6

hanya demi pemikiran - letakkan properti objek di luar garis waktu:

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

console.log(foo.c())

ada jawaban yang lebih baik di atas juga . Ini adalah bagaimana saya mengubah kode contoh yang Anda tanyakan.

MEMPERBARUI:

var foo = {
    get a(){return 5},
    get b(){return 6},
    get c(){return this.a + this.b}
}
// console.log(foo.c);
animaacija
sumber
2
Di ES6 Anda dapat membuat pendekatan umum ini jauh lebih elegan: var foo = { get a(){return 5}, get b(){return 6}, get c(){return this.a + this.b} }jadi sekarang Anda bisa melakukan foo.calih - alih foo.c():) (Jangan ragu untuk menempelkannya ke dalam jawaban Anda sehingga pemformatan lebih baik!)
5

Menciptakan fungsi baru pada objek Anda secara literal dan menggunakan konstruktor tampaknya merupakan perubahan radikal dari masalah awal, dan itu tidak perlu.

Anda tidak bisa merujuk properti saudara selama inisialisasi objek literal.

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

Solusi paling sederhana untuk properti yang dihitung mengikuti (tanpa tumpukan, tanpa fungsi, tanpa konstruktor):

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

x.c = x.a + x.b; // apply computed property
Rick O'Shea
sumber
3

Jawaban lain yang diposting di sini lebih baik tetapi inilah alternatifnya:

  • Menetapkan nilai saat inisialisasi (bukan pengambil, atau diturunkan, dll)
  • Tidak memerlukan jenis init()atau kode apa pun di luar objek literal
  • Merupakan objek literal dan bukan fungsi pabrik atau mekanik pembuatan objek lainnya.
  • Seharusnya tidak memiliki dampak kinerja (kecuali pada inisialisasi)

Fungsi anonim yang dijalankan sendiri dan penyimpanan jendela

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

Pesanan dijamin ( barsebelum baz).

Tentu windowsaja itu mencemari , tetapi saya tidak bisa membayangkan seseorang menulis naskah yang window.tempharus gigih. Mungkin tempMyAppjika Anda paranoid.

Ini juga jelek tapi kadang berguna. Contohnya adalah ketika Anda menggunakan API dengan kondisi inisialisasi yang kaku dan tidak merasa ingin refactoring sehingga pelingkupannya benar.

Dan itu kering, tentu saja.

DanielST
sumber
3

Kunci dari semua ini adalah RUANG LINGKUP .

Anda perlu merangkum "parent" (objek induk) dari properti yang ingin Anda tetapkan sebagai objek instantiated sendiri, dan kemudian Anda bisa membuat referensi ke properti saudara menggunakan kata kunci this

Sangat, sangat penting untuk diingat bahwa jika Anda merujuk thistanpa terlebih dahulu melakukannya, maka thisakan merujuk pada lingkup luar ... yang akan menjadi windowobjek.

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)
};
Komunitas
sumber
2
Ini bahkan bukan JS yang valid.
2

jika objek Anda ditulis sebagai fungsi yang mengembalikan objek, DAN Anda menggunakan ES6 objek-atribut 'metode', maka itu mungkin:

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);
daviestar
sumber
2

Saya menggunakan kode berikut sebagai alternatif, dan berfungsi. Dan variabel dapat berupa array juga. (@ 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]
Indiana
sumber
2

Inilah cara ES6 yang rapi:

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

Saya menggunakannya untuk melakukan sesuatu seperti ini:

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]);

Ambil
sumber
1

Bagaimana dengan solusi ini ini akan bekerja dengan objek bersarang dengan array juga

      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');
Gaurav
sumber
0

Melempar opsi karena saya tidak melihat skenario persis ini tertutup. Jika Anda tidak ingin cmemperbarui kapan aatau bmemperbarui, maka ES6 IIFE berfungsi dengan baik.

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

Untuk kebutuhan saya, saya memiliki objek yang berhubungan dengan array yang akhirnya akan digunakan dalam satu lingkaran, jadi saya hanya ingin menghitung beberapa pengaturan umum sekali, jadi inilah yang saya miliki:

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

Karena saya perlu mengatur properti untuk indexOfSelectedTierdan saya perlu menggunakan nilai itu ketika mengatur hasUpperTierSelectionproperti, saya menghitung nilai itu terlebih dahulu dan meneruskannya sebagai param ke IIFE

Snekse
sumber
0

Pendekatan lain adalah dengan mendeklarasikan objek terlebih dahulu sebelum menetapkan properti ke dalamnya:

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

Dengan itu, Anda bisa menggunakan nama variabel objek untuk mengakses nilai yang sudah ditetapkan.
Terbaik untuk config.jsfile.

5ervant
sumber
Itu bukan referensi diri, melainkan referensi ke variabel fooyang dideklarasikan yang menunjuk ke objek yang dimaksud.
Derek Henderson
0
var x = {
    a: (window.secreta = 5),
    b: (window.secretb = 6),
    c: window.secreta + window.secretb
};

Ini hampir identik dengan jawaban @ slicedtoad, tetapi tidak menggunakan fungsi.

David Newberry
sumber
-1

Catatan: Solusi ini menggunakan Typescript (Anda dapat menggunakan vanilla JS yang dikompilasi oleh TS jika diperlukan)

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();

Di sini kami menggunakan ekspresi kelas untuk mendapatkan antarmuka literal objek bersarang yang kami inginkan. Ini adalah hal terbaik IMHO berikutnya untuk dapat mereferensikan properti suatu objek selama pembuatan.

Hal utama yang perlu diperhatikan adalah saat menggunakan solusi ini, Anda memiliki antarmuka yang sama persis seperti yang Anda miliki dari objek literal. Dan sintaksnya cukup dekat dengan objek literal itu sendiri (vs menggunakan fungsi, dll).

Bandingkan yang berikut ini

Solusi yang saya usulkan

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

Solusi jika objek literal sudah mencukupi

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

Contoh lain

Di sini di kelas ini, Anda dapat menggabungkan beberapa jalur relatif di antara mereka sendiri, yang tidak mungkin dengan objek literal.

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';
        };
    }
}
Dheeraj Bhaskar
sumber
2
Mungkinkah itu karena jawaban Anda sama sekali tidak relevan? Saya setuju bahwa downvoters harus menjelaskan, tetapi jawaban Anda jelas tidak ada hubungannya dengan pertanyaan ...
Manngo
@Manngo terima kasih telah menunjukkannya. Jujur, saya akan pertanyaan yang sama seperti OP dan saya menggunakan solusi yang saya sarankan. Tidak yakin, mengapa itu dianggap tidak relevan. Jika Anda punya waktu, tolong jelaskan agar saya dapat membuat jawabannya lebih baik atau setidaknya tahu di mana saya salah. Sayangnya, saya tidak mengerti mengapa ini bukan solusi yang masuk akal.
Dheeraj Bhaskar
-2

Jika Anda ingin menggunakan JS asli, jawaban lain memberikan solusi yang baik.

Tetapi jika Anda bersedia menulis objek referensi diri seperti:

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

Saya menulis perpustakaan npm bernama self-referenced-object yang mendukung sintaks itu dan mengembalikan objek asli.

alex-e-leon
sumber
1
Harap hindari hanya tautan jawaban . Jawaban yang "tidak lebih dari tautan ke situs eksternal" dapat dihapus .
Quentin
@ Quentin, apakah Anda memiliki saran tentang bagaimana saya dapat meningkatkan jawaban saya? Jawaban lain untuk pertanyaan ini mencakup bagaimana Anda mungkin dapat menulis objek referensi diri dalam javascript asli, tetapi jika Anda ingin menulis objek referensi diri dengan sintaksis yang mirip dengan sintaksis di poster pertanyaan asli, saya pikir perpustakaan itu yang Saya menulis semoga bermanfaat bagi orang lain mencari solusi. Senang mendapatkan umpan balik.
alex-e-leon
Beberapa hal untuk ditingkatkan di sini. Pertama, dan yang paling jelas, Anda menggunakan sintaks literal template tanpa tanda centang. Anda bnilai properti harus: ${this.a + this.a}. Kedua, tetapi yang kurang penting, Anda ingin mengembalikan nomor, bukan string dengan menggunakan sesuatu seperti parseInt. Terakhir dan PALING penting, ketika saya mencoba contoh ini tidak berfungsi, untuk alasan yang sama OP bertanya. Pengembalian thistidak terdefinisi saat menggunakan objek deklarasi sendiri. @ alex-e-leon
Alec Donald Mather
@AlecDonaldMather - terima kasih telah meluangkan waktu untuk melihatnya dan memberikan umpan balik! Jika Anda tertarik dengan proyek ini, mungkin lebih baik untuk memindahkan diskusi ini ke github, tetapi untuk menjawab beberapa umpan balik Anda: - Menggunakan backticks: Seperti disebutkan dalam komentar sebelumnya, sintaks ini tidak didukung oleh JS, dan menggunakan string sebagai gantinya dari backticks diperlukan di sini untuk menghindari js mencoba menyelesaikan "ini" sebelum obj telah didefinisikan - mengembalikan angka, ini harus bekerja jika a + b sudah angka, karena a + b akan mengembalikan angka jika a dan b adalah sudah angka.
alex-e-leon
Apakah ini kembali tidak terdefinisi, dapatkah Anda menjelaskan bagaimana Anda mencoba menggunakan perpustakaan? Ini seharusnya tidak terjadi, tapi mungkin ada kasus tepi yang saya tinggalkan? Yang mengatakan, perpustakaan ini tidak menyelesaikan masalah sepenuhnya, dan memiliki serangkaian pengorbanan sendiri, tetapi jika Anda tertarik untuk membantu saya meningkatkannya / menggunakannya, beri tahu saya!
alex-e-leon