একটি স্ট্রিংকে টেম্পলেট স্ট্রিংয়ে রূপান্তর করুন


147

সাধারণ স্ট্রিং হিসাবে কোনও টেম্পলেট স্ট্রিং তৈরি করা কি সম্ভব?

let a="b:${b}";

একটি তারপর এটি একটি টেম্পলেট স্ট্রিং রূপান্তর

let b=10;
console.log(a.template());//b:10

ছাড়া eval, new Functionএবং গতিশীল কোড উত্পন্নকরণের অন্যান্য উপায়?


5
আপনি এটি অর্জনের জন্য কোনও উপায় খুঁজে পেয়েছেন? আমার একদিন এটি করার প্রয়োজন হতে পারে এবং আপনি কী এসেছেন তা জানতে আগ্রহী।
ব্রায়ান রায়নার

@ ব্রায়ানরায়ার আপনাকে বলতে দেয় যে আপনার জেএস প্রোগ্রামটি রেস্ট এআইপি থেকে ডেটা আনার চেষ্টা করছে, যার ইউআরএল একটি কনফিগারেশন ফাইলের স্ট্রিং হিসাবে রয়েছে "/ রিসোর্স / <রিসোর্স_আইডি> / আপডেট /" এবং আপনি আপনার প্রোগ্রাম থেকে গতিশীল "রিসোর্স_আইডি" রেখেছেন । যদি না আপনি সেই url কে অংশগুলিতে বিভক্ত করতে এবং বিভিন্ন অঞ্চলে সংরক্ষণ করতে চান তবে আপনার কিছু ধরণের স্ট্রিং টেম্পলেট প্রক্রিয়াজাতকরণ প্রয়োজন।
রিউ_হায়াবুসা


ইভালকে আরও ভাল ব্যবহারের পরিবর্তে ইভালকে ব্যবহার করার পরামর্শ দেওয়া হয় না এটি প্রস্তাবিত নয় এবং অত্যন্ত নিরুৎসাহিত, সুতরাং দয়া করে এটি ডেভেলপার ব্যবহার করবেন না mo موজিলা.আর.ইন.ইউ / ডকস / ওয়েবে / জাভাস্ক্রিপ্ট / রেফারেন্স/…! যাক বি = 10; যাক a = "b: $ {b}"; যাক প্রতিক্রিয়া = a.replace (/ \ $ {\ w +} /, খ); conssole.log (প্রতিক্রিয়া);
বিজয় পালস্কর

উত্তর:


79

আপনার টেম্পলেট স্ট্রিংটি অবশ্যই bপরিবর্তনশীলটির পরিবর্তনশীল হিসাবে (রানটাইম ক্ষেত্রে) পেতে হবে, সুতরাং উত্তরটি হ'ল: না, গতিশীল কোড জেনারেশন ব্যতীত এটি অসম্ভব।

তবে evalএটি সহ বেশ সহজ:

let tpl = eval('`'+a+'`');

7
eval নিরাপত্তাহীন, তাই গতিশীল কোড উত্পন্নকরণের অন্যান্য মাধ্যমগুলি
কলানিক

8
@KOLANICH বিশেষ কেনার ক্ষেত্রে যে - মধ্যে পালাবার ফিরে কোট aস্ট্রিং এবং এটি অনেক কম অনিরাপদ হবে: let tpl = eval('`'+a.replace(/`/g,'\\`')+'`');। আমি মনে করি আরও গুরুত্বপূর্ণ হ'ল evalআপনার কোডটি অপ্টিমাইজ করতে সংকলককে প্রতিরোধ করা। তবে আমি মনে করি এটি এই প্রশ্নের সাথে অপ্রাসঙ্গিক।
অ্যালেক্সপডগুলি

3
প্রকৃতপক্ষে, আপনি টেম্পলেট স্ট্রিংগুলির মধ্যেও ফাংশন পরিচালনা করতে পারেন।
কলানিশ

9
@KOLANICH দুঃখিত আপনি অপছন্দ eval। তবে মনে রাখবেন যে কোনও টেম্পলেট আক্ষরিক নিজেই এর একটি রূপ eval। দুটি উদাহরণ: var পরীক্ষা = Result: ${alert('hello')}; var পরীক্ষা = Result: ${b=4}; উভয়ই স্ক্রিপ্টের প্রসঙ্গে স্বেচ্ছাসেবক কোড কার্যকর করবে। আপনি যদি স্বেচ্ছাচারী স্ট্রিংগুলিকে অনুমতি দিতে চান তবে আপনি পাশাপাশি অনুমতিও দিতে পারেন eval
মানংগো

6
সতর্ক হোন. যেহেতু বাবেলের মতো কিছু
এটিকে স্থানান্তরিত

79

আমার প্রকল্পে আমি ES6 এর সাথে এরকম কিছু তৈরি করেছি:

String.prototype.interpolate = function(params) {
  const names = Object.keys(params);
  const vals = Object.values(params);
  return new Function(...names, `return \`${this}\`;`)(...vals);
}

const template = 'Example text: ${text}';
const result = template.interpolate({
  text: 'Foo Boo'
});
console.log(result);

আপডেট আমি লড্যাশ নির্ভরতা অপসারণ করেছি, কী এবং মান পেতে ES6 এর সমতুল্য পদ্ধতি রয়েছে।


