জাভাস্ক্রিপ্টে alচ্ছিক পরামিতিগুলি পরিচালনা করা


127

আমার একটি স্থির জাভাস্ক্রিপ্ট ফাংশন রয়েছে যা 1, 2 বা 3 পরামিতি নিতে পারে:

function getData(id, parameters, callback) //parameters (associative array) and callback (function) are optional

আমি জানি যে প্রদত্ত প্যারামিটারটি অপরিবর্তিত থাকলে আমি সর্বদা পরীক্ষা করতে পারি, তবে কীভাবে পাস হবে তা প্যারামিটার বা কলব্যাক ছিল কিনা আমি কীভাবে জানব?

এটি করার সর্বোত্তম উপায় কী?


এতে কী কী পাস হতে পারে তার উদাহরণ:

1:

getData('offers');

2:

var array = new Array();
array['type']='lalal';
getData('offers',array);

3:

var foo = function (){...}
getData('offers',foo);

4:

getData('offers',array,foo);

2
আপনি কি পাস হতে পারে একটি উদাহরণ দেখাতে পারেন?
জেমস ব্ল্যাক

উত্তর:


163

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

function getData (id, parameters, callback) {
  if (arguments.length == 2) { // if only two arguments were supplied
    if (Object.prototype.toString.call(parameters) == "[object Function]") {
      callback = parameters; 
    }
  }
  //...
}

আপনি এইভাবে আর্গুমেন্ট অবজেক্টটিও ব্যবহার করতে পারেন:

function getData (/*id, parameters, callback*/) {
  var id = arguments[0], parameters, callback;

  if (arguments.length == 2) { // only two arguments supplied
    if (Object.prototype.toString.call(arguments[1]) == "[object Function]") {
      callback = arguments[1]; // if is a function, set as 'callback'
    } else {
      parameters = arguments[1]; // if not a function, set as 'parameters'
    }
  } else if (arguments.length == 3) { // three arguments supplied
      parameters = arguments[1];
      callback = arguments[2];
  }
  //...
}

আপনি যদি আগ্রহী হন তবে জাভাস্ক্রিপ্টে পদ্ধতি ওভারলোডিং অনুকরণ করার কৌশল সম্পর্কে জন রেসিগের এই নিবন্ধটি একবার দেখুন ।


কেন অবজেক্ট.প্রোটোটাইপ.টোস্ট্রিং.কম (পরামিতি) == "[অবজেক্ট ফাংশন]" এবং টাইপফ (পরামিতি) === 'ফাংশন' ব্যবহার করবেন না? তাদের মধ্যে কিছু গুরুত্বপূর্ণ পার্থক্য আছে? PS আপনি যে নিবন্ধটি উল্লেখ করেছেন তা পরবর্তীকালের ব্যবহার বলে মনে হচ্ছে
টোমর ক্যাগান

@ টোমেনকাগান আমি মনে করি এটি পছন্দ হিসাবে বিবেচিত (ইশ)। এই প্রশ্নের অধীনে বিষয়টিতে কিছু ভাল উত্তর / মন্তব্য রয়েছে ।
ফিলিইইইইপ্প

75

এর - এর অর্থ হ'ল আপনি আপনার ফাংশনটি যুক্তি দিয়ে সন্ধান করছেন যা সঠিক ক্রমে নয় ... যা আমি সুপারিশ করব না।

আমি পরিবর্তে আপনার ফাংশনটিতে কোনও বস্তুকে খাওয়ানোর পরামর্শ দেব:

function getData( props ) {
    props = props || {};
    props.params = props.params || {};
    props.id = props.id || 1;
    props.callback = props.callback || function(){};
    alert( props.callback )
};

getData( {
    id: 3,
    callback: function(){ alert('hi'); }
} );

