แปลงสตริงเป็นชื่อตัวแปรใน JavaScript


260

ฉันค้นหาวิธีแก้ไขปัญหา แต่ไม่พบสิ่งใดที่ทำงานได้

onlyVideoฉันมีตัวแปรที่เรียกว่า

"onlyVideo"สตริงจะถูกส่งผ่านไปยังฟังก์ชัน ฉันต้องการตั้งค่าตัวแปรonlyVideoภายในฟังก์ชั่นเป็นบางสิ่ง ฉันจะทำสิ่งนั้นได้อย่างไร

(มีตัวแปรหลายตัวที่สามารถเรียกใช้ในฟังก์ชั่นได้ดังนั้นฉันต้องการให้มันทำงานแบบไดนามิกไม่ใช่ifคำสั่งที่เข้ารหัสยาก)

แก้ไข: อาจเป็นวิธีที่ดีกว่าในการทำสิ่งที่คุณพยายามจะทำ ฉันถามสิ่งนี้ก่อนในการผจญภัย JavaScript ของฉัน ตรวจสอบว่า JavaScript ทำงานอย่างไร

คำแนะนำง่ายๆ:

// create JavaScript object
var obj = { "key1": 1 };

// assign - set "key2" to 2
obj.key2 = 2;

// read values
obj.key1 === 1;
obj.key2 === 2;

// read values with a string, same result as above
// but works with special characters and spaces
// and of course variables
obj["key1"] === 1;
obj["key2"] === 2;

// read with a variable
var key1Str = "key1";
obj[key1Str] === 1;

5
คุณใช้สิ่งนี้เพื่ออะไร คุณแน่ใจหรือไม่ว่าคุณต้องตั้งค่าให้เป็นตัวแปรภายในเครื่องและ Object (Hash) จะไม่ทำงาน
Dogbert

mmm ... ฉันยังไม่เข้าใจเลยว่าทำไมคุณถึงอยากทำสิ่งนี้ในโลกที่มีอาร์เรย์ อย่างไรก็ตามรหัสและคำอธิบายของคุณจะช่วยได้มาก
เควินชาเวซ

ฉันคิดว่าเราต้องการรายละเอียดเพิ่มเติมเกี่ยวกับเป้าหมายสูงสุดของคุณคือ
mcgrailm

คำตอบ:


280

หากเป็นตัวแปรทั่วโลกwindow[variableName] หรือในกรณีของคุณwindow["onlyVideo"]ควรทำเคล็ดลับ


35
แม้ว่าจะไม่ใช่ทั่วโลกคุณสามารถเข้าถึงได้เช่นนั้นโดยscope[property]หรือแม้กระทั่งthis[property]
วอยเบดนาร์สกี้

7
@WojciechBednarski: อย่าสับสนขอบเขตและบริบท thisคือบริบทสิ่งที่ชี้ไปขึ้นอยู่กับวิธีเรียกใช้ฟังก์ชัน ใน JS 50% ของเวลาthisนั้นwindowยกเว้นว่าคุณเปิดใช้งานโหมดเข้มงวดและthisกลายเป็นundefinedและจะเกิดข้อผิดพลาด ขอบเขตเป็นสิ่งที่แตกต่างอย่างสิ้นเชิงและก็ไม่ได้วัตถุ (ยกเว้นขอบเขตทั่วโลกซึ่งจะสะท้อนจากwindowวัตถุ)
slebetman

3
ไม่ทำงานWebWorkers(ซึ่งหมายselfถึงขอบเขตทั่วโลกเช่นเดียวกับในเบราว์เซอร์โดยที่เท่ากับwindow) และ Node.js ซึ่งglobalเป็นตัวแปรที่คุณต้องการ และมันยังใหม่กว่าทำงานได้กับขอบเขตในพื้นที่เช่นตัวฟังก์ชัน
Tomáš Zato - Reinstate Monica

อย่างไรก็ตามมีการกำหนดวิธีconstใช้นี้หรือไม่
toing_toing

165

Javascript มีeval()ฟังก์ชันสำหรับโอกาสดังกล่าว:

function (varString) {
  var myVar = eval(varString);
  // .....
}

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

function SetTo5(varString) {
  var newValue = 5;
  eval(varString + " = " + newValue);
}

หรือถ้าใช้สตริง:

function SetToString(varString) {
  var newValue = "string";
  eval(varString + " = " + "'" + newValue + "'");
}

แต่ฉันคิดว่ามีวิธีที่เหมาะสมกว่าในการบรรลุสิ่งที่คุณกำลังมองหา? ฉันไม่คิดว่า eval () เป็นสิ่งที่คุณต้องการใช้จริงๆเว้นแต่จะมีเหตุผลที่ดี EVAL ()