1
হাই, আপনার সমাধানটি দুর্দান্ত কাজ করে, তবে আমি যখন এটি রিএ্যাক্ট নেটিভ (বিল্ড মোড) এ ব্যবহার করি তখন এটি একটি ত্রুটি ফেলে দেয়: অবৈধ অক্ষর '`' , যদিও এটি যখন আমি ডিবাগ মোডে চলি তখন এটি কাজ করে। দেখে মনে হচ্ছে, বাবেল ইস্যু, কোন সাহায্য?
মোহিত পান্ডে

@ মোহিতপান্দে যখন আমি ফ্যান্টমজেএস-এর অধীনে এই কোডটির পরীক্ষা চালাচ্ছিলাম এবং এটি ক্রোমের অধীনে চলেছিল তখন আমি একই ত্রুটি পেয়েছিলাম। যদি এটি হয় তবে আমি মনে করি ইএস 6 এর আরও ভাল সমর্থন নিয়ে ফ্যান্টমজেএসের নতুন বিটা সংস্করণ রয়েছে, আপনি এটি ইনস্টল করার চেষ্টা করতে পারেন।
ম্যাটিউজ মোসকা

1
দুর্ভাগ্যক্রমে, এটি কাজ করে না এবং আমি তার জন্য একটি রেজিওস লিখেছিলাম। উত্তর হিসাবে যুক্ত করা হয়েছে।
মোহিত পান্ডে

এই সমাধানটি কেবল তখনই কাজ করে যদি ব্যাক-টিক "` "অক্ষরটি টেম্পলেট স্ট্রিংয়ে উপস্থিত না থাকে
স্লিভারনিজা - এমএসএফটি

আমি চেষ্টা করার পরে আমি পেয়েছিলাম ReferenceError: _ is not defined। এটি কি কোড ES6 নয় তবে lodashনির্দিষ্ট, বা ...?
এক্সপিটি

29

আপনি এখানে যা চাইছেন:

//non working code quoted from the question
let b=10;
console.log(a.template());//b:10

একেবারে সমান (পাওয়ার এবং, এর, সুরক্ষার দিক থেকে) এর সাথে সমান: কোডযুক্ত evalস্ট্রিং নেওয়ার এবং সেই কোডটি কার্যকর করার ক্ষমতা; এবং আহ্বানকারী কোডটির কলারের পরিবেশে স্থানীয় ভেরিয়েবলগুলি দেখার ক্ষমতা।

জেএসে কোনও ফাংশনের জন্য তার কলারে স্থানীয় ভেরিয়েবলগুলি দেখার কোনও উপায় নেই, যদি না সেই ফাংশনটি না হয় eval()। এমনকি এটি Function()করতে পারে না।


