জাভাস্ক্রিপ্টে মানআফ () বনাম টু স্ট্রিং ()


115

জাভাস্ক্রিপ্টে প্রতিটি বস্তুর একটি মানফল () এবং টুস্ট্রিং () পদ্ধতি রয়েছে। আমি ভেবেছিলাম যে যখনই স্ট্রিং রূপান্তরটির জন্য ডাকা হবে তখন টসস্ট্রিং () পদ্ধতিটি শুরু হয়েছিল, তবে দৃশ্যত এটি মান ওফ () দ্বারা ট্রাম্পড হয়।

উদাহরণস্বরূপ, কোড

var x = {toString: function() {return "foo"; },
         valueOf: function() {return 42; }};
window.console.log ("x="+x);
window.console.log ("x="+x.toString());

মুদ্রণ করবে

x=42
x=foo

এটি আমাকে পিছন দিকে আঘাত করে .. যদি x একটি জটিল সংখ্যা হয়, উদাহরণস্বরূপ, আমি এর মানটি আমাকে দিতে চাই তবে মানটি চাই (তবে) যখনই আমি একটি স্ট্রিতে রূপান্তর করতে চাই তখন আমি "এ + দ্বি" এর মতো কিছু চাই। এবং আমি স্ট্রিংকে স্পষ্টভাবে প্রসঙ্গে যে স্ট্রিংকে বোঝায় তা টু স্ট্রিং () করতে চাই না।

এটা কি ঠিক এভাবেই হয়?


6
আপনি চেষ্টা করেছেন window.console.log (x);নাকি alert (x);?
Li0liQ

5
তারা যথাক্রমে "অবজেক্ট" এবং "ফু" দেয়। মজার জিনিস.
ব্রেনজাম

আসলে, সতর্কতা (এক্স); "foo" দেয়, এবং window.console.log (x); ফায়ারব্যাগে "foo {}" এবং Chrome কনসোলে পুরো অবজেক্ট দেয়।
ব্রেনজাম

ফায়ারফক্সে 33.0.2 alert(x)প্রদর্শন fooএবং window.console.log(x)প্রদর্শন করে Object { toString: x.toString(), valueOf: x.valueOf() }
জন সন্ডারসন

উত্তর:


107

("X =" + x) "x = মান" এবং "x = টস্ট্রিং" না দেওয়ার কারণটি নিম্নলিখিত। "+" মূল্যায়ন করার সময়, জাভাস্ক্রিপ্ট প্রথমে অপারেন্ডগুলির আদিম মান সংগ্রহ করে এবং তারপরে সিদ্ধান্ত নেয় যে প্রতিটি আদিম ধরণের ভিত্তিতে সংযোজন বা উপসংহার প্রয়োগ করা উচিত কিনা।

সুতরাং, আপনি কীভাবে এটি মনে হয় এটি কাজ করে

a + b:
    pa = ToPrimitive(a)
    if(pa is string)
       return concat(pa, ToString(b))
    else
       return add(pa, ToNumber(b))

এবং আসলে এটি ঘটে

a + b:
    pa = ToPrimitive(a)
    pb = ToPrimitive(b)*
    if(pa is string || pb is string)
       return concat(ToString(pa), ToString(pb))
    else
       return add(ToNumber(pa), ToNumber(pb))

অর্থাত্, টুস্ট্রিং আপনার মূল অবজেক্টে নয়, মানফলের ফলাফলের জন্য প্রয়োগ করা হয়।

আরও রেফারেন্সের জন্য, বিভাগটি দেখুন 11.6.1 ECMAScript ভাষা নির্দিষ্টকরণের সংযোজন অপারেটর (+)


* STRING কখন প্রেক্ষাপটে বলা হয়, ToPrimitive করে toString ডাকা, কিন্তু এই ক্ষেত্রে এখানে, কারণ + কোনো ধরনের প্রেক্ষাপটে জোরদার করে না।


