Değişken bir JavaScript nesnesi anahtarındaki bir anahtar için nasıl kullanılır?


406

Aşağıdakiler neden çalışır?

<something>.stop().animate(
    { 'top' : 10 }, 10
);

Halbuki bu işe yaramıyor:

var thetop = 'top';
<something>.stop().animate(
    { thetop : 10 }, 10
);

Daha da netleştirmek için: Şu anda bir CSS özelliğini bir fonksiyon olarak animate işlevine geçiremiyorum.



Yanıtlar:


667

{ thetop : 10 }geçerli bir nesne değişmezidir. Kod thetop, 10 değerine sahip bir özelliğe sahip bir nesne oluşturur . Aşağıdakilerin ikisi de aynıdır:

obj = { thetop : 10 };
obj = { "thetop" : 10 };

ES5 ve önceki sürümlerde, değişkeni nesne değişmezi içinde özellik adı olarak kullanamazsınız. Tek seçeneğiniz aşağıdakileri yapmaktır:

var thetop = "top";

// create the object literal
var aniArgs = {};

// Assign the variable property name with a value of 10
aniArgs[thetop] = 10; 

// Pass the resulting object to the animate method
<something>.stop().animate(
    aniArgs, 10  
);  

ES6 , ComputedPropertyName öğesini , nesne hazırları için dilbilgisinin bir parçası olarak tanımlar ; bu, kodu şöyle yazmanıza olanak tanır:

var thetop = "top",
    obj = { [thetop]: 10 };

console.log(obj.top); // -> 10

Bu yeni sözdizimini her genel tarayıcının en son sürümlerinde kullanabilirsiniz.


Anlıyorum! Teşekkür ederim! Shoudln bu eval ile de çalışmıyor mu? Yani şu anda benim
örneğimde işe yaramıyor

3
@Marcel: eval()dinamik özellik adları için bir nesne değişmezinin içinde çalışmaz, sadece bir hata alırsınız. Sadece bu değil, aynı eval()zamanda böyle şeyler için de kullanılmamalıdır. Aşağıdakilerin doğru ve yanlış kullanımı hakkında mükemmel bir makale var eval: blogs.msdn.com/ericlippert/archive/2003/11/01/53329.aspx
Andy E

2
@AndyE, "son sürümleri" ve "mevcut IE TP" yi "XXX'dan sonraki sürümler" veya "2014 mm'den sonra" gibi daha spesifik bir süreyle güncellemeyi düşünüyor (kendim değişiklik yapardım, ancak hangi iyi değerlerin olduğunu bilmiyorum olacaktır.
Alexei Levenkov

1
ES6 için, anahtar null / undefined ise mülkü dışarıda bırakmanın bir yolu var mı? Örneğin {[key] : "value"}, eğer anahtar null olsaydı, verirdi { null: "value"}, oysa sonucun olmasını isterdim{}
wasabigeek

harika bir çözüm, ama neden bu kadar çok şey biliyorsun, tüm spesifikasyonu okumak bile puan alamadım :(
hugemeow

126

İle ECMAScript 2015 artık parantez gösterimi ile nesne bildiriminde doğrudan yapabilir: 

var obj = {
  [key]: value
}

Burada keydeğer döndüren herhangi bir ifade türü (örneğin bir değişken) olabilir.

Yani burada kodunuz şöyle görünecektir:

<something>.stop().animate({
  [thetop]: 10
}, 10)

thetopAnahtar olarak kullanılmadan önce nerede değerlendirilecektir.


17

Çalışmaması gerektiğini söyleyen ES5 teklifi

Not: ES6 için kurallar değişti: https://stackoverflow.com/a/2274327/895245

Spec: http://www.ecma-international.org/ecma-262/5.1/#sec-11.1.5

Mülkiyet adı :

  • IdentifierName
  • StringLiteral
  • NumericLiteral

[...]

PropertyName: IdentifierName üretimi şu şekilde değerlendirilir:

  1. IdentifierName ile aynı karakter dizisini içeren String değerini döndürür.

PropertyName: StringLiteral üretimi şu şekilde değerlendirilir:

  1. StringLiteral öğesinin SV [String değeri] değerini döndürün.

PropertyName: NumericLiteral üretimi şu şekilde değerlendirilir:

  1. Nbr, NumericLiteral değerini oluşturmanın sonucu olsun.
  2. Dizeye Dön (nbr).

Bunun anlamı şudur ki:

  • { theTop : 10 } ile tamamen aynı { 'theTop' : 10 }

    PropertyName theTopBir olan IdentifierNamebu dönüştürülmüş olur, böylece 'theTop'dize değeridir dize değeri, 'theTop'.

  • Değişken anahtarlarla nesne başlatıcıları (değişmez değerler) yazmak mümkün değildir.

    Yalnızca üç seçenek IdentifierName(dize değişmezine genişletilir) StringLiteralve NumericLiteral(ayrıca bir dize genişletilir) şeklindedir.


3
Downvoters: Bu soruya herhangi bir standart teklif eden ilk kişi bendim . En üstteki cevaptaki ES6 alıntısı cevap verdikten sonra düzenlendi ve bu standart henüz kabul edilmedi. Neden başka neden aşağı oy aldığımı biliyorsanız, lütfen açıklayın, sadece öğrenmek istiyorum. Ben de akran baskısı rozeti alabilirsiniz ...
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

Sanırım downvote çoğunlukla cevabınız bir çözüm sunmadığı için ve bu konuda "yararlı değil" idi. Akran baskısına doğru oylama :-)
Bergi

3
@Bergi cesaretiniz için teşekkürler! :-) Ama sanırım soruyu doğrudan yanıtladım : S: "Aşağıdakiler neden işe yarıyor?". C: çünkü ES5 öyle diyor. "Bu konuda ne yapmalı?" örtük. ES6 çözümünde birileri düzenlemeden önce standart bir teklif olmadan "imkansız" demenin en önemli sorusunu küçümsediniz mi?
Ciro Santilli 法轮功 5 病 六四 事件 法轮功