আপনি যখন জাভাস্ক্রিপ্টে "টেমপ্লেট স্ট্রিংস" নামে কিছু আছে বলে শুনছেন, তখন এটি গোঁফের মতো একটি বিল্ট-ইন টেম্পলেট লাইব্রেরি ধরে নেওয়া স্বাভাবিক। এটা না। এটি প্রধানত কেবল স্ট্রিং ইন্টারপোলেশন এবং জেএসের জন্য একাধিক স্ট্রিং। যদিও আমি মনে করি এটি কিছুক্ষণের জন্য একটি সাধারণ ভুল ধারণা হতে চলেছে। :(


2
টিবিএইচ এটাই আমি ভেবেছিলাম। খুব, খুব সহজ ছিল।
ব্রায়ান রায়নার

এটি (এখনও) কাজ করে? আমি পেয়ে করছি template is not a function
আয়নিক বিজাউ

2
এই উত্তরের উপরের কোড ব্লকটি প্রশ্নের একটি উদ্ধৃতি। এটা কাজ করে না.
জেসন ওরেডরফ

27

না, ডায়নামিক কোড জেনারেশন ছাড়া এটি করার কোনও উপায় নেই।

তবে, আমি একটি ফাংশন তৈরি করেছি যা নিয়মিত স্ট্রিংটিকে একটি ফাংশনে পরিণত করবে যা অভ্যন্তরীণভাবে টেমপ্লেটের স্ট্রিংগুলি ব্যবহার করে মানচিত্রের মানচিত্র সরবরাহ করা যেতে পারে।

টেমপ্লেট স্ট্রিং গিস্ট তৈরি করুন

/**
 * Produces a function which uses template strings to do simple interpolation from objects.
 * 
 * Usage:
 *    var makeMeKing = generateTemplateString('${name} is now the king of ${country}!');
 * 
 *    console.log(makeMeKing({ name: 'Bryan', country: 'Scotland'}));
 *    // Logs 'Bryan is now the king of Scotland!'
 */
var generateTemplateString = (function(){
    var cache = {};

    function generateTemplate(template){
        var fn = cache[template];

        if (!fn){
            // Replace ${expressions} (etc) with ${map.expressions}.

            var sanitized = template
                .replace(/\$\{([\s]*[^;\s\{]+[\s]*)\}/g, function(_, match){
                    return `\$\{map.${match.trim()}\}`;
                    })
                // Afterwards, replace anything that's not ${map.expressions}' (etc) with a blank string.
                .replace(/(\$\{(?!map\.)[^}]+\})/g, '');

            fn = Function('map', `return \`${sanitized}\``);
        }

        return fn;
    }

    return generateTemplate;
})();

ব্যবহার:

var kingMaker = generateTemplateString('${name} is king!');

console.log(kingMaker({name: 'Bryan'}));
// Logs 'Bryan is king!' to the console.

আশা করি এটি কারও সাহায্য করবে। আপনি যদি কোডটিতে কোনও সমস্যা খুঁজে পান তবে গিস্টটি আপডেট করার জন্য দয়া করে এত দয়া করুন।


ধন্যবাদ! আমি এটি জাভাস্ক্রিপ্ট স্প্রিন্টফ সমাধানের পরিবর্তে ব্যবহার করেছি।
seangwright

1
প্রতিটি টেমপ্লেট var test = generateTemplateString('/api/${param1}/${param2}/') console.log(test({param1: 'bar', param2: 'foo'}))ফিরে আসার জন্য কাজ করে না/api/bar//
গিলাইম ভিনসেন্ট

ধন্যবাদ, স্থির। রেজেক্স two {প্যারাম 1} / $ {পরম 2 a এর একক ম্যাচ অন্তর্ভুক্ত করেছিল যখন এটি দুটি ম্যাচ হওয়া উচিত ছিল।
ব্রায়ান রায়নার 14

মনে রাখবেন যে পিছনে টিক্সের জন্য সমর্থন হারিয়েছে বলে, এটি আইই 11 এ কাজ করে না।
s.meijer

1
অবশ্যই, যদি কোনও ব্রাউজার দ্বারা টেম্পলেট স্ট্রিংগুলি সমর্থন করে না, তবে এই পদ্ধতিটি কাজ করবে না। আপনি যদি অসমর্থিত ব্রাউজারগুলিতে টেম্পলেট স্ট্রিং ব্যবহার করতে চান তবে আমি টাইপস্ক্রিপ্টের মতো ভাষা বা বাবেলের মতো ট্রান্সপ্লোর ব্যবহার করার পরামর্শ দেব; পুরানো ব্রাউজারগুলিতে ES6 পাওয়ার একমাত্র উপায়।
ব্রায়ান রায়নার

9

টিএলডিআর: https://jsfiddle.net/w3jx07vt/

সবাই ভেরিয়েবল অ্যাক্সেস সম্পর্কে উদ্বিগ্ন বলে মনে হচ্ছে, কেন কেবল সেগুলি পাস করবেন না? আমি নিশ্চিত যে কলারের মধ্যে পরিবর্তনশীল প্রসঙ্গটি পাওয়া এবং এটি পাস করা খুব কঠিন হবে না। আপত্তি থেকে প্রস্তাবগুলি পেতে এই https://stackoverflow.com/a/6394168/6563504 ব্যবহার করুন । আমি এখনই আপনার জন্য পরীক্ষা করতে পারি না, তবে এটি কাজ করা উচিত।

function renderString(str,obj){
    return str.replace(/\$\{(.+?)\}/g,(match,p1)=>{return index(obj,p1)})
}

পরীক্ষিত। এখানে সম্পূর্ণ কোড।

function index(obj,is,value) {
    if (typeof is == 'string')
        is=is.split('.');
    if (is.length==1 && value!==undefined)
        return obj[is[0]] = value;
    else if (is.length==0)
        return obj;
    else
        return index(obj[is[0]],is.slice(1), value);
}

function renderString(str,obj){
    return str.replace(/\$\{.+?\}/g,(match)=>{return index(obj,match)})
}

renderString('abc${a}asdas',{a:23,b:44}) //abc23asdas
renderString('abc${a.c}asdas',{a:{c:22,d:55},b:44}) //abc22asdas

@ s.meijer আপনি কি বিস্তারিত বলতে পারবেন? আমি এই কোডটি সফলভাবে ব্যবহার করছি। jsfiddle.net/w3jx07vt
এম

1
আরও ভাল রেজেক্স আপনাকে ${}অক্ষর নির্বাচন না করার অনুমতি দেয় । চেষ্টা করুন:/(?!\${)([^{}]*)(?=})/g
এরিক হোডনস্কি

@ রিলেক jsfiddle.net/w3jx07vt/2 আমি এই কাজটি করতে পারি না, হাত ধার দেওয়ার যত্ন নিয়ে আমি আমার পোস্ট আপডেট করব? :)
এম

সুতরাং আপনি যেভাবে এটি ধরার চেষ্টা করছেন এটি আসলে তেমন কোনও উপকার করবে না, আমি পরিবর্তে স্ট্রিং প্রতিস্থাপনটি শেষ করেছি। ইন্টারপোলেশনের একটি পদক্ষেপ যুক্ত করার পরিবর্তে, আমি স্ট্রিংটিকে ইন্টারপ বা স্ট্রিং হিসাবে ব্যবহার করতে পারি। অভিনব নয়, তবে তা কাজ করেছে।
এরিক হোডনস্কি

8

এখানে সমস্যাটি এমন একটি ফাংশন যা তার কলারের ভেরিয়েবলগুলিতে অ্যাক্সেস করে। এই কারণেই আমরা evalটেমপ্লেট প্রসেসিংয়ের জন্য সরাসরি ব্যবহৃত হচ্ছে দেখছি । একটি সম্ভাব্য সমাধান হ'ল অভিধানের বৈশিষ্ট্য অনুসারে আনুষ্ঠানিক পরামিতিগুলি গ্রহণ করে একটি ক্রিয়াকলাপ উত্পন্ন করা এবং এটি একই ক্রমে সম্পর্কিত মানগুলির সাথে কল করা। একটি বিকল্প উপায় হ'ল এই জাতীয় কিছু সহজ:

var name = "John Smith";
var message = "Hello, my name is ${name}";
console.log(new Function('return `' + message + '`;')());

বাবেল সংকলক ব্যবহারকারী যে কোনও ব্যক্তির জন্য আমাদের এমন ক্লোজার তৈরি করতে হবে যা এটি তৈরি হয়েছিল এমন পরিবেশের স্মরণ করে:

console.log(new Function('name', 'return `' + message + '`;')(name));

আপনার প্রথম স্নিপেটটি এর চেয়ে খারাপ evalকারণ এটি কেবল একটি বৈশ্বিক nameপরিবর্তনশীল সাথে কাজ করে
বার্গি

@ বেরগি আপনার বক্তব্যটি বৈধ - ফাংশনের সুযোগটি নষ্ট হবে। আমি সমস্যার একটি সহজ সমাধান উপস্থাপন করতে চেয়েছিলাম এবং কী করা যায় তার একটি সরল উদাহরণ সরবরাহ করেছি। সমস্যাটি কাটিয়ে উঠার জন্য যে কেউ কেবল নিম্নলিখিতটি নিয়ে আসতে পারে: var template = function() { var name = "John Smith"; var message = "Hello, my name is ${name}"; this.local = new Function('return '+ বার্তা +';')();}
দিদিঙ্কো

না, যে ঠিক কী না কাজ - new Functionঅ্যাক্সেস নেই var nameমধ্যে templateফাংশন।
বার্গি

দ্বিতীয় স্নিপটি আমার সমস্যার সমাধান করেছে ... আমার কাছ থেকে ভোট দিন! ধন্যবাদ, এটি একটি আইফ্রেমে গতিশীল রাউটিংয়ের সাথে আমাদের যে অস্থায়ী সমস্যাটি ছিল তা সমাধান করতে সহায়তা করেছে :)
ক্রিস বয়েড

