วิธีการใช้ตัวแปรสำหรับคีย์ในวัตถุ JavaScript ตัวอักษร?


406

ทำไมงานต่อไปนี้

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

ในขณะที่สิ่งนี้ไม่ทำงาน:

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

วิธีทำให้ชัดเจนยิ่งขึ้น: ในขณะนี้ฉันไม่สามารถส่งคุณสมบัติ CSS ไปยังฟังก์ชันภาพเคลื่อนไหวเป็นตัวแปรได้



คำตอบ:


667

{ thetop : 10 }เป็นวัตถุที่ถูกต้องตามตัวอักษร รหัสจะสร้างวัตถุที่มีคุณสมบัติชื่อthetopที่มีค่า 10 ทั้งสองอย่างต่อไปนี้จะเหมือนกัน:

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

ใน ES5 และก่อนหน้านี้คุณไม่สามารถใช้ตัวแปรเป็นชื่อคุณสมบัติภายในวัตถุตามตัวอักษร ตัวเลือกเดียวของคุณคือทำสิ่งต่อไปนี้:

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เป็นส่วนหนึ่งของไวยากรณ์สำหรับตัวอักษรวัตถุซึ่งช่วยให้คุณสามารถเขียนรหัสเช่นนี้:

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

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

คุณสามารถใช้ไวยากรณ์ใหม่นี้ในเวอร์ชันล่าสุดของแต่ละเบราว์เซอร์หลัก


ฉันเข้าใจ! ขอบคุณ! Shoudl นี่ยังใช้งานได้กับ eval ไม่ได้หรือ ฉันหมายความว่ามันไม่ทำงานในตัวอย่างของฉันในขณะนี้ แต่ฉันผอมมันควร ... :-)
speendo

3
@Marcel: eval()จะไม่ทำงานภายในวัตถุตามตัวอักษรสำหรับชื่อคุณสมบัติแบบไดนามิกคุณเพียงแค่ได้รับข้อผิดพลาด ไม่เพียงแค่นั้น แต่eval()ไม่ควรใช้กับสิ่งเหล่านี้ มีบทความที่ยอดเยี่ยมเกี่ยวกับการใช้งานที่ถูกต้องและไม่ถูกต้องของeval: blogs.msdn.com/ericlippert/archive/2003/11/01/53329.aspx
Andy E