3
ใช่ฉันจะไปกับเรื่องนี้แล้วค่อนข้างใช้หน้าต่าง (มันมีบางประการ)
Ingo

12
ทำไมeval()คำตอบข้อเดียวถึงถูกลบเพราะถูกลบ
BoltClock

4
@goggin คุณควรทดสอบอาร์กิวเมนต์ใหม่เพื่อให้แน่ใจว่าเป็นชื่อที่ถูกต้อง เพียงแค่ทำการโต้แย้งโดยไม่ตรวจสอบก่อนเป็นสิ่งที่ไม่ปลอดภัยอย่างน่าขัน
Šime Vidas

16
นี่เป็นคำตอบที่สมจริงสำหรับคำถามเท่านั้น เพียงเพราะมันเกี่ยวข้องกับ "eeeeevil" eval ไม่ได้ทำให้มันน้อยลงจริง Javascript ไม่มีตัวแปรตัวแปร (เช่น $$ varname ใน php) ดังนั้นนี่เป็นคำตอบเดียวเท่านั้น การใช้window[varname]มีผลข้างเคียงของการแนะนำตัวแปรทั่วโลกซึ่งอาจไม่ต้องการ @Shaz ฉันไม่คิดว่าคุณให้เครดิตล่าม JS ที่ทันสมัยเพียงพอ พวกมันเร็วมากและการแยกวิเคราะห์และดำเนินการการมอบหมายหนึ่งบรรทัดอย่างง่ายจะไม่ขัดขวางการใช้งาน CPU ของใครก็ตามตราบใดที่มันไม่ได้ถูกทำในตัวจับเวลา 1 มิลลิวินาทีหรือการวนรอบที่แน่น
MooGoo

2
@TheParamagneticCroissant ผู้ที่หลงใหลเกี่ยวกับการดูแลรหัส คนที่เห็นคุณค่าของเวลาและเงินเท่านั้น
Jimbo

41

เท่าที่โซลูชั่น eval vs. global ตัวแปร ...

ฉันคิดว่ามีข้อดีสำหรับแต่ละคน แต่นี่เป็นขั้วคู่ที่ผิดพลาด หากคุณหวาดระแวงกับ namespace ทั่วโลกเพียงแค่สร้าง namespace ชั่วคราวและใช้เทคนิคเดียวกัน

var tempNamespace = {};
var myString = "myVarProperty";

tempNamespace[myString] = 5;

ค่อนข้างแน่ใจว่าคุณสามารถเข้าถึงได้ในฐานะ tempNamespace.myVarProperty (ตอนนี้ 5) หลีกเลี่ยงการใช้หน้าต่างสำหรับการจัดเก็บ (สตริงสามารถใส่ลงในวงเล็บได้โดยตรง)


ปรับเปลี่ยนรหัสของคุณเล็กน้อยเพื่อให้ inline var tempNamespace = {["myVarProperty"] เดียวกัน: "วิดีโอที่แน่นอนเท่านั้น"};
Tioma

1
นี่เป็นวิธีแก้ปัญหาที่ดีมาก - ดูเหมือนว่า eval () จะต้องหลีกเลี่ยงหากจำเป็นจริงๆหลีกเลี่ยงวิธีแก้ปัญหาที่สง่างามมากที่นี่
2560

เริ่มต้นด้วยการรวบรวม document.body.getElementsByTagName ('*') มันเป็นเรื่องง่ายที่จะหาองค์ประกอบทั้งหมดที่มีแอตทริบิวต์ 'id' และสร้างตัวแปรสำหรับค่าวัตถุองค์ประกอบของแต่ละวัตถุในวัตถุทั่วโลก 'id' จากนั้นคุณสามารถอ้างถึง <div id = container> ใน JavaScript เป็น 'id.container' ง่ายมาก!
David Spector

15
var myString = "echoHello";

window[myString] = function() {
    alert("Hello!");
}

echoHello();

บอกว่าไม่มีการชั่วร้าย EVAL ตัวอย่างที่นี่: https://jsfiddle.net/Shaz/WmA8t/


3
ทำให้การทำงานในขอบเขตท้องถิ่นและฉันจะลบ downvote
Tomáš Zato - Reinstate Monica

@ TomášZatofunction aScope() { this[myString] = function() { alert("Hello!"); };};
rrw

@richmondwang thisไม่ได้หมายถึงขอบเขตในตัวเครื่อง แต่ไปยังวัตถุที่ฟังก์ชั่นถูกผูกไว้กับระหว่างการโทร
Tomáš Zato - Reinstate Monica