7

এখানে অনেকগুলি ভাল সমাধান পোস্ট করা হয়েছে তবে এখনও ES6 স্ট্রিং.আরভ পদ্ধতিটি ব্যবহার করে না এমন কোনটি নেই । এখানে আমার অবদান। এটির একটি গুরুত্বপূর্ণ সীমাবদ্ধতা রয়েছে যে এটি কেবলমাত্র পাস করা বস্তু থেকে সম্পত্তি গ্রহণ করবে, যার অর্থ টেমপ্লেটে কোনও কোড এক্সিকিউশন কাজ করবে না।

function parseStringTemplate(str, obj) {
    let parts = str.split(/\$\{(?!\d)[\wæøåÆØÅ]*\}/);
    let args = str.match(/[^{\}]+(?=})/g) || [];
    let parameters = args.map(argument => obj[argument] || (obj[argument] === undefined ? "" : obj[argument]));
    return String.raw({ raw: parts }, ...parameters);
}
let template = "Hello, ${name}! Are you ${age} years old?";
let values = { name: "John Doe", age: 18 };

parseStringTemplate(template, values);
// output: Hello, John Doe! Are you 18 years old?
  1. অ-যুক্তিযুক্ত পাঠ্য অংশগুলিতে স্ট্রিং বিভক্ত করুন। রেজেক্স দেখুন ।
    parts: ["Hello, ", "! Are you ", " years old?"]
  2. সম্পত্তির নামগুলিতে স্ট্রিং বিভক্ত করুন। ম্যাচ ব্যর্থ হলে খালি অ্যারে।
    args: ["name", "age"]
  3. objসম্পত্তি নাম অনুসারে মানচিত্রের পরামিতি । অগভীর এক স্তরের ম্যাপিংয়ের মাধ্যমে সমাধান সীমাবদ্ধ। অপরিজ্ঞাত মানগুলি একটি খালি স্ট্রিংয়ের সাথে প্রতিস্থাপিত হয়, তবে অন্যান্য মিথ্যা মানগুলি গৃহীত হয়।
    parameters: ["John Doe", 18]
  4. ব্যবহার String.raw(...)এবং ফলাফল ফলাফল।

কৌতূহলের বাইরে স্ট্রিং.আরও এখানে আসলে কী মান দিচ্ছে? দেখে মনে হচ্ছে আপনি স্ট্রিংকে বিশ্লেষণ এবং বিকল্পগুলি কী তা ট্র্যাক করে রাখার সমস্ত কাজ করছেন। এটি কি কেবল .replace()বারবার কল করা থেকে আলাদা ?
স্টিভ বেনেট

ফেয়ার পয়েন্ট, @ স্টিভবেনেট। একটি সাধারণ স্ট্রিংটিকে টেম্পলেট স্ট্রিংয়ে পরিণত করতে আমার কিছু সমস্যা হয়েছিল এবং আমি নিজেই কাঁচা বস্তু তৈরি করে একটি সমাধান পেয়েছি। আমার ধারণা, এটি স্ট্রিং.আরওকে একটি সংক্ষেপণ পদ্ধতিতে হ্রাস করে তবে আমি মনে করি এটি বেশ ভালভাবে কাজ করে। আমি এর সাথে একটি দুর্দান্ত সমাধান দেখতে চাই .replace(), যদিও :) আমি মনে করি পাঠযোগ্যতা গুরুত্বপূর্ণ, তাই আমি নিজেই নিয়মিত ভাব প্রকাশ করার সময়, সমস্ত কিছু বোঝার জন্য আমি তাদের নাম দেওয়ার চেষ্টা করি ...
পেকা