3
(প্যাঁ স্ট্রিং এন্ড & পিবি স্ট্রিং হয়) "আসলে" ব্লক রিডে "শর্তযুক্ত হওয়া উচিত নয়? অর্থাৎ "||" এর পরিবর্তে "&&" ?
ব্রেইনজাম

3
মানটি অবশ্যই "বা" বলে (লিঙ্কটি দেখুন)।
ব্যবহারকারী 187291

2
হ্যাঁ এটি ঠিক ঠিক - সংক্ষেপে অন্যান্য ধরণের চেয়ে স্ট্রিংগুলিকে প্রাধান্য দেওয়া হয়। যদি অপরেন্দ্র একটি স্ট্রিং হয় তবে পুরো জিনিসটি স্ট্রিং হিসাবে সংমিশ্রিত হবে। ভাল উত্তর.
devios1

76

উত্তরটি পাওয়ার আগে এখানে আরও কিছু বিশদ দেওয়া হল:

var x = {
    toString: function () { return "foo"; },
    valueOf: function () { return 42; }
};

alert(x); // foo
"x=" + x; // "x=42"
x + "=x"; // "42=x"
x + "1"; // 421
x + 1; // 43
["x=", x].join(""); // "x=foo"

toStringফাংশন হয় না "trumped" দ্বারা valueOfসাধারণভাবে। ইসমাস্ক্রিপ্ট স্ট্যান্ডার্ডটি আসলে এই প্রশ্নের উত্তর বেশ সুন্দরভাবে দেয়। প্রতিটি বস্তুর একটি [[DefaultValue]]সম্পত্তি থাকে, যা চাহিদা অনুযায়ী গণনা করা হয়। এই সম্পত্তিটি জিজ্ঞাসা করার সময়, দোভাষী তার কী ধরণের মান প্রত্যাশা করে তার জন্য একটি "ইঙ্গিত" সরবরাহ করে। ইঙ্গিতটি যদি হয় Stringতবে toStringতার আগে ব্যবহৃত হয় valueOf। তবে, যদি ইঙ্গিতটি হয় Numberতবে valueOfপ্রথমে ব্যবহার করা হবে। মনে রাখবেন যে কেবলমাত্র একজন উপস্থিত থাকলে, বা এটি একটি প্রাক-প্রাক-প্রত্যাবর্তন করে, এটি সাধারণত অন্যটিকে দ্বিতীয় পছন্দ হিসাবে ডাকে।

+অপারেটর সবসময় ইঙ্গিতটি প্রদান করে Number, এমনকি যদি প্রথম প্রতীক একটি স্ট্রিং মান। যদিও এটি xতার Numberপ্রতিনিধিত্বের জন্য জিজ্ঞাসা করে , যেহেতু প্রথম অপারেন্ডটি একটি স্ট্রিংটি ফেরত [[DefaultValue]]দেয়, এটি স্ট্রিং কনটেন্টেশন দেয়।

যদি আপনি গ্যারান্টিটি দিতে চান যে toStringস্ট্রিং কনটেনটেশনের জন্য ডাকা হয়, একটি অ্যারে এবং .join("")পদ্ধতিটি ব্যবহার করুন।

(ActionScript 3.0 সামান্য আচরণ পরিবর্তন +অবশ্য। যদি পারেন প্রতীক একটি নয় String, এটি একটি স্ট্রিং সংযুক্তকরণের অপারেটর যেমন আচরণ এবং ইঙ্গিতটি ব্যবহার করবে Stringযখন এটি কল [[DefaultValue]]। সুতরাং, AS3 এ, এই উদাহরণে উৎপাদনের "foo বিন্যাস, এক্স = foo বিন্যাস, foo বিন্যাস = x, foo1, 43, x = foo "।)