2
@AndyE พิจารณาอัปเดต "รุ่นล่าสุด" และ "IE IE ปัจจุบัน" ด้วยเวลาที่เฉพาะเจาะจงมากขึ้นเช่น "รุ่นที่ใหม่กว่า XXX" หรือ "หลัง 2014-mm" (ฉันจะทำการเปลี่ยนแปลงด้วยตัวเอง แต่ฉันไม่ทราบว่าค่าใดดี จะเป็น.
Alexei Levenkov

1
สำหรับ ES6 มีวิธีที่จะออกจากสถานที่ให้บริการถ้าคีย์เป็นโมฆะ / ไม่ได้กำหนด? ตัวอย่างเช่นใน{[key] : "value"}ถ้าคีย์เป็นโมฆะมันจะให้{ null: "value"}ในขณะที่ฉันต้องการผลลัพธ์ที่จะเป็น{}
wasabigeek

วิธีแก้ปัญหาที่ยอดเยี่ยม แต่ทำไมคุณรู้มากถึงแม้จะอ่านรายละเอียดทั้งหมดไม่สามารถหาจุด :(
hugemeow

126

ด้วยECMAScript 2015ตอนนี้คุณสามารถทำได้โดยตรงในการประกาศวัตถุด้วยเครื่องหมายวงเล็บ: 

var obj = {
  [key]: value
}

โดยที่keyสามารถเป็นนิพจน์ประเภทใดก็ได้ (เช่นตัวแปร) ที่ส่งคืนค่า

ดังนั้นรหัสของคุณจะมีลักษณะดังนี้:

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

thetopจะทำการประเมินที่ไหนก่อนใช้เป็นกุญแจ


17

ใบเสนอราคา ES5 ที่บอกว่าไม่ควรใช้งาน

หมายเหตุ: กฎมีการเปลี่ยนแปลงสำหรับ ES6: https://stackoverflow.com/a/2274327/895245

ข้อมูลจำเพาะ: http://www.ecma-international.org/ecma-262/5.1/#sec-11.1.5

ชื่อคุณสมบัติ:

  • IdentifierName
  • StringLiteral
  • NumericLiteral

[ ... ]

PropertyName การผลิต: IdentifierName ถูกประเมินดังนี้:

  1. ส่งคืนค่าสตริงที่มีลำดับของอักขระเหมือนกับ IdentifierName

PropertyName การผลิต: StringLiteral ถูกประเมินดังนี้:

  1. ส่งคืน SV [ค่าสตริง] ของ StringLiteral

PropertyName การผลิต: NumericLiteral ได้รับการประเมินดังนี้:

  1. ให้ nbr เป็นผลลัพธ์ของการสร้างค่าของ NumericLiteral
  2. ส่งคืน ToString (nbr)

ซึ่งหมายความว่า:

  • { theTop : 10 } เหมือนกันทุกประการ { 'theTop' : 10 }

    PropertyName theTopเป็นIdentifierNameดังนั้นจึงได้รับการแปลงเป็นค่าสตริงซึ่งเป็นค่าสตริงของ'theTop''theTop'

  • ไม่สามารถเขียนวัตถุเริ่มต้น (ตัวอักษร) ด้วยปุ่มตัวแปร

    สามตัวเลือกเท่านั้นคือIdentifierName(ขยายเป็นสตริงตัวอักษร) StringLiteralและNumericLiteral(ขยายเป็นสตริงด้วย)


3
Downvoters: ฉันเป็นคนแรกที่พูดมาตรฐานเกี่ยวกับคำถามนี้ ใบเสนอราคา ES6 สำหรับคำตอบที่ถูกแก้ไขหลังจากที่ฉันตอบและมาตรฐานนั้นยังไม่ได้รับการยอมรับในเวลานั้น หากคุณรู้ว่าเพราะเหตุใดฉันถึงได้ลงคะแนนโปรดอธิบายฉันต้องการเรียนรู้ ฉันอาจจะได้รับตราความกดดันจากเพื่อนด้วย ...
Ciro Santilli 法轮功冠状病六四事件法轮功

ฉันเดาว่า downvote ส่วนใหญ่เป็นเพราะคำตอบของคุณไม่ได้มีทางออกและเป็น "ไม่มีประโยชน์" ในเรื่องนั้น การลงคะแนนต่อแรงกดดันจากเพื่อน :-)
Bergi

3
@Bergi ขอบคุณที่มีความกล้าหาญ! :-) แต่ฉันคิดว่าฉันได้ตอบคำถามโดยตรง : Q: "ทำไมงานต่อไปนี้ถึงทำงานได้?" ตอบ: เพราะ ES5 บอกเช่นนั้น "จะทำอย่างไรกับเรื่องนี้?" เป็นนัย คุณลดลงคำถามยอดนิยมสำหรับการพูดว่า "มันเป็นไปไม่ได้" โดยไม่ต้องพูดมาตรฐานก่อนที่จะมีคนแก้ไขในการแก้ปัญหา ES6?
Ciro Santilli 郝海东冠状病六四事件法轮功

อ่าใช่มั้ย ฉันมักจะอ้างอิงคำถามเฉพาะในบล็อกโควตเพื่อให้ชัดเจนเมื่อตอบคำถามโดยตรง การอ้างอิงมาตรฐานสามารถทำให้ได้คำตอบที่ดียิ่งขึ้น แต่ตอนนี้โพสต์ของคุณไม่ได้ตอบคำถามด้วย ระบุสิ่งที่สามารถทำให้สำคัญใน ES5 ไม่ได้หมายความว่าพวกเขาทำงาน แท้จริงthetopเป็นIdentifierNameดังนั้นทำไมมันไม่ทำงาน ? คำถามนั้นยังคงเปิดอยู่
Bergi

1
@Bergi ขอบคุณอีกครั้งสำหรับการอธิบายให้ฉัน! ฉันได้ทำการปรับปรุงเพื่อให้ชัดเจนยิ่งขึ้น ฉันไม่ได้ทำมาก่อนเพราะฉันเห็นว่าชัดเจนเพราะเราสามารถเขียน{a:1}.aได้ดังนั้นจึงaไม่ควรขยายค่าตัวแปรในกรณีตัวระบุ แต่ใช่การอธิบายเพิ่มเติมคือการปรับปรุงในกรณีนี้
Ciro Santilli 法轮功冠状病六四事件法轮功

5

ฉันใช้สิ่งต่อไปนี้เพื่อเพิ่มคุณสมบัติที่มีชื่อ "ไดนามิก" ลงในวัตถุ:

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