6

দানিয়েলের উত্তর (এবং s.meijer এর অনুরূপ সারকথা ) কিন্তু আরো ভালো পঠনযোগ্য:

const regex = /\${[^{]+}/g;

export default function interpolate(template, variables, fallback) {
    return template.replace(regex, (match) => {
        const path = match.slice(2, -1).trim();
        return getObjPath(path, variables, fallback);
    });
}

//get the specified property or nested property of an object
function getObjPath(path, obj, fallback = '') {
    return path.split('.').reduce((res, key) => res[key] || fallback, obj);
}

দ্রষ্টব্য: এটি s.meijer এর মূলটিকে কিছুটা উন্নত করে, যেহেতু এটি এর মতো জিনিসের সাথে মেলে না ${foo{bar}(রেজেক্স কেবলমাত্র ভিতরে-কোঁকড়ানো নমনীয় অক্ষরের অনুমতি দেয় ${এবং })।


আপডেট: আমাকে এটি ব্যবহার করে উদাহরণের জন্য জিজ্ঞাসা করা হয়েছিল, সুতরাং আপনি এখানে যান:

const replacements = {
    name: 'Bob',
    age: 37
}

interpolate('My name is ${name}, and I am ${age}.', replacements)

আপনি কি আসলে এটি ব্যবহার করে একটি উদাহরণ পোস্ট করতে পারেন? এই জাভাস্ক্রিপ্টটি আমার বাইরে কিছুটা। আমি /\$\{(.*?)(?!\$\{)\}/g(নেস্ট কোঁকড়া ধনুর্বন্ধনী হ্যান্ডেলগুলি) এর একটি রেজেক্সের পরামর্শ দেব । আমার একটি কার্যনির্বাহী সমাধান রয়েছে তবে আমি নিশ্চিত নই যে এটি আপনার মতো পোর্টেবল, সুতরাং এটি একটি পৃষ্ঠায় কীভাবে প্রয়োগ করা উচিত তা দেখতে আমি পছন্দ করব। খনিও ব্যবহার করে eval()
নিয়মিত জো

আমি এগিয়ে গিয়েছিলাম এবং পাশাপাশি একটি উত্তর পোস্ট করেছি, এবং কীভাবে আরও সুরক্ষিত এবং পারফরম্যান্স-মনের দিক থেকে তৈরি করা যায় সে সম্পর্কে আমি আপনার প্রতিক্রিয়াটি পছন্দ করব: stackoverflow.com/a/48294208
নিয়মিত জো

@ রেগুলারজো আমি একটি উদাহরণ যুক্ত করেছি। আমার লক্ষ্যটি এটিকে সহজ রাখা ছিল, তবে আপনি ঠিক বলেছেন যে আপনি যদি নেস্টেড কোঁকড়া ধনুর্বন্ধনী পরিচালনা করতে চান তবে আপনার রেজেক্স পরিবর্তন করা দরকার। যাইহোক, নিয়মিত স্ট্রিংকে মূল্যায়ন করার সময় আমি এটির জন্য কোনও ব্যবহারের ক্ষেত্রে ভাবতে পারি না যেন এটি কোনও টেমপ্লেট আক্ষরিক (এই ফাংশনের পুরো উদ্দেশ্য)। তোমার মনে কি ছিল?
ম্যাট ব্রাউন

এছাড়াও, আমি না পারফরম্যান্স বিশেষজ্ঞ বা সুরক্ষা বিশেষজ্ঞ; আমার উত্তর সত্যিই ঠিক আগের দুটি উত্তর একত্রিত হয়। তবে আমি বলব যে evalসম্ভাব্য ভুলগুলির জন্য আপনাকে আরও বেশি উন্মুক্ত ব্যবহার করবে যা সুরক্ষার সমস্যার কারণ হয়ে দাঁড়াবে, যদিও আমার সমস্ত সংস্করণটি বিন্দু-বিচ্ছিন্ন পথ থেকে কোনও বস্তুর উপর একটি সম্পত্তি অনুসন্ধান করছে যা নিরাপদ হওয়া উচিত।
ম্যাট ব্রাউন

5

উদাহরণস্বরূপ, আপনি স্ট্রিং প্রোটোটাইপ ব্যবহার করতে পারেন

String.prototype.toTemplate=function(){
    return eval('`'+this+'`');
}
//...
var a="b:${b}";
var b=10;
console.log(a.toTemplate());//b:10

তবে মূল প্রশ্নের উত্তর কোনও উপায় নয়।


5

আমি মিঃ মিঃ এর উত্তর পছন্দ করেছি এবং তার উপর ভিত্তি করে আমার নিজস্ব সংস্করণ লিখেছি:

function parseTemplate(template, map, fallback) {
    return template.replace(/\$\{[^}]+\}/g, (match) => 
        match
            .slice(2, -1)
            .trim()
            .split(".")
            .reduce(
                (searchObject, key) => searchObject[key] || fallback || match,
                map
            )
    );
}

1
ঝরঝরে! সত্যিই ঝরঝরে!
xpt

4

ইন্টারনেট এক্সপ্লোরারের সমর্থন সহ আমার এই পদ্ধতিটি প্রয়োজন। দেখা গেল, পিছনের টিকগুলি এমনকি আইই 11 দ্বারা সমর্থিত নয়। এছাড়াও; ব্যবহার করা evalবা এটি সমতুল্য Functionমনে হয় না সঠিক।

এক যে লক্ষ্য; আমি ব্যাকটিকগুলিও ব্যবহার করি তবে এগুলি বাবেলের মতো সংকলকগুলি দ্বারা সরানো হয়। অন্যান্যগুলির দ্বারা প্রস্তাবিত পদ্ধতিগুলি রান-টাইমের উপর নির্ভর করে। আগে যেমন বলেছি; এটি আইই ১১ এবং এর চেয়ে কম সমস্যা।

সুতরাং আমি এটাই নিয়ে এসেছি:

function get(path, obj, fb = `$\{${path}}`) {
  return path.split('.').reduce((res, key) => res[key] || fb, obj);
}

function parseTpl(template, map, fallback) {
  return template.replace(/\$\{.+?}/g, (match) => {
    const path = match.substr(2, match.length - 3).trim();
    return get(path, map, fallback);
  });
}

উদাহরণ আউটপুট:

const data = { person: { name: 'John', age: 18 } };

parseTpl('Hi ${person.name} (${person.age})', data);
// output: Hi John (18)

parseTpl('Hello ${person.name} from ${person.city}', data);
// output: Hello John from ${person.city}

parseTpl('Hello ${person.name} from ${person.city}', data, '-');
// output: Hello John from -

"ইভাল ব্যবহার করা বা এটি সমতুল্য ফাংশনটি সঠিক মনে হয় না" " ... হ্যাঁ ... আমি সম্মত, তবে আমি মনে করি এটি খুব কম ব্যবহারের মধ্যে একটি, যাতে কেউ বলতে পারে যে "মিম্চে, আসুন আমরা এটি ব্যবহার করি"। দয়া করে jsperf.com/es6-string-tmpl দেখুন - এটি আমার ব্যবহারিক ব্যবহারের ক্ষেত্রে। আপনার ফাংশন (খনি হিসাবে একই রিজেক্সপ সহ) এবং খনি (ইওওয়াল + স্ট্রিং লিটারাল) ব্যবহার করে। ধন্যবাদ! :)
আন্দ্রে পুড্ডু

@ আন্দ্রেয়া পুড্ডু, আপনার অভিনয়টি আরও ভাল। তবে আবার; টেমপ্লেট স্ট্রিংগুলি IE এ অসমর্থিত। সুতরাং eval('`' + taggedURL + '`')সহজভাবে কাজ করে না।
s.meijer

"মনে হচ্ছে" আরও ভাল আমি বলতে চাই, কারণ এটি বিচ্ছিন্নতার সাথে পরীক্ষা করা হয়েছে ... সেই পরীক্ষার একমাত্র উদ্দেশ্য ছিল সম্ভাব্য পারফরম্যান্সের সমস্যাগুলি ব্যবহার করে দেখা eval। টেম্পলেট আক্ষরিক সম্পর্কিত: আবার এটি নির্দেশ করার জন্য ধন্যবাদ। আমি আমার কোডটি স্থানান্তর করতে বাবেলকে ব্যবহার করছি তবে আমার ফাংশনটি এখনও স্পষ্টতই কাজ করবে না 😐
আন্দ্রে পুড্ডু

3

আমি বর্তমানে বিদ্যমান উত্তরগুলিতে মন্তব্য করতে পারি না তাই ব্রায়ান রায়নরের দুর্দান্ত প্রতিক্রিয়া সম্পর্কে আমি সরাসরি মন্তব্য করতে পারিনি। সুতরাং, এই প্রতিক্রিয়া সামান্য সংশোধন করে তার উত্তর আপডেট করতে চলেছে।

সংক্ষেপে, তার ফাংশনটি আসলে তৈরি ফাংশনটি ক্যাশে করতে ব্যর্থ হয়, সুতরাং এটি সর্বদা পুনরায় তৈরি হবে, তা আগে যে টেমপ্লেটটি দেখেছিল তা নির্বিশেষে। এখানে সংশোধিত কোডটি দেওয়া হয়েছে:

    /**
     * Produces a function which uses template strings to do simple interpolation from objects.
     * 
     * Usage:
     *    var makeMeKing = generateTemplateString('${name} is now the king of ${country}!');
     * 
     *    console.log(makeMeKing({ name: 'Bryan', country: 'Scotland'}));
     *    // Logs 'Bryan is now the king of Scotland!'
     */
    var generateTemplateString = (function(){
        var cache = {};

        function generateTemplate(template){
            var fn = cache[template];

            if (!fn){
                // Replace ${expressions} (etc) with ${map.expressions}.

                var sanitized = template
                    .replace(/\$\{([\s]*[^;\s\{]+[\s]*)\}/g, function(_, match){
                        return `\$\{map.${match.trim()}\}`;
                    })
                    // Afterwards, replace anything that's not ${map.expressions}' (etc) with a blank string.
                    .replace(/(\$\{(?!map\.)[^}]+\})/g, '');

                fn = cache[template] = Function('map', `return \`${sanitized}\``);
            }

            return fn;
        };

        return generateTemplate;
    })();

3

@ ম্যাটিউজ মোসকা, সমাধানটি দুর্দান্ত কাজ করে তবে আমি যখন এটিকে রিএ্যাক্ট নেটিভ (বিল্ড মোড) এ ব্যবহার করি তখন এটি একটি ত্রুটি ফেলে দেয়: অবৈধ চরিত্র '`' , যদিও এটি ডিবাগ মোডে চালানোর সময় এটি কাজ করে।

তাই আমি রেজিেক্স ব্যবহার করে আমার নিজস্ব সমাধান লিখেছিলাম।

String.prototype.interpolate = function(params) {
  let template = this
  for (let key in params) {
    template = template.replace(new RegExp('\\$\\{' + key + '\\}', 'g'), params[key])
  }
  return template
}

const template = 'Example text: ${text}',
  result = template.interpolate({
    text: 'Foo Boo'
  })

console.log(result)

ডেমো: https://es6console.com/j31pqx1p/

দ্রষ্টব্য: যেহেতু আমি কোনও সমস্যার মূল কারণ জানি না, তাই আমি প্রতিক্রিয়া-নেটিভ রেপো, https://github.com/facebook/react-native/issues/14107 এ টিকিট উত্থাপন করেছি , যাতে তারা একবার সক্ষম হতে পারে ঠিক করুন / একই সম্পর্কে আমাকে গাইড :)


এটি ব্যাক-টিক অক্ষরযুক্ত টেমপ্লেটগুলি সমর্থন করে। যাইহোক, একটি টেম্প্লেটিং প্যাটার্ন উদ্ভাবনের চেষ্টা করার চেয়ে আপনি কেবল গোঁফ বা অনুরূপ ব্যবহার করার চেয়ে ভাল । আপনার টেমপ্লেটগুলি এটি কতটা জটিল তার উপর নির্ভর করে এটি একটি ব্রুট ফোর্স অ্যাপ্রোচ যা প্রান্তের কেসগুলি বিবেচনা করে না - কীটিতে একটি বিশেষ রেজেক্স প্যাটার্ন থাকতে পারে।
স্লিভারনিঞ্জা - এমএসএফটি

2

এখনও গতিশীল তবে কেবল একটি নগ্ন ইওল ব্যবহারের চেয়ে নিয়ন্ত্রণ করা বেশি বলে মনে হচ্ছে:

const vm = require('vm')
const moment = require('moment')


let template = '### ${context.hours_worked[0].value} \n Hours worked \n #### ${Math.abs(context.hours_worked_avg_diff[0].value)}% ${fns.gt0(context.hours_worked_avg_diff[0].value, "more", "less")} than usual on ${fns.getDOW(new Date())}'
let context = {
  hours_worked:[{value:10}],
  hours_worked_avg_diff:[{value:10}],

}


function getDOW(now) {
  return moment(now).locale('es').format('dddd')
}

function gt0(_in, tVal, fVal) {
  return _in >0 ? tVal: fVal
}



function templateIt(context, template) {
  const script = new vm.Script('`'+template+'`')
  return script.runInNewContext({context, fns:{getDOW, gt0 }})
}

console.log(templateIt(context, template))

https://repl.it/IdVt/3


1

এই সমাধানটি ES6 ছাড়াই কাজ করে:

function render(template, opts) {
  return new Function(
    'return new Function (' + Object.keys(opts).reduce((args, arg) => args += '\'' + arg + '\',', '') + '\'return `' + template.replace(/(^|[^\\])'/g, '$1\\\'') + '`;\'' +
    ').apply(null, ' + JSON.stringify(Object.keys(opts).reduce((vals, key) => vals.push(opts[key]) && vals, [])) + ');'
  )();
}

render("hello ${ name }", {name:'mo'}); // "hello mo"

দ্রষ্টব্য: Functionকনস্ট্রাক্টর সর্বদা বিশ্বব্যাপী স্কোপটিতে তৈরি করা হয়, যা টেমপ্লেট দ্বারা গ্লোবাল ভেরিয়েবলগুলি ওভাররাইট করার সম্ভাব্য কারণ হতে পারেrender("hello ${ someGlobalVar = 'some new value' }", {name:'mo'});


0

যেহেতু আমরা এমন কিছুতে হুইলটিকে পুনঃস্থাপন করছি যা জাভাস্ক্রিপ্টে একটি সুন্দর বৈশিষ্ট্য হবে।

আমি ব্যবহার করি eval(), যা নিরাপদ নয়, তবে জাভাস্ক্রিপ্ট নিরাপদ নয়। আমি সহজেই স্বীকার করে নিয়েছি যে আমি জাভাস্ক্রিপ্টের সাথে সেরা নই, তবে আমার একটি প্রয়োজন ছিল, এবং আমার একটি উত্তরের প্রয়োজন ছিল যাতে আমি এটি তৈরি করি।

আমি আমার পরিবর্তকের @পরিবর্তে একটি পরিবর্তে স্টাইলাইজ করা বেছে নিয়েছি $, বিশেষত কারণ আমি যতক্ষণ না প্রস্তুত ততক্ষণ মূল্যায়ন না করে অক্ষরের বহুমাত্রিক বৈশিষ্ট্যটি ব্যবহার করতে চাই । সুতরাং ভেরিয়েবল সিনট্যাক্স হয়@{OptionalObject.OptionalObjectN.VARIABLE_NAME}

আমি কোনও জাভাস্ক্রিপ্ট বিশেষজ্ঞ নই, তাই আমি আনন্দের সাথে উন্নতির বিষয়ে পরামর্শ নেব তবে ...

var prsLiteral, prsRegex = /\@\{(.*?)(?!\@\{)\}/g
for(i = 0; i < myResultSet.length; i++) {
    prsLiteral = rt.replace(prsRegex,function (match,varname) {
        return eval(varname + "[" + i + "]");
        // you could instead use return eval(varname) if you're not looping.
    })
    console.log(prsLiteral);
}

একটি খুব সাধারণ বাস্তবায়ন অনুসরণ করা হয়

myResultSet = {totalrecords: 2,
Name: ["Bob", "Stephanie"],
Age: [37,22]};

rt = `My name is @{myResultSet.Name}, and I am @{myResultSet.Age}.`

var prsLiteral, prsRegex = /\@\{(.*?)(?!\@\{)\}/g
for(i = 0; i < myResultSet.totalrecords; i++) {
    prsLiteral = rt.replace(prsRegex,function (match,varname) {
        return eval(varname + "[" + i + "]");
        // you could instead use return eval(varname) if you're not looping.
    })
    console.log(prsLiteral);
}

আমার বাস্তব বাস্তবায়নে, আমি ব্যবহার করতে পছন্দ করি @{{variable}}। ধনুর্বন্ধনী আরও একটি সেট। অপ্রত্যাশিতভাবে এর মুখোমুখি হওয়ার অসাধ্য সম্ভাবনা। এটির জন্য রেজেক্স দেখতে ভাল লাগবে/\@\{\{(.*?)(?!\@\{\{)\}\}/g

পড়া সহজ করতে

\@\{\{    # opening sequence, @{{ literally.
(.*?)     # capturing the variable name
          # ^ captures only until it reaches the closing sequence
(?!       # negative lookahead, making sure the following
          # ^ pattern is not found ahead of the current character
  \@\{\{  # same as opening sequence, if you change that, change this
)
\}\}      # closing sequence.

আপনি Regex সঙ্গে অভিজ্ঞতা না করে থাকেন, একটি প্রশংসনীয় নিরাপদ নিয়ম যে অ আলফানিউমেরিক অক্ষর অব্যাহতি, এবং না কি অযথা চিঠি অব্যাহতি হিসাবে অনেক পলান চিঠি কার্যত Regex সব স্বাদে বিশেষ অর্থ আছে।


0

আপনার এই ছোট্ট জেএস মডিউলটি অ্যান্ড্রিয়া গিয়ামারচি দ্বারা, গিথুব থেকে চেষ্টা করা উচিত: https://github.com/WebReflection/backtick-template

/*! (C) 2017 Andrea Giammarchi - MIT Style License */
function template(fn, $str, $object) {'use strict';
  var
    stringify = JSON.stringify,
    hasTransformer = typeof fn === 'function',
    str = hasTransformer ? $str : fn,
    object = hasTransformer ? $object : $str,
    i = 0, length = str.length,
    strings = i < length ? [] : ['""'],
    values = hasTransformer ? [] : strings,
    open, close, counter
  ;
  while (i < length) {
    open = str.indexOf('${', i);
    if (-1 < open) {
      strings.push(stringify(str.slice(i, open)));
      open += 2;
      close = open;
      counter = 1;
      while (close < length) {
        switch (str.charAt(close++)) {
          case '}': counter -= 1; break;
          case '{': counter += 1; break;
        }
        if (counter < 1) {
          values.push('(' + str.slice(open, close - 1) + ')');
          break;
        }
      }
      i = close;
    } else {
      strings.push(stringify(str.slice(i)));
      i = length;
    }
  }
  if (hasTransformer) {
    str = 'function' + (Math.random() * 1e5 | 0);
    if (strings.length === values.length) strings.push('""');
    strings = [
      str,
      'with(this)return ' + str + '([' + strings + ']' + (
        values.length ? (',' + values.join(',')) : ''
      ) + ')'
    ];
  } else {
    strings = ['with(this)return ' + strings.join('+')];
  }
  return Function.apply(null, strings).apply(
    object,
    hasTransformer ? [fn] : []
  );
}

template.asMethod = function (fn, object) {'use strict';
  return typeof fn === 'function' ?
    template(fn, this, object) :
    template(this, fn);
};

ডেমো (নিম্নলিখিত সমস্ত পরীক্ষাগুলি সত্য হয়):

const info = 'template';
// just string
`some ${info}` === template('some ${info}', {info});

// passing through a transformer
transform `some ${info}` === template(transform, 'some ${info}', {info});

// using it as String method
String.prototype.template = template.asMethod;

`some ${info}` === 'some ${info}'.template({info});

transform `some ${info}` === 'some ${info}'.template(transform, {info});

0

আমি নিজের সমাধানটি একটি ফাংশন হিসাবে বর্ণনা সহ একটি ধরণের করে তৈরি করেছি

export class Foo {
...
description?: Object;
...
}

let myFoo:Foo = {
...
  description: (a,b) => `Welcome ${a}, glad to see you like the ${b} section`.
...
}

এবং তাই করছে:

let myDescription = myFoo.description('Bar', 'bar');

0

পরিবর্তে ভাল ব্যবহারের পরিবর্তে regex ব্যবহার হয়

এভাল এটির প্রস্তাবিত এবং উচ্চ নিরুৎসাহিত নয়, তাই দয়া করে এটি ব্যবহার করবেন না ( এমডএন এভাল )।

 let b = 10;
 let a="b:${b}";

let response = a.replace(/\${\w+}/ ,b);
conssole.log(response);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.