1
এছাড়াও খেয়াল করুন যে যদি valueOfবা toStringঅ-আদিম ফিরে আসে তবে সেগুলি উপেক্ষা করা হবে। যদি না উপস্থিত থাকে, না উভয়ই কোনও আদিম ফেরত দেয়, তবে একটি TypeErrorনিক্ষেপ করা হয়।
ব্যাচারি

1
ধন্যবাদ ব্যাচারি, এটি আমি যে উত্তরের জন্য প্রত্যাশা করছিলাম তারই ক্যালিবার। তবে x + "x =" হওয়া উচিত নয়; "42x =" ফলন? এবং এক্স + "1"; ফলন 421? এছাড়াও, আপনার কি ইসমাস্ক্রিপ্ট স্ট্যান্ডার্ডের প্রাসঙ্গিক অংশের জন্য একটি URL আছে?
ব্রেইনজাম

2
প্রকৃতপক্ষে, '+' ইঙ্গিতগুলি ব্যবহার করে না (দেখুন $ 11.6.1) সুতরাং ToPrimitive ডাকে [[DefaultValue]](no-hint), যা সমান [[DefaultValue]](number)
ব্যবহারকারী 187291

9
বিল্ট-ইন ডেট ক্লাসের ক্ষেত্রে এটি মনে হয় না। ("" + new Date(0)) === new Date(0).toString()। একটি তারিখের অবজেক্টটি toString()যখন কোনও কিছুর সাথে যুক্ত হয় তখন তার মানটি সর্বদা ফিরে আসে বলে মনে হয় ।
কেপোজিন

7
+1 এবং থেক্স! আমি আপনার ব্লগ পোস্টটি পেয়েছি যাতে আপনি এই উত্তরটি বিস্তারিতভাবে বর্ণনা করেছেন এবং এখানে লিঙ্ক / ভাগ করতে চেয়েছিলেন। এই উত্তরে এটি সত্যিই সহায়ক সংযোজন ছিল (দিমিত্রি এ সোশনিকভের মন্তব্য সহ)।
গীতারল্যাব

1

TLDR

টাইপ জবরদস্তি, বা অন্তর্নিহিত ধরণের রূপান্তর, দুর্বল টাইপিং সক্ষম করে এবং জাভাস্ক্রিপ্ট জুড়ে ব্যবহৃত হয়। বেশিরভাগ অপারেটর (কঠোর সমতা অপারেটরগুলির উল্লেখযোগ্য ব্যতিক্রম ===এবং !==), এবং মান পরীক্ষা করার ক্রিয়াকলাপগুলি (উদাহরণস্বরূপ if(value)...) তাদের সরবরাহকৃত মানকে বাধ্য করবে, যদি সেই মানগুলির প্রকারগুলি অপারেশনের সাথে তাত্ক্ষণিকভাবে সামঞ্জস্য না করে।

কোনও মানকে বাধ্য করার জন্য ব্যবহৃত যথাযথ প্রক্রিয়াটি মূল্যায়নের প্রকাশের উপর নির্ভর করে। প্রশ্নে, সংযোজন অপারেটরটি ব্যবহার করা হচ্ছে।

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

তারপরে, যেহেতু প্রশ্নের অপারেটরগুলির মধ্যে একটি স্ট্রিং, উভয় অপারেন্ডগুলি স্ট্রিতে রূপান্তরিত হয়। এই প্রক্রিয়াটি বিমূর্ত, অভ্যন্তরীণ অপারেশন ToString(নোট: মূলধন) toStringব্যবহার করে এবং বস্তুর (বা এর প্রোটোটাইপ চেইন) পদ্ধতি থেকে পৃথক ।

অবশেষে, ফলাফলযুক্ত স্ট্রিংগুলি সংক্ষিপ্ত করা হয়।

বিস্তারিত