উপকারিতা:

  • যুক্তি আদেশের জন্য আপনাকে অ্যাকাউন্ট করতে হবে না
  • আপনাকে টাইপ চেকিং করতে হবে না
  • ডিফল্ট মানগুলি সংজ্ঞায়িত করা সহজ কারণ কোনও ধরণের চেকিংয়ের প্রয়োজন হয় না
  • মাথা ব্যথা কম কল্পনা করুন আপনি যদি চতুর্থ যুক্তি যুক্ত করেন তবে প্রতিবার আপনার টাইপ পরীক্ষা করে আপডেট করতে হবে এবং চতুর্থ বা পর পরের কাজগুলিও যদি হয়?

অপূর্ণতা:

  • রিফ্যাক্টর কোড করার সময়

আপনার যদি বিকল্প না থাকে তবে কোনও বস্তু আসলেই কোনও ফাংশন কিনা তা সনাক্ত করতে আপনি কোনও ফাংশন ব্যবহার করতে পারেন (শেষ উদাহরণটি দেখুন)।

দ্রষ্টব্য: এটি কোনও ফাংশন সনাক্ত করার উপযুক্ত উপায়:

function isFunction(obj) {
    return Object.prototype.toString.call(obj) === "[object Function]";
}

isFunction( function(){} )

"কিছু ইএস বাগের কারণে এটি 99% সময় কাজ করবে।" আপনি আরও ব্যাখ্যা করতে পারেন? কেন এটি ভুল হতে পারে?
জেডি।

আমি একটি ফাংশন সনাক্ত করতে সঠিক কোড যুক্ত করেছি। আমি বিশ্বাস করি যে বাগটি এখানে রয়েছে: বাগস.সেমাস্ক্রিপ্ট.আর্গ
স্পিকেট /

আমি আপনাকে কেবল একটি অবজেক্ট খাওয়ানোর পরামর্শ দেব। যদি তা না হয় তবে সিএমএসের পদ্ধতিটি ব্যবহার করুন।
মধ্যস্থতা ওমুরিলিভ

ওহ ... জঘন্য ... ঠিক একই ধারণা পোস্ট করেছেন।
আরনিস ল্যাপসা

1
অন্য একটি সম্ভাব্য অসুবিধা হল বুদ্ধিমানের অভাব। আমি এটিকে বড় বিষয় হিসাবে বিবেচনা করি না, তবে লক্ষ্য করা উচিত।
এডিন

2

সুতরাং দ্বিতীয় প্যারামিটারটি অ্যারে বা ফাংশন কিনা তা নির্ধারণ করতে টাইপ অফ অপারেটরটি ব্যবহার করুন।

এটি কিছু পরামর্শ দিতে পারে: http://www.planetpdf.com/developer/article.asp?ContentID=testing_for_object_types_in_ja

এটি কাজ বা হোম ওয়ার্ক কিনা তা আমি নিশ্চিত নই, তাই এই মুহুর্তে আপনাকে উত্তর দিতে চাই না, তবে টাইপফ আপনাকে এটি নির্ধারণে সহায়তা করবে।


2

আপনার প্রাপ্ত পরামিতিগুলির ধরণটি পরীক্ষা করা উচিত। সম্ভবত আপনার argumentsঅ্যারে ব্যবহার করা উচিত যেহেতু দ্বিতীয় প্যারামিটারটি কখনও কখনও 'পরামিতি' এবং কখনও কখনও 'কলব্যাক' এবং পরামিতিগুলির নামকরণ বিভ্রান্তিকর হতে পারে।


2

আমি জানি এটি একটি বেশ পুরানো প্রশ্ন, তবে আমি সম্প্রতি এটি নিয়ে কাজ করেছি। আপনি এই সমাধানটি সম্পর্কে কী ভাবেন তা আমাকে জানান।

আমি একটি ইউটিলিটি তৈরি করেছি যা আমাকে দৃ strongly়তার সাথে যুক্তিগুলি টাইপ করতে এবং সেগুলি alচ্ছিক হতে দেয়। আপনি মূলত একটি প্রক্সিতে আপনার ফাংশনটি মোড়েন। আপনি যদি কোনও যুক্তি এড়িয়ে যান তবে এটি অপরিজ্ঞাত । এটা তোলে করা বিচিত্র পেতে পারেন যদি একাধিক আছে ঐচ্ছিক অধিকার পরবর্তী প্রতিটি অন্যান্য একই ধরনের সঙ্গে আর্গুমেন্ট। (কাস্টম আর্গুমেন্ট চেক করার জন্য প্রকারের পরিবর্তে ফাংশনগুলি পাশ করার বিকল্প রয়েছে পাশাপাশি প্রতিটি প্যারামিটারের জন্য ডিফল্ট মান উল্লেখ করা যেতে পারে))