8

คุณสามารถเข้าถึงวัตถุหน้าต่างเป็นอาเรย์แบบเชื่อมโยงและกำหนดเป็นวิธีนั้นได้

window["onlyVideo"] = "TEST";
document.write(onlyVideo);

8

เมธอด window ['variableName'] ใช้ได้เฉพาะเมื่อตัวแปรถูกกำหนดในขอบเขตส่วนกลาง คำตอบที่ถูกต้องคือ "Refactor" หากคุณสามารถระบุบริบท "วัตถุ" ดังนั้นจึงมีวิธีแก้ปัญหาทั่วไปที่เป็นไปได้ แต่มีตัวแปรบางอย่างที่ไม่มีฟังก์ชั่นระดับโลกที่สามารถแก้ไขได้ตามขอบเขตของตัวแปร

(function(){
    var findMe = 'no way';
})();

6

หากคุณกำลังพยายามเข้าถึงคุณสมบัติของวัตถุคุณจะต้องเริ่มต้นด้วยขอบเขตwindowและผ่านแต่ละคุณสมบัติของวัตถุจนกว่าคุณจะได้รับสิ่งที่คุณต้องการ สมมติว่าa.b.cมีการกำหนดที่อื่นในสคริปต์คุณสามารถใช้ต่อไปนี้:

var values = window;
var str = 'a.b.c'.values.split('.');

for(var i=0; i < str.length; i++)
    values = values[str[i]];

สิ่งนี้จะทำงานเพื่อรับคุณสมบัติของวัตถุใด ๆ ไม่ว่าจะลึกแค่ไหน


ตัวอย่างของคุณเจ๋ง ฉันทราบว่าถ้าฉันใช้nameเป็นชื่อตัวแปรตัวอย่างของคุณจะล้มเหลว แต่ใช้ได้กับชื่อตัวแปรอื่น ๆ สิ่งนี้อาจเกี่ยวข้องกับวัตถุหน้าต่างที่มีnameตัวแปรอยู่แล้ว รวมถึง.valueวิธีการที่ก่อให้เกิดความล้มเหลว ความสามารถในการตีความตัวแปรวัตถุที่ซ้อนกันอย่างลึกซึ้งคือสิ่งที่ฉันกำลังมองหาและวิธีการของคุณบ่งบอกทิศทางที่ดี ขอบคุณ
ธีโอ

ไม่มีปัญหา. คำตอบนั้นยิ่งแสดงให้เห็นถึงแนวคิดมากกว่าจะเป็นคำตอบที่คัดลอก / วาง (เช่นเดียวกับคำตอบส่วนใหญ่ที่นี่ในดังนั้นฉันคิดว่า)

1
ดังนั้นการตอบสนองจะดียิ่งขึ้นเมื่อคุณสามารถใช้เวลาในการปรับปรุงพวกเขามากกว่าแก้ไขพวกเขา ;-)
Theo

ใช้งานไม่ได้:Uncaught TypeError: Cannot read property 'split' of undefined
Roberto 14


0

มันสามารถทำได้เช่นนี้

(function(X, Y) {
  
  // X is the local name of the 'class'
  // Doo is default value if param X is empty
  var X = (typeof X == 'string') ? X: 'Doo';
  var Y = (typeof Y == 'string') ? Y: 'doo';
  
  // this refers to the local X defined above
  this[X] = function(doo) {
    // object variable
    this.doo = doo || 'doo it';
  }
  // prototypal inheritance for methods
  // defined by another
  this[X].prototype[Y] = function() {
    return this.doo || 'doo';
  };
  
  // make X global
  window[X] = this[X];
}('Dooa', 'dooa')); // give the names here

// test
doo = new Dooa('abc');
doo2 = new Dooa('def');
console.log(doo.dooa());
console.log(doo2.dooa());


0

รหัสต่อไปนี้ทำให้ง่ายต่อการอ้างอิงแต่ละ DIV ของคุณและองค์ประกอบ HTML อื่น ๆ ใน JavaScript รหัสนี้ควรรวมไว้ข้างหน้าแท็กเพื่อให้องค์ประกอบ HTML ทั้งหมดเห็น ควรตามด้วยรหัส JavaScript ของคุณ

// For each element with an id (example: 'MyDIV') in the body, create a variable
// for easy reference. An example is below.
var D=document;
var id={}; // All ID elements
var els=document.body.getElementsByTagName('*');
for (var i = 0; i < els.length; i++)
    {
    thisid = els[i].id;
    if (!thisid)
        continue;
    val=D.getElementById(thisid);
    id[thisid]=val;
    }

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