জাভাস্ক্রিপ্টে প্রতিটি ভাষার ধরণের সাথে সম্পর্কিত প্রতিটি কন্সট্রাক্টর ফাংশন অবজেক্টের প্রোটোটাইপে (যেমন, সংখ্যা, বিগিয়ান্ট, স্ট্রিং, বুলিয়ান, সিম্বল এবং অবজেক্ট) দুটি পদ্ধতি রয়েছে: valueOfএবং toString

এর উদ্দেশ্য valueOfহ'ল কোনও বস্তুর সাথে সম্পর্কিত আদিম মানটি পুনরুদ্ধার করা (যদি এটির একটি থাকে)। যদি কোনও অবজেক্টের অন্তর্নিহিত আদিম মান না থাকে তবে অবজেক্টটি কেবল সহজভাবে ফিরে আসে।

যদি valueOfকোনও আদিমতার বিরুদ্ধে ডাকা হয়, তবে আদিমটি স্বাভাবিক উপায়ে স্বয়ংক্রিয়ভাবে বাক্সযুক্ত হয় এবং অন্তর্নিহিত আদিম মান ফিরে আসে। নোট করুন যে স্ট্রিংয়ের জন্য অন্তর্নিহিত আদিম মান (অর্থাত্‍ প্রদত্ত মান valueOf) হ'ল স্ট্রিং প্রতিনিধিত্ব।

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

console.log(typeof new Boolean(true)) // 'object'
console.log(typeof new Boolean(true).valueOf()) // 'boolean'
console.log(({}).valueOf()) // {} (no primitive value to return)

উদ্দেশ্য toString, অন্য দিকে, একটি অবজেক্ট একটি স্ট্রিং উপস্থাপনা আসতে হয়।

উদাহরণ স্বরূপ:

console.log({}.toString()) // '[object Object]'
console.log(new Number(1).toString()) // '1'

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

জবরদস্তি প্রক্রিয়া চলাকালীন, রূপান্তর দুটি मोड আছে যা ঘটতে পারে:

  1. কোনও বস্তুর কোনও আদিম রূপান্তরকরণ (এতে কোনও ধরণের রূপান্তর নিজেই জড়িত থাকতে পারে) এবং
  2. একটি নির্দিষ্ট ধরনের দৃষ্টান্ত সরাসরি রূপান্তর, আদিম ধরনের এক কন্সট্রাকটর ফাংশন বস্তুর ব্যবহার (অর্থাত। Number(), Boolean(), String()ইত্যাদি)

আদিম রূপান্তর

অপ-আদিম প্রকারকে অপারেশন করার জন্য আদিমগুলিতে রূপান্তর করার চেষ্টা করার সময় বিমূর্ত অপারেশনটিকে ToPrimitive'সংখ্যা', বা 'স্ট্রিং' এর anচ্ছিক "ইঙ্গিত" দিয়ে ডাকা হয়। যদি ইঙ্গিতটি বাদ দেওয়া হয়, তবে ডিফল্ট ইঙ্গিতটি 'সংখ্যা' হয় (যদি না @@toPrimitiveপদ্ধতিটি ওভাররাইড না করা থাকে)। যদি ইঙ্গিতটি 'স্ট্রিং' হয় তবে toStringপ্রথমে চেষ্টা করা হয় এবং valueOfদ্বিতীয়টি যদি toStringকোনও আদিম ফিরে না আসে। অন্যথায়, তদ্বিপরীত। ইঙ্গিতটি রূপান্তরটির অনুরোধ করা অপারেশনের উপর নির্ভর করে।

সংযোজন অপারেটর কোনও ইঙ্গিত সরবরাহ করে না, তাই valueOfপ্রথমে চেষ্টা করা হয়। বিয়োগ অপারেটর 'সংখ্যার' একটি ইঙ্গিত সরবরাহ করে, তাই valueOfপ্রথমে চেষ্টা করা হয়। ইঙ্গিতটি 'স্ট্রিং' হ'ল এমন একমাত্র পরিস্থিতিটিতে আমি সুনির্দিষ্টভাবে দেখতে পাচ্ছি:

  1. Object#toString
  2. বিমূর্ত ক্রিয়াকলাপ ToPropertyKey, যা একটি যুক্তিটিকে একটি মান হিসাবে রূপান্তর করে যা সম্পত্তি কী হিসাবে ব্যবহৃত হতে পারে