key เป็นชื่อของคุณสมบัติใหม่

วัตถุของคุณสมบัติที่ส่งผ่านไปanimateจะเป็น{left: 20, width: 100, top: 10}

นี่เป็นเพียงการใช้[]สัญกรณ์ที่จำเป็นตามที่แนะนำโดยคำตอบอื่น ๆ แต่มีรหัสบรรทัดน้อยลง!


5

การเพิ่มวงเล็บเหลี่ยมรอบ ๆ ตัวแปรใช้งานได้ดีสำหรับฉัน ลองสิ่งนี้

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

สิ่งนี้จะไม่ทำงานใน EcmaScript เวอร์ชันเก่า แต่ทุกวันนี้นี่เป็นวิธีที่สะอาดตา
Oliver

3

ฉันไม่พบตัวอย่างง่ายๆเกี่ยวกับความแตกต่างระหว่าง ES6 และ ES5 ดังนั้นฉันจึงสร้างมันขึ้นมา ตัวอย่างโค้ดทั้งคู่สร้างวัตถุเดียวกันทั้งหมด แต่ตัวอย่าง ES5 ยังทำงานในเบราว์เซอร์รุ่นเก่า (เช่น IE11) ซึ่งตัวอย่าง ES6 ใช้ไม่ได้

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

ตัวอย่างที่ซับซ้อนมากขึ้นการใช้วงเล็บและตัวอักษร ... สิ่งที่คุณอาจต้องทำกับ vue / axios ล้อมตัวอักษรไว้ในวงเล็บดังนั้น

[`... `]

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

1

รับรหัส:

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

แปล:

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

ในขณะที่คุณสามารถดูประกาศไม่ได้ทำให้การใช้งานของตัวแปร{ thetop : 10 } thetopแต่จะสร้างวัตถุที่มีชื่อคีย์thetopแทน หากคุณต้องการให้คีย์เป็นค่าของตัวแปรthetopคุณจะต้องใช้วงเล็บเหลี่ยมรอบthetop:

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

ไวยากรณ์ของวงเล็บเหลี่ยมได้รับการแนะนำให้รู้จักกับ ES6 ใน JavaScript เวอร์ชันก่อนหน้าคุณต้องทำสิ่งต่อไปนี้:

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

1

ฉันไม่อยากจะเชื่อว่าสิ่งนี้ยังไม่ได้โพสต์: เพียงใช้สัญลักษณ์ลูกศรพร้อมการประเมินแบบไม่ระบุชื่อ!

ไม่มีการบุกรุกอย่างสมบูรณ์ไม่ยุ่งกับเนมสเปซและใช้เพียงบรรทัดเดียว:

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

การสาธิต:

มีประโยชน์ในสภาพแวดล้อมที่ไม่รองรับสิ่งใหม่ {[myKey]: myValue}ไวยากรณ์เช่น - ชัดเจน ฉันเพิ่งตรวจสอบแล้วบนคอนโซลนักพัฒนาเว็บ - Firefox 72.0.1, เปิดตัว 2020-01-08

(ฉันแน่ใจว่าคุณสามารถสร้างโซลูชันที่มีประสิทธิภาพ / ขยายได้มากขึ้นหรืออะไรก็ตามที่เกี่ยวข้องกับการใช้งานอย่างชาญฉลาดreduceแต่ ณ จุดนั้นคุณอาจได้รับการบริการที่ดีขึ้นโดยการแยกการสร้างวัตถุออกเป็นฟังก์ชันของตัวเอง ทั้งหมดในบรรทัด)


ไม่ว่าเรื่องตั้งแต่ OP ถามนี้สิบปีที่ผ่านมา แต่เพื่อความสมบูรณ์ประโยชน์และเพื่อแสดงให้เห็นถึงวิธีการที่จะว่า ตอบคำถามตามที่ระบุไว้ฉันจะแสดงนี้ในบริบทเดิม:

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

0

ด้วยวิธีนี้คุณสามารถบรรลุผลลัพธ์ที่ต้องการ

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

การติดตั้ง ES5 เพื่อกำหนดคีย์ด้านล่าง:

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

Object.defineProperties(obj, objArgs);

ฉันแนบตัวอย่างที่ฉันใช้ในการแปลงเป็นวัตถุเปล่า

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:

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

หรือแยกไปยังฟังก์ชัน:

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

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


0

คุณสามารถทำได้ด้วยวิธีนี้:

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

0

คุณสามารถลองสิ่งนี้:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.