জাভাস্ক্রিপ্টের এই স্নিপেটগুলি উভয়ই একটি ত্রুটির মুখোমুখি হওয়া সত্ত্বেও কেন আলাদা আচরণ করে?


107

var a = {}
var b = {}

try{
  a.x.y = b.e = 1 // Uncaught TypeError: Cannot set property 'y' of undefined
} catch(err) {
  console.error(err);
}
console.log(b.e) // 1

var a = {}
var b = {}

try {
  a.x.y.z = b.e = 1 // Uncaught TypeError: Cannot read property 'y' of undefined
} catch(err) {
  console.error(err);
}

console.log(b.e) // undefined


3
@ নিনা স্কলজ: আমি বুঝতে পারছি না। কোনও সিনট্যাক্স ত্রুটি নেই; সুতরাং আমি ধরে নিই b.z = 1এবং b.e = 1প্রথমে চালিত করব (উপর ভিত্তি করে ডান-অ্যাসোসিয়েটিভিটি দেওয়া হবে =), তারপরে a.x.y.z = ...মৃত্যুদন্ড কার্যকর এবং ব্যর্থ হবে; কেন bএক ক্ষেত্রে অ্যাসাইনমেন্ট পাস হয় কিন্তু অন্য ক্ষেত্রে হয় না?
আমাদান

3
@ নিনা স্কলজ আমরা সম্মত হই যে সম্পত্তিটির yঅস্তিত্ব নেই a.x; তবে উভয় ক্ষেত্রেই এটি সত্য। এটি দ্বিতীয় ক্ষেত্রে ডান-হাতের কার্যনির্বাহীকরণটিকে কেন প্রথম আটকে দেয় না? ফাঁসির আদেশে আলাদা কী? (আমি সিন্ট্যাক্স ত্রুটির কথা উল্লেখ করেছি কারণ সিনট্যাক্স ত্রুটির সময়কাল একটি রানটাইম ত্রুটির তুলনায় খুব আলাদা))
আমদান

@ আমদান চলমান কোডের পরে আপনি ত্রুটি পেয়ে যাবেন, এবং মানটি দেখতে আবার ভেরিয়েবল নামের চেয়ে ব্যবহারের চেয়ে
কোড ম্যানিয়াক

2
এই বর্ণনা পেলাম জাভাস্ক্রিপ্ট নিয়োগ প্রক্রিয়াটিতে ecma-international.org/ecma-262/5.1/#sec-11.13
সলোমন ট্যাম

2
এটি তাত্ত্বিক দৃষ্টিকোণ থেকে আকর্ষণীয়, তবে এটি অবশ্যই অপ্রত্যাশিত আচরণের বিভাগের "এই কারণেই আপনি এর মতো কোডটি লেখেন না" এর অধীনে চলে আসে।
জন মন্টগোমেরি

উত্তর:


152

আসলে, আপনি যদি ত্রুটি বার্তাটি সঠিকভাবে পড়ে থাকেন তবে কেস 1 এবং কেস 2 বিভিন্ন ত্রুটি ফেলে দেয়।

কেস a.x.y:

সংজ্ঞায়িত 'y' এর সম্পত্তি সেট করা যায় না

কেস a.x.y.z:

অপরিজ্ঞাতকৃত সম্পত্তি 'y' পড়তে পারে না

আমি অনুমান করি সহজ ইংরেজিতে ধাপে ধাপে কার্যকর করার মাধ্যমে এটি বর্ণনা করা ভাল।

মামলা 1

// 1. Declare variable `a`
// 2. Define variable `a` as {}
var a = {}

// 1. Declare variable `b`
// 2. Define variable `b` as {}
var b = {}

try {

  /**
   *  1. Read `a`, gets {}
   *  2. Read `a.x`, gets undefined
   *  3. Read `b`, gets {}
   *  4. Set `b.z` to 1, returns 1
   *  5. Set `a.x.y` to return value of `b.z = 1`
   *  6. Throws "Cannot **set** property 'y' of undefined"
   */
  a.x.y = b.z = 1
  
} catch(e){
  console.error(e.message)
} finally {
  console.log(b.z)
}

মামলা 2

// 1. Declare variable `a`
// 2. Define variable `a` as {}
var a = {}

// 1. Declare variable `b`
// 2. Define variable `b` as {}
var b = {}

try {

  /**
   *  1. Read `a`, gets {}
   *  2. Read `a.x`, gets undefined
   *  3. Read `a.x.y`, throws "Cannot **read** property 'y' of undefined".
   */
  a.x.y.z = b.z = 1
  
} catch(e){
  console.error(e.message)
} finally {
  console.log(b.z)
}

মন্তব্যে, সলোমন ট্যাম অ্যাসাইনমেন্ট অপারেশন সম্পর্কে এই ইসিএমএ ডকুমেন্টেশনটি পেয়েছেন ।


57

কোন অংশটি কার্যকর করা হয় তা দেখার জন্য যখন আপনি বন্ধনী স্বরলিপিটির ভিতরে কমা অপারেটরটি ব্যবহার করেন তখন অপারেশনের ক্রম আরও স্পষ্ট হয়:

var a = {}
var b = {}