বাস্তবায়নটি দেখতে এটির মতো:

function displayOverlay(/*message, timeout, callback*/) {
  return arrangeArgs(arguments, String, Number, Function, 
    function(message, timeout, callback) {
      /* ... your code ... */
    });
};

স্পষ্টতার জন্য, এখানে যা চলছে তা এখানে:

function displayOverlay(/*message, timeout, callback*/) {
  //arrangeArgs is the proxy
  return arrangeArgs(
           //first pass in the original arguments
           arguments, 
           //then pass in the type for each argument
           String,  Number,  Function, 
           //lastly, pass in your function and the proxy will do the rest!
           function(message, timeout, callback) {

             //debug output of each argument to verify it's working
             console.log("message", message, "timeout", timeout, "callback", callback);

             /* ... your code ... */

           }
         );
};

আপনি আমার গিটহাবের সংগ্রহস্থলে অ্যারেঞ্জআর্গস প্রক্সি কোডটি দেখতে পারেন:

https://github.com/joelvh/Sysmo.js/blob/master/sysmo.js

সংগ্রহস্থল থেকে অনুলিপি করা কিছু মন্তব্য সহ ইউটিলিটি ফাংশনটি এখানে:

/*
 ****** Overview ******
 * 
 * Strongly type a function's arguments to allow for any arguments to be optional.
 * 
 * Other resources:
 * http://ejohn.org/blog/javascript-method-overloading/
 * 
 ****** Example implementation ******
 * 
 * //all args are optional... will display overlay with default settings
 * var displayOverlay = function() {
 *   return Sysmo.optionalArgs(arguments, 
 *            String, [Number, false, 0], Function, 
 *            function(message, timeout, callback) {
 *              var overlay = new Overlay(message);
 *              overlay.timeout = timeout;
 *              overlay.display({onDisplayed: callback});
 *            });
 * }
 * 
 ****** Example function call ******
 * 
 * //the window.alert() function is the callback, message and timeout are not defined.
 * displayOverlay(alert);
 * 
 * //displays the overlay after 500 miliseconds, then alerts... message is not defined.
 * displayOverlay(500, alert);
 * 
 ****** Setup ******
 * 
 * arguments = the original arguments to the function defined in your javascript API.
 * config = describe the argument type
 *  - Class - specify the type (e.g. String, Number, Function, Array) 
 *  - [Class/function, boolean, default] - pass an array where the first value is a class or a function...
 *                                         The "boolean" indicates if the first value should be treated as a function.
 *                                         The "default" is an optional default value to use instead of undefined.
 * 
 */
arrangeArgs: function (/* arguments, config1 [, config2] , callback */) {
  //config format: [String, false, ''], [Number, false, 0], [Function, false, function(){}]
  //config doesn't need a default value.
  //config can also be classes instead of an array if not required and no default value.

  var configs = Sysmo.makeArray(arguments),
      values = Sysmo.makeArray(configs.shift()),
      callback = configs.pop(),
      args = [],
      done = function() {
        //add the proper number of arguments before adding remaining values
        if (!args.length) {
          args = Array(configs.length);
        }
        //fire callback with args and remaining values concatenated
        return callback.apply(null, args.concat(values));
      };

  //if there are not values to process, just fire callback
  if (!values.length) {
    return done();
  }

  //loop through configs to create more easily readable objects
  for (var i = 0; i < configs.length; i++) {

    var config = configs[i];

    //make sure there's a value
    if (values.length) {

      //type or validator function
      var fn = config[0] || config,
          //if config[1] is true, use fn as validator, 
          //otherwise create a validator from a closure to preserve fn for later use
          validate = (config[1]) ? fn : function(value) {
            return value.constructor === fn;
          };

      //see if arg value matches config
      if (validate(values[0])) {
        args.push(values.shift());
        continue;
      }
    }

    //add a default value if there is no value in the original args
    //or if the type didn't match
    args.push(config[2]);
  }

  return done();
}

