چرا !{}[true] در جاوااسکریپت به true ارزیابی میشود؟
{}[true] برابر با [true] است و ![true] باید false باشد.
پس چرا !{}[true] به true ارزیابی میشود؟
پاسخ شماره ۱
من معتقدم که دلیل آن این است که {}[true] ساده به عنوان یک بلوک دستور خالی (نه یک شیء لغتنامهای) تجزیه میشود که به دنبال آن یک آرایه حاوی true وجود دارد، که true است.
از سوی دیگر، اعمال عملگر ! باعث میشود پارسر {} را به عنوان یک شیء literal تفسیر کند، بنابراین {}[true] بعدی به یک دسترسی به عضو تبدیل میشود که undefined را برمیگرداند، و !{}[true] واقعاً true است (چون !undefined برابر با true است).
پاسخ شماره ۲
زیرا {}[true] مقدار true را برنمیگرداند، بلکه undefined را برمیگرداند، و undefined به عنوان false ارزیابی میشود:
http://jsfiddle.net/67GEu/
'use strict';
var b = {}[true];
alert(b); // undefined
b = !{}[true];
alert(b); // true
پاسخ شماره ۳
زیرا
{}[true]
به undefined ارزیابی میشود، و !undefined برابر با true است.
از @schlingel:
true به عنوان کلید و {} به عنوان نقشه هش استفاده میشود. هیچ ویژگی با کلید true وجود ندارد، بنابراین undefined برگردانده میشود. نه اینکه undefined true باشد، همانطور که انتظار میرفت.
جلسه کنسول (Node.js [0.10.17]):
> {}[true]
undefined
> !{}[true]
true
> [true]
[ true ]
> ![true]
false
>
با این حال، در کنسول گوگل کروم:
> !{}[true]
true
پس، هیچ ناسازگاریای وجود ندارد. احتمالاً شما از نسخه قدیمی ماشین مجازی جاوااسکریپت استفاده میکنید. برای کسانی که به شواهد بیشتری نیاز دارند:
بهروزرسانی
با فایرفاکس، همچنین به true ارزیابی میشود:
پاسخ شماره ۴
دلیل سردرگمی ناشی از سوءتفاهم در مورد ادعای اول شما است:
{}[true] برابر است با [true]
چیزی که هنگام اجرای آن میبینید نتیجه یک ابهام است. جاوااسکریپت مجموعهای تعریفشده از قوانین دارد که چگونه با ابهامات مانند این برخورد کند، و در این مورد، آنچه شما به عنوان یک دستور واحد میبینید را به دو دستور جداگانه تقسیم میکند.
پس جاوااسکریپت کد بالا را به عنوان دو دستور جداگانه میبیند: ابتدا یک {} وجود دارد، و سپس یک [true] کاملاً جداگانه. دستور دوم همان چیزی است که نتیجه [true] را به شما میدهد. دستور اول {} عملاً کاملاً نادیده گرفته میشود.
شما میتوانید این را با امتحان کردن موارد زیر ثابت کنید:
({}[true])
مثلاً کل چیز را در پرانتز قرار دادن برای مجبور کردن مفسر به خواندن آن بهعنوان یک دستور واحد.
حال خواهید دید که مقدار واقعی عبارت شما تعریفنشده است. (این همچنین به ما کمک خواهد کرد تا بعداً بخش بعدی را درک کنیم)
حالا میدانیم که قسمت ابتدایی سؤال شما یک انحراف است، پس بیایید به قسمت نهایی سؤال برویم:
پس چرا !{}[true] به true ارزیابی میشود؟
اینجا، ما همان عبارت را داریم، اما با یک ! که در جلوی آن اضافه شده است.
در این مورد، قوانین جاوااسکریپت به آن میگویند که کل آن را به عنوان یک دستور واحد ارزیابی کند.
به آنچه هنگام قرار دادن عبارت قبلی در براکتها اتفاق افتاد اشاره کنید؛ ما undefined را دریافت کردیم. این بار، ما اساساً همان کار را انجام میدهیم، اما یک ! جلوی آن قرار میدهیم. بنابراین کد شما میتواند به صورت سادهشده به !undefined باشد، که برابر با true است.
امیدوارم این کمی توضیح بدهد.
این یک موجود پیچیده است، اما درسی که باید از اینجا گرفت این است که هنگام ارزیابی عبارات خود در کنسول، از کروشه استفاده کنید تا از نتایج کاذب مانند این جلوگیری شود.
پاسخ شماره ۵
{}[true] برابر با undefined است. برای فهمیدن این موضوع این را بنویسید:
a = {};
a[true] === undefined // true
یا به سادگی:
({})[true] === undefined // true
ما میدانیم که !undefined برابر با true است.
از پاسخ @Benjamin Gruenbaum:
ابزارهای توسعهدهنده کروم کارهای زیر را انجام میدهند:
try {
if (injectCommandLineAPI && inspectedWindow.console) {
inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {\n" + expression + "\n}";
}
var result = evalFunction.call(object, expression);
if (objectGroup === "console")
this._lastResult = result;
return result;
}
finally {
if (injectCommandLineAPI && inspectedWindow.console)
delete inspectedWindow.console._commandLineAPI;
}
بنابراین اساساً، این یک
callروی شیء با عبارت انجام میدهد. عبارت به صورت:
with ((window && window.console && window.console._commandLineAPI) || {}) {
{}+{};// <-- This is your code
}
بنابراین، همانطور که میبینید، عبارت مستقیماً ارزیابی میشود، بدون پرانتزهای اطراف آن.
اطلاعات بیشتر را میتوان در این سؤال پیدا کرد.
پاسخ شماره ۶
جوابهای اینجا خوب هستند، در اینجا یک تحلیل به صورت شبهکد آمده است:
{}[‘whatever’]=بلوک خالی، NewArray(‘whatever’)=NewArray(‘whatever’){}[true]=بلوک خالی، NewArray(true)=NewArray(true)!{}['Anything']= LogicalNOT(convertToBool(NewObject.Anything)) = LogicalNOT(convertToBool(undefined)) = LogicalNOT(false) = true({}[‘whatever’])=گروهبندی(NewObject.whatever)=گروهبندی(undefined)=undefined