Ah doğru. Genellikle bir blok alıntıdaki belirli sorulara doğrudan cevap verdiğimde açıklığa kavuşturmak için atıyorum. Standarttan alıntı yapmak iyi bir yanıtı daha da iyi hale getirebilir, ancak şu anda yayınınız imo sorusuna bile cevap vermiyor. ES5'te neyin anahtar yapabileceğini belirtmek, nasıl çalıştıklarını ima etmez . Elbette thetopbir IdentifierName, neden çalışmıyor ? Bu soru hala açık.
Bergi

1
@ Bergi bana açıkladığınız için tekrar teşekkürler! Daha açık hale getirmek için güncelledim. Daha önce yapmamıştım çünkü açıktı, çünkü yazabiliyoruz {a:1}.a, bu yüzden aaçıkça tanımlayıcı durumundaki değişken değerini genişletmedik. Ancak evet, daha fazla açıklamak bu durumda bir gelişmedir.
Ciro Santilli 法轮功 冠状 at 六四 事件 法轮功

5

Bir nesneye "dinamik" adıyla bir özellik eklemek için aşağıdaki kullandım:

var key = 'top';
$('#myElement').animate(
   (function(o) { o[key]=10; return o;})({left: 20, width: 100}),
   10
);

key yeni mülkün adıdır.

Özelliklerin amacı geçirilen animateolacak{left: 20, width: 100, top: 10}

Bu sadece []diğer cevapların önerdiği şekilde gerekli gösterimi kullanıyor , ancak daha az kod satırı ile!


5

Değişkenin etrafına köşeli parantez eklemek benim için iyi sonuç verir. Bunu dene

var thetop = 'top';
<something>.stop().animate(
    { [thetop] : 10 }, 10
);

Bu, EcmaScript'in eski sürümlerinde çalışmaz, ancak bugünlerde bu çok temiz bir yaklaşımdır.
Oliver

3

Ben bulamadım basit bir örnek ben bir yapılan bu yüzden, ES6 ve ES5 arasındaki farklar hakkında. Her iki kod örneği de tamamen aynı nesneyi oluşturur. Ancak ES5 örneği, ES6 örneğinin çalışmadığı eski tarayıcılarda da (IE11 gibi) çalışır.

ES6

var matrix = {};
var a = 'one';
var b = 'two';
var c = 'three';
var d = 'four';

matrix[a] = {[b]: {[c]: d}};

ES5

var matrix = {};
var a = 'one';
var b = 'two';
var c = 'three';
var d = 'four';

function addObj(obj, key, value) {
  obj[key] = value;
  return obj;
}

matrix[a] = addObj({}, b, addObj({}, c, d));

2

2020 güncelleme / örnek ...

Daha karmaşık bir örnek, parantez ve değişmez değerleri kullanarak ... örneğin vue / axios ile yapmanız gerekebilecek bir şey. Değişmezi parantez içine alın, böylece

[`...`]

{
    [`filter[${query.key}]`]: query.value,  // 'filter[foo]' : 'bar'
}

1

Verilen kod:

var thetop = 'top';
<something>.stop().animate(
    { thetop : 10 }, 10
);

Tercüme:

var thetop = 'top';
var config = { thetop : 10 }; // config.thetop = 10
<something>.stop().animate(config, 10);