ডাইরেক্ট টাইপ রূপান্তর

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

সংযোজনগুলির বিপরীতে, বিয়োগ অপারেটরের ওভারলোডের আচরণ নেই এবং তাই toNumericপ্রতিটি অপারেন্ডকে প্রথমে তাদের ব্যবহার করে আদিমগুলিতে রূপান্তরিত করার জন্য আহ্বান জানাবে ToPrimitive

তাই:

 1  +  1   //  2                 
'1' +  1   // '11'   Both already primitives, RHS converted to string, '1' + '1',   '11'
 1  + [2]  // '12'   [2].valueOf() returns an object, so `toString` fallback is used, 1 + String([2]), '1' + '2', 12
 1  + {}   // '1[object Object]'    {}.valueOf() is not a primitive, so toString fallback used, String(1) + String({}), '1' + '[object Object]', '1[object Object]'
 2  - {}   // NaN    {}.valueOf() is not a primitive, so toString fallback used => 2 - Number('[object Object]'), NaN
+'a'       // NaN    `ToPrimitive` passed 'number' hint), Number('a'), NaN
+''        // 0      `ToPrimitive` passed 'number' hint), Number(''), 0
+'-1'      // -1     `ToPrimitive` passed 'number' hint), Number('-1'), -1
+{}        // NaN    `ToPrimitive` passed 'number' hint', `valueOf` returns an object, so falls back to `toString`, Number('[Object object]'), NaN
 1 + 'a'   // '1a'    Both are primitives, one is a string, String(1) + 'a'
 1 + {}    // '1[object Object]'    One primitive, one object, `ToPrimitive` passed no hint, meaning conversion to string will occur, one of the operands is now a string, String(1) + String({}), `1[object Object]`
[] + []    // ''     Two objects, `ToPrimitive` passed no hint, String([]) + String([]), '' (empty string)
 1 - 'a'   // NaN    Both are primitives, one is a string, `ToPrimitive` passed 'number' hint, 1-Number('a'), 1-NaN, NaN
 1 - {}    // NaN    One primitive, one is an object, `ToPrimitive` passed 'number' hint, `valueOf` returns object, so falls back to `toString`, 1-Number([object Object]), 1-NaN, NaN
[] - []    // 0      Two objects, `ToPrimitive` passed 'number' hint => `valueOf` returns array instance, so falls back to `toString`, Number('')-Number(''), 0-0, 0

নোট করুন যে Dateঅন্তর্নিহিত অবজেক্টটি অনন্য, কারণ এটি কেবলমাত্র ডিফল্ট @@toPrimitiveপদ্ধতিটিকে ওভাররাইড করার জন্য অন্তর্নিহিত , যেখানে ডিফল্ট ইঙ্গিতটি 'স্ট্রিং' ('সংখ্যার পরিবর্তে') বলে মনে করা হয়। এটি থাকার কারণ Date, প্রোগ্রামারটির সুবিধার্থে উদাহরণগুলি তাদের সংখ্যাসূচক মানের পরিবর্তে ডিফল্টরূপে পঠনযোগ্য স্ট্রিংগুলিতে অনুবাদ করা উচিত। আপনি @@toPrimitiveনিজের জিনিসগুলিতে ব্যবহার করে ওভাররাইড করতে পারেন Symbol.toPrimitive

নিম্নলিখিত গ্রিডটি বিমূর্ত সমতা অপারেটর ( ==) ( উত্স ) এর জন্য জবরদস্তির ফলাফলগুলি দেখায় :

এখানে চিত্র বর্ণনা লিখুন

এছাড়াও দেখুন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.