2

আমি আপনাকে আরগুজেএস ব্যবহার করার পরামর্শ দিচ্ছি

আপনি কেবল আপনার ফাংশনটি এইভাবে টাইপ করতে পারেন:

function getData(){
  arguments = __({id: String, parameters: [Object], callback: [Function]})

  // and now access your arguments by arguments.id,
  //          arguments.parameters and arguments.callback
}

আমি আপনার উদাহরণ দ্বারা বিবেচনা করেছি যে আপনি চান আপনার idপরামিতি একটি স্ট্রিং, ডান? এখন, getDataএকটি প্রয়োজন String idএবং বিকল্পগুলি গ্রহণ করছে Object parametersএবং Function callback। আপনার পোস্ট করা সমস্ত ব্যবহারের ক্ষেত্রে প্রত্যাশার মতো কাজ করবে।



1

আপনি কি বলছেন আপনার কাছে এই জাতীয় কল আসতে পারে: getData (আইডি, পরামিতি); getData (আইডি, কলব্যাক)?

এক্ষেত্রে আপনি অবশ্যই অবস্থানের উপর নির্ভর করতে পারবেন না এবং আপনাকে টাইপ: গেটটাইপ () এবং তারপরে প্রয়োজনীয় গেটটাইম () প্রয়োজন হলে বিশ্লেষণের উপর নির্ভর করতে হবে

প্রশ্নে থাকা প্যারামিটারটি একটি অ্যারে বা কোনও ফাংশন কিনা তা পরীক্ষা করুন।


0

আমি মনে করি আপনি এখানে টাইপফ () ব্যবহার করতে চান:

function f(id, parameters, callback) {
  console.log(typeof(parameters)+" "+typeof(callback));
}

f("hi", {"a":"boo"}, f); //prints "object function"
f("hi", f, {"a":"boo"}); //prints "function object"

0

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

function getData(id, opt){
    var data = voodooMagic(id, opt.parameters);
    if (opt.callback!=undefined)
      opt.callback.call(data);
    return data;         
}

getData(5, {parameters: "1,2,3", callback: 
    function(){for (i=0;i<=1;i--)alert("FAIL!");}
});

0

আমার ধারণা এটি স্ব-ব্যাখ্যামূলক উদাহরণ হতে পারে:

function clickOn(elem /*bubble, cancelable*/) {
    var bubble =     (arguments.length > 1)  ? arguments[1] : true;
    var cancelable = (arguments.length == 3) ? arguments[2] : true;

    var cle = document.createEvent("MouseEvent");
    cle.initEvent("click", bubble, cancelable);
    elem.dispatchEvent(cle);
}

-5

আপনি কি ফাংশনটি ওভাররাইড করতে পারেন? এটি কি কাজ করবে না:

function doSomething(id){}
function doSomething(id,parameters){}
function doSomething(id,parameters,callback){}

8
না, এটি কাজ করবে না। আপনি কোনও ত্রুটি পাবেন না তবে জাভাস্ক্রিপ্ট সর্বদা আপনার সংজ্ঞায়িত সর্বশেষতম ফাংশনটি ব্যবহার করবে।
জেডি।

6
কি দারুন. আমি ভেবেছিলাম তুমি পাগল হয়ে গেছ। আমি ঠিক এটি পরীক্ষা করেছি। তুমি ঠিক. আমার পৃথিবী আমার জন্য কিছুটা বদলেছে changed আমি মনে করি আমার কাছে প্রযোজনায় এর মতো কিছু নেই তা নিশ্চিত করার জন্য আজ আমার কাছে অনেক জাভাস্ক্রিপ্ট রয়েছে। মন্তব্যের জন্য ধন্যবাদ. আমি আপনাকে একটি +1 দিয়েছি।
জে.হেন্দ্রিক্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.