Gördüğünüz gibi, { thetop : 10 }bildirim değişkeni kullanmıyor thetop. Bunun yerine adlı bir anahtar içeren bir nesne oluşturur thetop. Anahtarın değişkenin değeri olmasını thetopistiyorsanız, etrafında köşeli parantez kullanmanız gerekir thetop:

var thetop = 'top';
var config = { [thetop] : 10 }; // config.top = 10
<something>.stop().animate(config, 10);

Köşeli parantez sözdizimi ES6 ile tanıtıldı. JavaScript'in önceki sürümlerinde aşağıdakileri yapmanız gerekir:

var thetop = 'top';
var config = (
  obj = {},
  obj['' + thetop] = 10,
  obj
); // config.top = 10
<something>.stop().animate(config, 10);

1

Bunun henüz gönderilmediğine inanamıyorum : anonim değerlendirme ile ok gösterimini kullanın!

Tamamen invaziv olmayan, ad alanıyla uğraşmaz ve sadece bir satır alır:

myNewObj = ((k,v)=>{o={};o[k]=v;return o;})(myKey,myValue);

demo:

{[myKey]: myValue}henüz yeni sözdizimini desteklemeyen ortamlarda kullanışlıdır , örneğin; Web Geliştirici Konsolumda doğruladım: Firefox 72.0.1, 2020-01-08'i yayınladı.

(Eminim bazı daha güçlü / genişletilebilir çözümler veya akıllıca kullanım içeren herhangi bir şey yapabilirsiniz reduce, ancak bu noktada Nesne oluşturma işlemini zorunlu olarak sıkışmak yerine kendi işlevine ayırarak daha iyi hizmet edersiniz. tüm satır içi)


değil OP bu on yıl önce sordu, ancak şeyiyle aşkına ve ne kadar göstermek için yana önemli olduğunu tam olarak , ben orijinal bağlamında bu göstereceğiz belirtildiği gibi sorunun cevabı:

var thetop = 'top';
<something>.stop().animate(
    ((k,v)=>{o={};o[k]=v;return o;})(thetop,10), 10
);

0

Bu şekilde istediğiniz çıktıyı elde edebilirsiniz

var jsonobj={};
var count=0;
$(document).on('click','#btnadd', function() {
    jsonobj[count]=new Array({ "1"  : $("#txtone").val()},{ "2"  : $("#txttwo").val()});
    count++;
    console.clear();
    console.log(jsonobj);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span>value 1</span><input id="txtone" type="text"/>
<span>value 2</span><input id="txttwo" type="text"/>
<button id="btnadd">Add</button>


0

Anahtar atamak için ES5 uygulaması aşağıdadır:

var obj = Object.create(null),
    objArgs = (
      (objArgs = {}),
      (objArgs.someKey = {
        value: 'someValue'
      }), objArgs);

Object.defineProperties(obj, objArgs);

Çıplak nesneye dönüştürmek için kullandığım bir pasaj ekledim.

var obj = {
  'key1': 'value1',
  'key2': 'value2',
  'key3': [
    'value3',
    'value4',
  ],
  'key4': {
    'key5': 'value5'
  }
}

var bareObj = function(obj) {

  var objArgs,
    bareObj = Object.create(null);

  Object.entries(obj).forEach(function([key, value]) {

    var objArgs = (
      (objArgs = {}),
      (objArgs[key] = {
        value: value
      }), objArgs);

    Object.defineProperties(bareObj, objArgs);

  });

  return {
    input: obj,
    output: bareObj
  };

}(obj);

if (!Object.entries) {
  Object.entries = function(obj){
    var arr = [];
    Object.keys(obj).forEach(function(key){
      arr.push([key, obj[key]]);
    });
    return arr;
  }
}

console(bareObj);


0

ES5 için aşağıdakileri yapabilirsiniz:

var theTop = 'top'
<something>.stop().animate(
  JSON.parse('{"' + theTop + '":' + JSON.stringify(10) + '}'), 10
)

Veya bir işleve çıkarın:

function newObj (key, value) {
  return JSON.parse('{"' + key + '":' + JSON.stringify(value) + '}')
}

var theTop = 'top'
<something>.stop().animate(
  newObj(theTop, 10), 10
)


0

Bunu şu şekilde yapabilirsiniz:

var thetop = 'top';
<something>.stop().animate(
    new function() {this[thetop] = 10;}, 10
);

0

Ayrıca şunu da deneyebilirsiniz:

let array1 = [{
    "description": "THURSDAY",
    "count": "1",
    "date": "2019-12-05"
},
{
    "description": "WEDNESDAY",
    "count": "0",
    "date": "2019-12-04"
}]
let res = array1.map((value, index) => {
    return { [value.description]: { count: value.count, date: value.date } }
})
console.log(res);

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.