try{
 // Uncaught TypeError: Cannot set property 'y' of undefined
  a
    [console.log('x'), 'x']
    [console.log('y'), 'y']
    = (console.log('right hand side'), b.e = 1);
} catch(err) {
  console.error(err);
}
console.log(b.e) // 1

var a = {}
var b = {}

try {
  // Uncaught TypeError: Cannot read property 'y' of undefined
  a
    [console.log('x'), 'x']
    [console.log('y'), 'y']
    [console.log('z'), 'z']
    = (console.log('right hand side'), b.e = 1);
} catch(err) {
  console.error(err);
}

console.log(b.e) // undefined

এ খুঁজছি বৈশিষ্ট :

উত্পাদন AssignmentExpression : LeftHandSideExpression = AssignmentExpressionনিম্নলিখিত হিসাবে মূল্যায়ন করা হয়:

  1. বামহ্যান্ডসাইডএক্সপ্রেসেশনকে মূল্যায়নের ফলাফল হিসাবে lref হওয়া যাক।

  2. আসুন AssignmentExpression মূল্যায়নের ফলাফল হতে দিন।

  3. চলুন GetValue(rref)

  4. সিন্ট্যাক্সেরর ব্যতিক্রম নিক্ষেপ করুন যদি ... (অপ্রাসঙ্গিক)

  5. কল করুন PutValue(lref, rval)

PutValueযা নিক্ষেপ করে TypeError:

  1. ও হোক ToObject(base)

  2. [[CanPut]]আর্গুমেন্ট পি দিয়ে ও এর অভ্যন্তরীণ পদ্ধতি কল করার ফলাফলটি যদি ভুল হয় তবে তা ঠিক

    ক। যদি থ্রোটি সত্য হয় তবে টাইপআরর ব্যতিক্রম নিক্ষেপ করুন।

এর সম্পত্তি হিসাবে কিছুই বরাদ্দ করা যায় না undefined- এর [[CanPut]]অভ্যন্তরীণ পদ্ধতি undefinedসর্বদা ফিরে আসবে false

অন্য কথায়: ব্যাখ্যাকারী বাম দিকে parses ডানদিকে parses তারপর, তারপর একটি ত্রুটি নিক্ষেপ করে যদি বাম-হাতের সম্পত্তিটি বরাদ্দ করা না যায়।

যখন তুমি কর

a.x.y = b.e = 1

বাম হাতটি সফলভাবে পার্স করা হয় যতক্ষণ না PutValueবলা হয়; .xসম্পত্তি যে মূল্যায়িত করে undefinedতা ডান-হাত পার্স হওয়ার পরে বিবেচনা করা হয় না। দোভাষী এটিকে "অপরিজ্ঞাপিত" y "এর সম্পত্তিটির জন্য কিছু মূল্য নির্ধারণ করুন এবং undefinedকেবল ভিতরে rows ুকিয়ে দেওয়ার সম্পত্তি হিসাবে বরাদ্দ করেন PutValue

বিপরীতে:

a.x.y.z = b.e = 1

দোভাষী কখনই সেই zসম্পত্তিটিতে অর্পণ করার চেষ্টা করে না এমন স্থানে পৌঁছায় না কারণ এটি প্রথমে a.x.yএকটি মানকে সমাধান করতে হবে । যদি a.x.yকোনও মান থেকে সমাধান করা হয় (এমনকি undefined) তবে এটি ঠিক হবে - PutValueউপরের মতো একটি ত্রুটি ভিতরে ফেলে দেওয়া হবে । কিন্তু অ্যাক্সেস a.x.y একটি ত্রুটি ছুড়ে ফেলে, কারণ সম্পত্তি yঅ্যাক্সেস করা যায় না undefined


20
দুর্দান্ত কমা অপারেটর ট্রিক - কখনও সেভাবে ব্যবহার করার কথা ভাবেন নি (অবশ্যই কেবলমাত্র ডিবাগিংয়ের জন্য)!
ecraig12345

2
এস / পার্স / মূল্যায়ন /
বার্গি

3

নিম্নলিখিত কোড বিবেচনা করুন:

var a = {};
a.x.y = console.log("evaluating right hand side"), 1;

ধাপের রুক্ষ রূপরেখা চালানো কোড হিসাবে অনুসরণ করে প্রয়োজনীয় সুত্র :

  1. বাম হাতের মূল্যায়ন করুন। দুটি বিষয় মনে রাখতে হবে:
    • একটি এক্সপ্রেশন মূল্যায়ন এক্সপ্রেশন এর মান পাওয়ার সমান নয়।
    • প্রপার্টি অ্যাক্সেসর রেফের মূল্যায়ন যেমন বেস মান (অপরিজ্ঞাত) এবং রেফারেন্সকৃত নাম ( ) সমন্বিত a.x.yএকটি রেফারেন্স রেফ প্রদান করে returnsa.xy
  2. ডান হাতের মূল্যায়ন করুন।
  3. পদক্ষেপ 2 এ প্রাপ্ত ফলাফলের মানটি পান।
  4. পদক্ষেপ 1 এ প্রাপ্ত রেফারেন্সের মানটি ধাপ 3 এ প্রাপ্ত মান হিসাবে নির্ধারণ করুন yঅর্থের সাথে অপরিজ্ঞাতকৃত সম্পত্তি সেট করুন । এটি একটি টাইপররর ব্যতিক্রম রেফ ফেলে দেওয়ার কথা ।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.