গতিশীলভাবে ফাংশন প্যারামিটারের নাম / মান কীভাবে পাবেন?


300

গতিশীলভাবে কোনও ফাংশনটির প্যারামিটারের নাম পাওয়ার কোনও উপায় আছে কি?

আসুন বলি যে আমার ফাংশনটি এমন দেখাচ্ছে:

function doSomething(param1, param2, .... paramN){
   // fill an array with the parameter name and value
   // some other code 
}

এখন, আমি কীভাবে প্যারামিটারের নামগুলি এবং তাদের মানগুলি ফাংশনের ভিতরে থেকে একটি অ্যারে রূপে পেতে পারি?


সবাইকে ধন্যবাদ আশেপাশে অনুসন্ধান করার পরে, আমি SO- তে সমাধান খুঁজে পেয়েছি: স্ট্যাকওভারফ্লো / প্রশ্ন / 914968/… এটি পরম নামটি পাওয়ার জন্য একটি রেজেক্স ব্যবহার করে। এটি সম্ভবত সেরা সমাধান নয়, তবে এটি আমার পক্ষে কাজ করে।
বিকাসদে

8
আসুন এবং উত্তর বন্ধু হিসাবে এটি চিহ্নিত করুন। কোন নতুন উত্তর আসছে না।
ম্যাথু গ্রেভস

function doSomething(...args) { /*use args*/}
কর্ক

উত্তর:


322

নিম্নলিখিত ফাংশনটি যে কোনও কার্যক্রমে প্যারামিটার নামের একটি অ্যারে প্রদান করবে।

var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var ARGUMENT_NAMES = /([^\s,]+)/g;
function getParamNames(func) {
  var fnStr = func.toString().replace(STRIP_COMMENTS, '');
  var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
  if(result === null)
     result = [];
  return result;
}

ব্যবহারের উদাহরণ:

getParamNames(getParamNames) // returns ['func']
getParamNames(function (a,b,c,d){}) // returns ['a','b','c','d']
getParamNames(function (a,/*b,c,*/d){}) // returns ['a','d']
getParamNames(function (){}) // returns []

সম্পাদনা করুন :

ES6 এর উদ্ভাবনের সাথে এই ফাংশনটি ডিফল্ট পরামিতিগুলি দ্বারা আরও ছড়িয়ে দেওয়া যায়। এখানে একটি দ্রুত হ্যাক যা বেশিরভাগ ক্ষেত্রে কাজ করা উচিত:

var STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/mg;

আমি বেশিরভাগ ক্ষেত্রে বলি কারণ এমন কিছু জিনিস রয়েছে যা এটির ট্রিপ করবে

function (a=4*(5/3), b) {} // returns ['a']

সম্পাদন করা : আমি আরও লক্ষ্য করি যে বিকাশদে একটি অ্যারেতেও প্যারামিটার মানগুলি চায়। এটি ইতিমধ্যে একটি স্থানীয় ভেরিয়েবল নামের আর্গুমেন্টে সরবরাহ করা হয়েছে।

https://developer.mozilla.org/en-US/docs/Web/ জাভা স্ক্রিপ্ট / রেফারেন্স / ফাংশন_আর_ফাংশন_স্কোপ / বিভাগ থেকে অংশগুলি :

আর্গুমেন্ট অবজেক্ট কোনও অ্যারে নয়। এটি একটি অ্যারের অনুরূপ, তবে দৈর্ঘ্য ব্যতীত কোনও অ্যারের বৈশিষ্ট্য নেই। উদাহরণস্বরূপ, এটিতে পপ পদ্ধতি নেই। তবে এটি একটি বাস্তব অ্যারে রূপান্তর করা যেতে পারে:

var args = Array.prototype.slice.call(arguments);

যদি অ্যারে জেনেরিকগুলি উপলভ্য থাকে তবে তার পরিবর্তে কেউ নিম্নলিখিতটি ব্যবহার করতে পারেন:

var args = Array.slice(arguments);

12
মনে রাখবেন যে মন্তব্য এবং স্থানগুলির কারণে এই সমাধানটি ব্যর্থ হতে পারে - উদাহরণস্বরূপ: var fn = function(a /* fooled you)*/,b){};ফলাফল হবে ["a", "/*", "fooled", "you"]
বুবারসন

1
কোনও যুক্তি না থাকলে খালি অ্যারে (নাল পরিবর্তে) ফেরত দেওয়ার জন্য আমি ফাংশনটি সংশোধন করেছি
বিটি

2
একটি রেজেক্স সংকলন করার জন্য একটি ব্যয় আছে, অতএব আপনি জটিল রেজেেক্সগুলি একাধিকবার সংকলন এড়াতে চান। এই কারণেই এটি ফাংশনের বাইরে করা হয়
জ্যাক অ্যালান

2
সংশোধন: পার্ল এটির অনুমতি দেয় এমন একটি / গুলি মডিফায়ারের সাথে রেজিक्सকে সংশোধন করতে চলেছিল। ' নিউলাইনও মেলতে পারে। / * * / এর ভিতরে মাল্টি-লাইন মন্তব্যের জন্য এটি প্রয়োজনীয়। জাভাস্ক্রিপ্ট রিজেক্স সক্রিয় করে / গুলি সংশোধককে অনুমতি দেয় না। [/ S / S] ব্যবহার করে মূল রেজেক্সটি নতুন লাইনের অক্ষরের সাথে মেলে। Sooo, পূর্ববর্তী মন্তব্য উপেক্ষা করুন।
tgoneil

1
@ এবং নোট আপনি আপনার পরীক্ষাগুলিতে রেজেক্স সংকলনটি অন্তর্ভুক্ত করছেন Note এগুলি কেবল একবার করা উচিত। আপনার ফলাফলগুলি ভিন্ন হতে পারে যদি আপনি পরীক্ষার পরিবর্তে পুনরায় সংকলনটি সেটআপ ধাপে নিয়ে যান
জ্যাক অ্যালান

123

নীচে অ্যাংুলারজেএস থেকে নেওয়া কোড দেওয়া হয়েছে যা নির্ভরতা ইঞ্জেকশন প্রক্রিয়াটির জন্য কৌশলটি ব্যবহার করে।

এবং এখানে এর একটি ব্যাখ্যা http://docs.angularjs.org/tutorial/step_05 থেকে নেওয়া হয়েছে

কৌণিকর নির্ভরতা ইনজেক্টর যখন নিয়ামকটি তৈরি করা হচ্ছে তখন আপনার নিয়ামককে পরিষেবা সরবরাহ করে। নির্ভরতা ইনজেক্টর পরিষেবাটি যে কোনও ট্রানজিটিভ নির্ভরশীলতা তৈরি করতেও যত্ন নেয় (পরিষেবাগুলি প্রায়ই অন্যান্য পরিষেবায় নির্ভর করে)।

নোট করুন যে আর্গুমেন্টের নামগুলি তাৎপর্যপূর্ণ, কারণ ইনজেকশনার নির্ভরতাগুলি অনুসন্ধান করতে এটি ব্যবহার করে।

/**
 * @ngdoc overview
 * @name AUTO
 * @description
 *
 * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
 */

var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(.+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
function annotate(fn) {
  var $inject,
      fnText,
      argDecl,
      last;

  if (typeof fn == 'function') {
    if (!($inject = fn.$inject)) {
      $inject = [];
      fnText = fn.toString().replace(STRIP_COMMENTS, '');
      argDecl = fnText.match(FN_ARGS);
      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
        arg.replace(FN_ARG, function(all, underscore, name){
          $inject.push(name);
        });
      });
      fn.$inject = $inject;
    }
  } else if (isArray(fn)) {
    last = fn.length - 1;
    assertArgFn(fn[last], 'fn')
    $inject = fn.slice(0, last);
  } else {
    assertArgFn(fn, 'fn', true);
  }
  return $inject;
}

40
স্পষ্টতই, শয়তানদের রক্ত ​​এবং শয়তানের রক্তের সাহায্যে @ পেইডনার্ড Regex ?! শীঘ্রই যদি জেএসে কোনও বিল্ট ইন থাকত তবে তা হবে না।
আদিত্য এমপি

6
@ পেইডনার্ড, তাই সত্য! শুধু ভাবলাম- কীভাবে এটি বাস্তবায়িত হয়? আসলে আমি
ফাংশননেম.টোস্ট্রিং

2
@ সাশা.সোচকা, জাভাস্ক্রিপ্টের সাথে প্যারামিটারের নাম পাওয়ার কোনও উপায় নেই বলে বুঝতে পেরে এখানে ঠিক একই জিনিসটি নিয়ে অবাক হয়ে এসেছিলেন
হার্ট সিমহা

14
মানুষের সময় বাঁচাতে, আপনি এই ফাংশনটি কৌনিক থেকে এই মাধ্যমে পেতে পারেন annotate = angular.injector.$$annotate
নিক

3
আমি আক্ষরিকভাবে এই বিষয়টির জন্য ইন্টারনেটে অনুসন্ধান করতে গিয়েছিলাম কারণ কৌতূহল ছিল যে কৌনিকটি কীভাবে এটি করেছিল ... এখন আমি জানি এবং আমি আরও জানি!
স্টিভেন হান্ট

40

এখানে একটি আপডেট সমাধান রয়েছে যা উপরে বর্ণিত সমস্ত প্রান্তের মামলাগুলি একটি কমপ্যাক্ট উপায়ে সমাধান করার চেষ্টা করে:

function $args(func) {  
    return (func + '')
      .replace(/[/][/].*$/mg,'') // strip single-line comments
      .replace(/\s+/g, '') // strip white space
      .replace(/[/][*][^/*]*[*][/]/g, '') // strip multi-line comments  
      .split('){', 1)[0].replace(/^[^(]*[(]/, '') // extract the parameters  
      .replace(/=[^,]+/g, '') // strip any ES6 defaults  
      .split(',').filter(Boolean); // split & filter [""]
}  

সংক্ষিপ্ত পরীক্ষার আউটপুট (সম্পূর্ণ পরীক্ষার কেসগুলি নীচে সংযুক্ত করা হয়):

'function (a,b,c)...' // returns ["a","b","c"]
'function ()...' // returns []
'function named(a, b, c) ...' // returns ["a","b","c"]
'function (a /* = 1 */, b /* = true */) ...' // returns ["a","b"]
'function fprintf(handle, fmt /*, ...*/) ...' // returns ["handle","fmt"]
'function( a, b = 1, c )...' // returns ["a","b","c"]
'function (a=4*(5/3), b) ...' // returns ["a","b"]
'function (a, // single-line comment xjunk) ...' // returns ["a","b"]
'function (a /* fooled you...' // returns ["a","b"]
'function (a /* function() yes */, \n /* no, */b)/* omg! */...' // returns ["a","b"]
'function ( A, b \n,c ,d \n ) \n ...' // returns ["A","b","c","d"]
'function (a,b)...' // returns ["a","b"]
'function $args(func) ...' // returns ["func"]
'null...' // returns ["null"]
'function Object() ...' // returns []


এক-লাইনের মন্তব্য উপস্থিত থাকলে এটি বিরতি দেয়। এটি ব্যবহার করে দেখুন: return (func+'') .replace(/[/][/].*$/mg,'') // strip single-line comments (line-ending sensitive, so goes first) .replace(/\s+/g,'') // remove whitespace
মার্লিন মরগান-গ্রাহাম

4
আপনি সম্ভবত প্রতিস্থাপন করা উচিত func + ''সঙ্গে Function.toString.call(func)কেস ফাংশন একটি কাস্টম .toString () বাস্তবায়ন হয়েছে যখন বিরুদ্ধে রক্ষা করতে।
পল গো

1
ফ্যাট অ্যারো =>.split(/\)[\{=]/, 1)[0]
ম্যাট

1
এটি ধ্বংসাত্মক বস্তুর (যেমন ({ a, b, c })) ডিস্ট্রাকচারের ভিতরে সমস্ত পরামিতিগুলিতে বিভক্ত করে । .split.split(/,(?![^{]*})/g)
কাঠামোগত

1
"//" বা "/ *" ধারণ করে যখন সেখানে ডিফল্ট স্ট্রিং মান থাকে তখন এটি কাজ করবে না
স্কিরিট

23

ফাঁকা স্থান এবং মন্তব্যে ঝুঁকির পরিমাণ কম এমন সমাধান হ'ল:

var fn = function(/* whoa) */ hi, you){};

fn.toString()
  .replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s))/mg,'')
  .match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1]
  .split(/,/)

["hi", "you"]

1
@ অ্যালেক্সমিলস একটি জিনিস আমি লক্ষ্য করেছি যে তা হ'ল তীর ফাংশনগুলির অনুশীলন বলছে যে তাদের 'ফাংশন' হিসাবে ধরা উচিত নয়। অর্থ এটি অ্যারে ফাংশনগুলির সাথে মেলে এটি উপযুক্ত হবে না। 'এটি' একইভাবে সেট করা নেই এবং সেগুলিকে ফাংশন হিসাবে ডাকা উচিত নয়। এটি এমন কিছু ছিল যা আমি কঠিনভাবে শিখেছি। ($ মাই সার্ভিস) => $ মাই সার্ভিস.ডোসোমথিং () দেখতে দুর্দান্ত লাগছে তবে এটি অ্যারে ফাংশনগুলির অপব্যবহার।
অ্যান্ড্রু টি ফিনেল

20

এখানে প্রচুর উত্তরগুলি রেজিক্সগুলি ব্যবহার করে, এটি ঠিক আছে তবে এটি ভাষাতে খুব ভাল নতুন সংযোজন পরিচালনা করে না (যেমন তীর ফাংশন এবং ক্লাস)। এছাড়াও নোটের বিষয়টি হ'ল আপনি যদি মিনিফাড কোডে এই ফাংশনগুলির কোনও ব্যবহার করেন তবে এটি চলে যাচ্ছে 🔥 এটি ক্ষুদ্রাকৃত নাম যাই হোক না কেন ব্যবহার করবে। কৌনিকটি ডিআই ধারক দিয়ে রেজিস্ট্রেশন করার সময় আর্গুমেন্টের ক্রমের সাথে মেলে এমন একটি স্ট্রিংয়ের অর্ডারযুক্ত অ্যারেতে আপনাকে অনুমতি দেওয়ার মাধ্যমে এগুলির চারপাশে যায়। সমাধান সহ তাই:

var esprima = require('esprima');
var _ = require('lodash');

const parseFunctionArguments = (func) => {
    // allows us to access properties that may or may not exist without throwing 
    // TypeError: Cannot set property 'x' of undefined
    const maybe = (x) => (x || {});

    // handle conversion to string and then to JSON AST
    const functionAsString = func.toString();
    const tree = esprima.parse(functionAsString);
    console.log(JSON.stringify(tree, null, 4))
    // We need to figure out where the main params are. Stupid arrow functions 👊
    const isArrowExpression = (maybe(_.first(tree.body)).type == 'ExpressionStatement');
    const params = isArrowExpression ? maybe(maybe(_.first(tree.body)).expression).params 
                                     : maybe(_.first(tree.body)).params;

    // extract out the param names from the JSON AST
    return _.map(params, 'name');
};

এটি মূল পার্স ইস্যু এবং আরও কয়েকটি ফাংশনের ধরণের (যেমন তীর ফাংশন) পরিচালনা করে। এটি কীভাবে পরিচালনা করতে পারে এবং কীভাবে পরিচালনা করতে পারে না তার একটি ধারণা এখানে রয়েছে:

// I usually use mocha as the test runner and chai as the assertion library
describe('Extracts argument names from function signature. 💪', () => {
    const test = (func) => {
        const expectation = ['it', 'parses', 'me'];
        const result = parseFunctionArguments(toBeParsed);
        result.should.equal(expectation);
    } 

    it('Parses a function declaration.', () => {
        function toBeParsed(it, parses, me){};
        test(toBeParsed);
    });

    it('Parses a functional expression.', () => {
        const toBeParsed = function(it, parses, me){};
        test(toBeParsed);
    });

    it('Parses an arrow function', () => {
        const toBeParsed = (it, parses, me) => {};
        test(toBeParsed);
    });

    // ================= cases not currently handled ========================

    // It blows up on this type of messing. TBH if you do this it deserves to 
    // fail 😋 On a tech note the params are pulled down in the function similar 
    // to how destructuring is handled by the ast.
    it('Parses complex default params', () => {
        function toBeParsed(it=4*(5/3), parses, me) {}
        test(toBeParsed);
    });

    // This passes back ['_ref'] as the params of the function. The _ref is a 
    // pointer to an VariableDeclarator where the ✨🦄 happens.
    it('Parses object destructuring param definitions.' () => {
        function toBeParsed ({it, parses, me}){}
        test(toBeParsed);
    });

    it('Parses object destructuring param definitions.' () => {
        function toBeParsed ([it, parses, me]){}
        test(toBeParsed);
    });

    // Classes while similar from an end result point of view to function
    // declarations are handled completely differently in the JS AST. 
    it('Parses a class constructor when passed through', () => {
        class ToBeParsed {
            constructor(it, parses, me) {}
        }
        test(ToBeParsed);
    });
});

আপনি এটি ES6 প্রক্সিগুলির জন্য কী ব্যবহার করতে চান তার উপর নির্ভর করে এবং ডেস্ট্রাকচারিং আপনার সেরা বাজি হতে পারে। উদাহরণস্বরূপ আপনি যদি নির্ভরতা ইনজেকশনের জন্য এটি ব্যবহার করতে চান (প্যারামগুলির নাম ব্যবহার করে) তবে আপনি এটি নিম্নলিখিত হিসাবে এটি করতে পারেন:

class GuiceJs {
    constructor() {
        this.modules = {}
    }
    resolve(name) {
        return this.getInjector()(this.modules[name]);
    }
    addModule(name, module) {
        this.modules[name] = module;
    }
    getInjector() {
        var container = this;

        return (klass) => {
            console.log(klass);
            var paramParser = new Proxy({}, {
                // The `get` handler is invoked whenever a get-call for
                // `injector.*` is made. We make a call to an external service
                // to actually hand back in the configured service. The proxy
                // allows us to bypass parsing the function params using
                // taditional regex or even the newer parser.
                get: (target, name) => container.resolve(name),

                // You shouldn't be able to set values on the injector.
                set: (target, name, value) => {
                    throw new Error(`Don't try to set ${name}! 😑`);
                }
            })
            return new klass(paramParser);
        }
    }
}

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

class App {
   constructor({tweeter, timeline}) {
        this.tweeter = tweeter;
        this.timeline = timeline;
    }
}

class HttpClient {}

class TwitterApi {
    constructor({client}) {
        this.client = client;
    }
}

class Timeline {
    constructor({api}) {
        this.api = api;
    }
}

class Tweeter {
    constructor({api}) {
        this.api = api;
    }
}

// Ok so now for the business end of the injector!
const di = new GuiceJs();

di.addModule('client', HttpClient);
di.addModule('api', TwitterApi);
di.addModule('tweeter', Tweeter);
di.addModule('timeline', Timeline);
di.addModule('app', App);

var app = di.resolve('app');
console.log(JSON.stringify(app, null, 4));

এটি নিম্নলিখিত ফলাফলগুলি দেয়:

{
    "tweeter": {
        "api": {
            "client": {}
        }
    },
    "timeline": {
        "api": {
            "client": {}
        }
    }
}

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

দ্রষ্টব্য: উত্পাদন ব্যবহারের জন্য প্রস্তুত হওয়ার আগে অনেক কাজ করার দরকার আছে তবে এটি কী দেখাচ্ছে তা ধারণা দেয় না an

উত্তরে কিছুটা দেরি হলেও এটি অন্যদের যারা একই জিনিস নিয়ে ভাবছেন তাদের পক্ষে এটি সহায়তা করতে পারে। 👍


13

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

কোনও ফাংশনের প্যারামিটারগুলি আসলে অ্যারে-জাতীয় অবজেক্টে বলা হয় arguments , যেখানে প্রথম যুক্তিটি হয় arguments[0], দ্বিতীয়টি হয় arguments[1]এবং আরও অনেক কিছু। প্রথম বন্ধনে প্যারামিটারের নাম লিখলে শর্টহ্যান্ড সিনট্যাক্স হিসাবে দেখা যায়। এই:

function doSomething(foo, bar) {
    console.log("does something");
}

...হিসাবে একই:

function doSomething() {
    var foo = arguments[0];
    var bar = arguments[1];

    console.log("does something");
}

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

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

এখানে আরও খারাপ এবং আরও সাধারণ পরিস্থিতি। যদি কোনও ফাংশনে 3 বা 4 টিরও বেশি আর্গুমেন্ট থাকে, তবে এটির পরিবর্তে এটি কোনও বস্তুটি সরবরাহ করা যৌক্তিক হতে পারে, যার সাথে কাজ করা সহজ।

function saySomething(obj) {
  if(obj.message) console.log((obj.sender || "Anon") + ": " + obj.message);
}

saySomething({sender: "user123", message: "Hello world"});

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


1
আমি মনে করি এর মতো কোনও কিসের ক্ষেত্রে সাধারণত: ডিবাগিং / লগিং, একধরণের সাজসজ্জা যা ফানকি স্টাফ করে (প্রযুক্তিগত শব্দ 😁), বা আপনার অ্যাপ্লিকেশনগুলির জন্য স্বয়ংক্রিয়ভাবে যুক্তির নামের ভিত্তিতে ইনজেকশনের জন্য নির্ভরতা ইনজেকশন কাঠামো তৈরি করে (এটি কীভাবে কৌনিক হয়) কাজ করে)। আরেকটি সত্যই আকর্ষণীয় ব্যবহারের ক্ষেত্রে প্রতিশ্রুতি-নোড (এটি একটি লাইব্রেরি যা একটি ফাংশন নেয় যা সাধারণত একটি কলব্যাক নেয় এবং তারপরে এটিকে প্রতিশ্রুতিতে রূপান্তর করে)। তারা এটিকে কলব্যাকের সাধারণ নামগুলি খুঁজতে (যেমন সিবি / কলব্যাক / ইত্যাদি) সন্ধান করতে ব্যবহার করে এবং তারপরে তারা ফাংশনটি মোড়ানোর আগে অ্যাসিঙ্ক বা সিঙ্ক করে কিনা তা পরীক্ষা করতে পারে।
জেমস ড্রু

তাদের বিশ্লেষণকারীদের জন্য এই ফাইলটি দেখুন । এটি কিছুটা নিষ্পাপ তবে এটি বেশিরভাগ ক্ষেত্রে পরিচালনা করে।
জেমস ড্রু

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

একটি "মজাদার" সিডনোটে, আপনি সমস্ত ফাংশনকে এমনভাবে কাজ করতে পারেন যেন তারা চালিয়ে অনামী বিল্ট-ইনগুলি থাকে:Function.prototype.toString = function () { return 'function () { [native code] }'; };
ডমিনো

1
সম্মত, এটি এটি পরিচালনা করতে কিছুটা অগোছালো। সবচেয়ে ভাল এবং সহজবোধ্য ব্যবহার হ'ল নির্ভরতা ইনজেকশন। সেক্ষেত্রে আপনি কোডটির মালিক এবং নামকরণ এবং কোডের অন্যান্য ক্ষেত্রগুলি পরিচালনা করতে পারেন। আমি এখানে এটি সর্বাধিক ব্যবহার দেখতে পাবেন বলে মনে করি। আমি বর্তমানে এসপ্রিমা ব্যবহার করছি ( রেগেক্সের পরিবর্তে) এবং ইএস 6 Proxy( কনস্ট্রাক্টর ট্র্যাপ এবং ট্র্যাপ প্রয়োগ করুন ) এবং Reflectionআমার কয়েকটি মডিউলের জন্য ডিআই হ্যান্ডেল করতে। এটা যুক্তিযুক্তভাবে শক্ত।
জেমস ড্র

10

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

এটি আমাকে এই প্রশ্নের দিকে নিয়ে গেছে তবে কোনও অন্তর্নিহিত সমাধান নেই। যা আমাকে এই উত্তরের দিকে নিয়ে গিয়েছিল যা ব্যাখ্যা করে যে argumentsকেবলমাত্র ফাংশনের বাইরে অবহেলিত , তাই আমরা আর ব্যবহার করতে পারি না myFunction.argumentsবা পাই:

TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

আমাদের হাতা রোল আপ এবং কাজ পেতে সময়:

Function ফাংশন প্যারামিটারগুলি পুনরুদ্ধার 4*(5/3)করতে পার্সার প্রয়োজন কারণ জটিল এক্সপ্রেশনগুলি ডিফল্ট মান হিসাবে ব্যবহার করা যেতে পারে। তাই গাফরের উত্তর বা জেমস ড্রয়ের উত্তর এখন পর্যন্ত সেরা পন্থা।

আমি ব্যাবিলন এবং এসপ্রিমা পার্সার চেষ্টা করেছিলাম কিন্তু দুর্ভাগ্যক্রমে তারা মেনুজ্জ চর্যটনিকের উত্তরে উল্লিখিত অনুসারে , তারা একক বেনামের ফাংশন পার্স করতে পারে না । কোডটি বন্ধুত্বের চারপাশে ঘিরে যদিও আমি যুক্তিটি পরিবর্তন না করতে পারি:

const ast = parser.parse("(\n" + func.toString() + "\n)")

নতুনলাইনগুলি //(একক-লাইন মন্তব্য) দিয়ে সমস্যাগুলি প্রতিরোধ করে ।

P যদি কোনও পার্সার উপলব্ধ না হয় তবে পরবর্তী সর্বোত্তম বিকল্পটি হল Angular.js এর নির্ভরতা ইনজেক্টর নিয়মিত এক্সপ্রেশনগুলির মতো একটি চেষ্টা করা এবং সত্য প্রযুক্তিটি ব্যবহার করা। আমি ল্যাম্বডারের উত্তরের একটি কার্যকরী সংস্করণ নম্রতার উত্তরের সাথে সংযুক্ত করেছি এবং ARROWনিয়মিত প্রকাশের দ্বারা ES6 ফ্যাট অ্যার ফাংশন অনুমোদিত কিনা তা নিয়ন্ত্রণ করার জন্য একটি alচ্ছিক বুলিয়ান যুক্ত করেছি added


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

আমি এই সমাধানগুলি যথাসাধ্য চেষ্টা করার চেষ্টা করব তবে জাভাস্ক্রিপ্ট রক্ষণাবেক্ষণকারীদের প্রচেষ্টা ছাড়াই এটি একটি উন্মুক্ত সমস্যা থেকে যাবে।

নোড.জেএস সংস্করণ (স্ট্যাকওভারফ্লো নোড.জেএস সমর্থন না করা পর্যন্ত চালানো যায় না):

const parserName = 'babylon';
// const parserName = 'esprima';
const parser = require(parserName);

function getArguments(func) {
    const maybe = function (x) {
        return x || {}; // optionals support
    }

    try {
        const ast = parser.parse("(\n" + func.toString() + "\n)");
        const program = parserName == 'babylon' ? ast.program : ast;

        return program
            .body[0]
            .expression
            .params
            .map(function(node) {
                return node.name || maybe(node.left).name || '...' + maybe(node.argument).name;
            });
    } catch (e) {
        return []; // could also return null
    }
};

////////// TESTS //////////

function logArgs(func) {
	let object = {};

	object[func] = getArguments(func);

	console.log(object);
// 	console.log(/*JSON.stringify(*/getArguments(func)/*)*/);
}

console.log('');
console.log('////////// MISC //////////');

logArgs((a, b) => {});
logArgs((a, b = 1) => {});
logArgs((a, b, ...args) => {});
logArgs(function(a, b, ...args) {});
logArgs(function(a, b = 1, c = 4 * (5 / 3), d = 2) {});
logArgs(async function(a, b, ...args) {});
logArgs(function async(a, b, ...args) {});

console.log('');
console.log('////////// FUNCTIONS //////////');

logArgs(function(a, b, c) {});
logArgs(function() {});
logArgs(function named(a, b, c) {});
logArgs(function(a /* = 1 */, b /* = true */) {});
logArgs(function fprintf(handle, fmt /*, ...*/) {});
logArgs(function(a, b = 1, c) {});
logArgs(function(a = 4 * (5 / 3), b) {});
// logArgs(function (a, // single-line comment xjunk) {});
// logArgs(function (a /* fooled you {});
// logArgs(function (a /* function() yes */, \n /* no, */b)/* omg! */ {});
// logArgs(function ( A, b \n,c ,d \n ) \n {});
logArgs(function(a, b) {});
logArgs(function $args(func) {});
logArgs(null);
logArgs(function Object() {});

console.log('');
console.log('////////// STRINGS //////////');

logArgs('function (a,b,c) {}');
logArgs('function () {}');
logArgs('function named(a, b, c) {}');
logArgs('function (a /* = 1 */, b /* = true */) {}');
logArgs('function fprintf(handle, fmt /*, ...*/) {}');
logArgs('function( a, b = 1, c ) {}');
logArgs('function (a=4*(5/3), b) {}');
logArgs('function (a, // single-line comment xjunk) {}');
logArgs('function (a /* fooled you {}');
logArgs('function (a /* function() yes */, \n /* no, */b)/* omg! */ {}');
logArgs('function ( A, b \n,c ,d \n ) \n {}');
logArgs('function (a,b) {}');
logArgs('function $args(func) {}');
logArgs('null');
logArgs('function Object() {}');

সম্পূর্ণ কাজের উদাহরণ:

https://repl.it/repls/SandybrownPhonyAngles

ব্রাউজার সংস্করণ (নোট করুন এটি প্রথম জটিল ডিফল্ট মানে থামবে):

function getArguments(func) {
    const ARROW = true;
    const FUNC_ARGS = ARROW ? /^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m : /^(function)\s*[^\(]*\(\s*([^\)]*)\)/m;
    const FUNC_ARG_SPLIT = /,/;
    const FUNC_ARG = /^\s*(_?)(.+?)\1\s*$/;
    const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;

    return ((func || '').toString().replace(STRIP_COMMENTS, '').match(FUNC_ARGS) || ['', '', ''])[2]
        .split(FUNC_ARG_SPLIT)
        .map(function(arg) {
            return arg.replace(FUNC_ARG, function(all, underscore, name) {
                return name.split('=')[0].trim();
            });
        })
        .filter(String);
}

////////// TESTS //////////

function logArgs(func) {
	let object = {};

	object[func] = getArguments(func);

	console.log(object);
// 	console.log(/*JSON.stringify(*/getArguments(func)/*)*/);
}

console.log('');
console.log('////////// MISC //////////');

logArgs((a, b) => {});
logArgs((a, b = 1) => {});
logArgs((a, b, ...args) => {});
logArgs(function(a, b, ...args) {});
logArgs(function(a, b = 1, c = 4 * (5 / 3), d = 2) {});
logArgs(async function(a, b, ...args) {});
logArgs(function async(a, b, ...args) {});

console.log('');
console.log('////////// FUNCTIONS //////////');

logArgs(function(a, b, c) {});
logArgs(function() {});
logArgs(function named(a, b, c) {});
logArgs(function(a /* = 1 */, b /* = true */) {});
logArgs(function fprintf(handle, fmt /*, ...*/) {});
logArgs(function(a, b = 1, c) {});
logArgs(function(a = 4 * (5 / 3), b) {});
// logArgs(function (a, // single-line comment xjunk) {});
// logArgs(function (a /* fooled you {});
// logArgs(function (a /* function() yes */, \n /* no, */b)/* omg! */ {});
// logArgs(function ( A, b \n,c ,d \n ) \n {});
logArgs(function(a, b) {});
logArgs(function $args(func) {});
logArgs(null);
logArgs(function Object() {});

console.log('');
console.log('////////// STRINGS //////////');

logArgs('function (a,b,c) {}');
logArgs('function () {}');
logArgs('function named(a, b, c) {}');
logArgs('function (a /* = 1 */, b /* = true */) {}');
logArgs('function fprintf(handle, fmt /*, ...*/) {}');
logArgs('function( a, b = 1, c ) {}');
logArgs('function (a=4*(5/3), b) {}');
logArgs('function (a, // single-line comment xjunk) {}');
logArgs('function (a /* fooled you {}');
logArgs('function (a /* function() yes */, \n /* no, */b)/* omg! */ {}');
logArgs('function ( A, b \n,c ,d \n ) \n {}');
logArgs('function (a,b) {}');
logArgs('function $args(func) {}');
logArgs('null');
logArgs('function Object() {}');

সম্পূর্ণ কাজের উদাহরণ:

https://repl.it/repls/StupendousShowyOffices


যদি আমি ভুল না হয়ে থাকি তবে আপনার ব্রাউজার সংস্করণে, FUNC_ARGS এ প্রথম শর্তযুক্ত তীর এবং traditionalতিহ্যগত ফাংশন উভয়ের জন্যই কাজ করবে, সুতরাং আপনার দ্বিতীয় অংশের প্রয়োজন হবে না এবং তাই আপনি তীরের উপর নির্ভরতা দূর করতে পারেন।
pwilcox

এটা অসাধারণ! আমি এর মতো একটি সমাধান খুঁজছিলাম যা ES6 সিনট্যাক্সটি coverাকতে পার্সার ব্যবহার করে। আমি এটি একটি উপহাস "প্রয়োগকারী ইন্টারফেস" ম্যাচার তৈরি করতে ব্যবহার করার পরিকল্পনা করছি কারণ কেবলমাত্র ফাংশন.লাইনেথের ডিফল্ট পরামিতিগুলির সীমাবদ্ধতা রয়েছে এবং আমি বিশ্রামের পরামিতিগুলি দৃsert় করতে সক্ষম হতে চেয়েছিলাম।
cue8chak

এটি উল্লেখ করার মতো যে পঞ্চম পরীক্ষার ক্ষেত্রে ডিফল্ট মানটিতে প্রথম বন্ধনী রয়েছে। আমি আশা করি আমার রেজেক্স-ফু ঠিক করার মতো শক্তিশালী ছিল, দুঃখিত!
ডেল অ্যান্ডারসন

8

আমি এখানে বেশিরভাগ উত্তর পড়েছি এবং আমি আমার ওয়ান-লাইন যুক্ত করতে চাই।

new RegExp('(?:'+Function.name+'\\s*|^)\\((.*?)\\)').exec(Function.toString().replace(/\n/g, ''))[1].replace(/\/\*.*?\*\//g, '').replace(/ /g, '')

অথবা

function getParameters(func) {
  return new RegExp('(?:'+func.name+'\\s*|^)\\s*\\((.*?)\\)').exec(func.toString().replace(/\n/g, ''))[1].replace(/\/\*.*?\*\//g, '').replace(/ /g, '');
}

বা ইসিএমএ 6-তে একটি-লাইনার ফাংশনের জন্য

var getParameters = func => new RegExp('(?:'+func.name+'\\s*|^)\\s*\\((.*?)\\)').exec(func.toString().replace(/\n/g, ''))[1].replace(/\/\*.*?\*\//g, '').replace(/ /g, '');

__

ধরা যাক আপনার একটি ফাংশন আছে

function foo(abc, def, ghi, jkl) {
  //code
}

নীচের কোডটি ফিরে আসবে "abc,def,ghi,jkl"

এই কোডটি কামিলো মার্টিন যে ফাংশনটি সেটআপ করেছিল তার সাথেও কাজ করবে :

function  (  A,  b
,c      ,d
){}

জ্যাক অ্যালানের জবাব সম্পর্কে বুবারসনের মন্তব্য সহ :

function(a /* fooled you)*/,b){}

__

ব্যাখ্যা

new RegExp('(?:'+Function.name+'\\s*|^)\\s*\\((.*?)\\)')

এটি দিয়ে নিয়মিত এক্সপ্রেশন তৈরি করে new RegExp('(?:'+Function.name+'\\s*|^)\\s*\\((.*?)\\)')। আমাকে ব্যবহার করতে হবে new RegExpকারণ আমি একটি পরিবর্তনশীল ইনজেকশন দিচ্ছি (Function.name রেজিএক্সপ্যাকের মধ্যে , ফাংশনের নাম লক্ষ্য করে) ইনজেক্ট করছি।

উদাহরণ যদি ফাংশনটির নাম "foo" ( function foo()) হয় তবে RegExp হবে /foo\s*\((.*?)\)/

Function.toString().replace(/\n/g, '')

তারপরে এটি পুরো ফাংশনটিকে স্ট্রিংয়ে রূপান্তর করে এবং সমস্ত নতুনলাইন সরিয়ে দেয়। নতুন লাইনগুলি সরিয়ে ফেলা ক্যামিলো মার্টিন প্রদত্ত ফাংশনটির সাথে সহায়তা করে ।

.exec(...)[1]

এটি RegExp.prototype.execফাংশন। এটি মূলত new RegExp()স্ট্রিং ( Function.toString()) এ নিয়মিত এক্সপোঞ্জেন্ট ( ) এর সাথে মেলে । তারপরে নিয়মিত এক্সপোঞ্জেন্ট ( ) এ পাওয়া [1]প্রথম ক্যাপচার গ্রুপটি ফিরিয়ে দেবে (.*?)

.replace(/\/\*.*?\*\//g, '').replace(/ /g, '')

এই প্রতিটি মন্তব্যের ভিতরে সরাবে /*এবং */, এবং সমস্ত জায়গা সরান।


এটাও এখন পড়ছেন সমর্থন করে এবং বোঝার তীর ( =>যেমন) ফাংশন, f = (a, b) => void 0;যার মধ্যে Function.toString()ফিরে আসবে (a, b) => void 0স্বাভাবিক ফাংশনের পরিবর্তে function f(a, b) { return void 0; }। মূল নিয়মিত প্রকাশটি তার বিভ্রান্তিতে একটি ত্রুটি ফেলে দিত, তবে এখন এটি দায়ী।

পরিবর্তনটি new RegExp(Function.name+'\\s*\\((.*?)\\)')( /Function\s*\((.*?)\)/) থেকে new RegExp('(?:'+Function.name+'\\s*|^)\\((.*?)\\)')( /(?:Function\s*|^)\((.*?)\)/) এ হয়েছিল


আপনি যদি কমা দ্বারা পৃথক স্ট্রিংয়ের পরিবর্তে সমস্ত পরামিতিগুলিকে একটি অ্যারে তৈরি করতে চান তবে শেষে কেবল যুক্ত করুন .split(',')


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

এই সহজ তীর ফাংশন কাজ করে না: f = (a, b) => void 0; উপর getParameters(f)আমি পেতেTypeError: Cannot read property '1' of null
যেমন AT

@AT আমি আপনার ইস্যুটির জন্য সমর্থন ঠিক করার জন্য উত্তরটি সবেমাত্র আপডেট করেছি
জেকেরট00

ধন্যবাদ… তবে মনে রাখবেন যে প্রথম বন্ধনীগুলির আর প্রয়োজন নেই, তাই আপনি getParameters(a => b => c => d => a*b*c*d)আপনার কোড সহ এখনও এমন কিছু করতে পারেন যা TypeError: Cannot read property '1' of nullএইটি স্ট্যাকওভারফ্লো.com

ফাংশনটির ডিফল্ট মান (ভূমিকা, নাম = "বব" থাকে না) কাজ করে না নিষ্কাশিত প্যারামিটারটি প্রত্যাশিত "নাম" এর পরিবর্তে নাম = "বব" হয়
দিমিত্রি


7

প্যারামিটার তালিকার মধ্যে মন্তব্য, সাদা স্থান এবং অন্যান্য জিনিসগুলির সাথে অনেকগুলি সমস্যা এড়াতে আপনি "এসপ্রিমা" পার্সার ব্যবহার করতে পারেন।

function getParameters(yourFunction) {
    var i,
        // safetyValve is necessary, because sole "function () {...}"
        // is not a valid syntax
        parsed = esprima.parse("safetyValve = " + yourFunction.toString()),
        params = parsed.body[0].expression.right.params,
        ret = [];

    for (i = 0; i < params.length; i += 1) {
        // Handle default params. Exe: function defaults(a = 0,b = 2,c = 3){}
        if (params[i].type == 'AssignmentPattern') {
            ret.push(params[i].left.name)
        } else {
            ret.push(params[i].name);
        }
    }

    return ret;
}

এটি এর মতো কোড দিয়েও কাজ করে:

getParameters(function (hello /*, foo ),* /bar* { */,world) {}); // ["hello", "world"]

6

আমি এটি করার আগে আগে চেষ্টা করেছি, তবে এটি করার কোনও অকৃত্রিম উপায় খুঁজে পাইনি। আমি পরিবর্তে একটি অবজেক্টে পাস এবং তারপরে লুপিং শেষ করেছি।

//define like
function test(args) {
    for(var item in args) {
        alert(item);
        alert(args[item]);
    }
}

//then used like
test({
    name:"Joe",
    age:40,
    admin:bool
});

আমার অনেকগুলি ফাংশন ইতিমধ্যে প্রাক-সংজ্ঞায়িত হয়েছে যা একক বস্তুর পরিবর্তে স্ট্যান্ডার্ড প্যারামিটার সহ ডাকা হচ্ছে। সবকিছু পরিবর্তন করতে অনেক বেশি সময় লাগবে।
বিকাসদে

2
এই প্রতিক্রিয়াটি মূল প্রশ্নের উত্তর নয় যা সংক্ষিপ্তভাবে সংজ্ঞায়িত হয়েছিল। এটি সম্পূর্ণ ভিন্ন সমস্যার সমাধান দেখায়। মূল প্রশ্নটি অ্যাঙ্গুলারজেএস এর নির্ভরতা ইঞ্জেকশনটিকে ব্যবহার করে এমন কৌশলটি বোঝায়। আর্গুমেন্টের নামগুলি অর্থপূর্ণ, কারণ এগুলি ডিআইডি স্বয়ংক্রিয়ভাবে সরবরাহ করে module
ল্যাম্বডার

4

আমি জানি না যে এই সমাধানটি আপনার সমস্যার জন্য উপযুক্ত কিনা তবে এটি আপনাকে যে কোড ব্যবহার করে তা পরিবর্তন না করেই আপনি যা চান তা ফাংশনটিকে নতুন করে সংজ্ঞা দিতে দেয়। বিদ্যমান কলগুলি অবস্থানযুক্ত প্যারাম ব্যবহার করবে, যখন ফাংশন বাস্তবায়নে "নামকৃত প্যারাম" (একক হ্যাশ প্যারাম) ব্যবহার করা যেতে পারে।

আমি ভেবেছিলাম আপনি যে কোনও উপায়ে বিদ্যমান ফাংশন সংজ্ঞা সংশোধন করবেন, তাই কোনও ফ্যাক্টরি ফাংশন যা আপনার যা চান তা করে না কেন:

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var withNamedParams = function(params, lambda) {
    return function() {
        var named = {};
        var max   = arguments.length;

        for (var i=0; i<max; i++) {
            named[params[i]] = arguments[i];
        }

        return lambda(named);
    };
};

var foo = withNamedParams(["a", "b", "c"], function(params) {
    for (var param in params) {
        alert(param + ": " + params[param]);
    }
});

foo(1, 2, 3);
</script>
</head>
<body>

</body>
</html>

আশা করি এটা সাহায্য করবে.


4

এটি করার সঠিক উপায় হ'ল জেএস পার্সার ব্যবহার করা। আকোর ব্যবহার করে এখানে একটি উদাহরণ দেওয়া হয়েছে ।

const acorn = require('acorn');    

function f(a, b, c) {
   // ...
}

const argNames = acorn.parse(f).body[0].params.map(x => x.name);
console.log(argNames);  // Output: [ 'a', 'b', 'c' ]

এখানে কোডটি ফাংশনের তিনটি (আনুষ্ঠানিক) পরামিতির নামগুলি সন্ধান করে f। এটা তোলে খাইয়ে তাই আছে fমধ্যে acorn.parse()


মূল্যবোধ সম্পর্কে কি?
ইরান otzap

2

প্যারামিটারগুলির তালিকা কীভাবে পাবেন তা আমি জানি না তবে এটি কতটা প্রত্যাশা করে তা পেতে আপনি এটি করতে পারেন।

alert(doSomething.length);

function gotcha (a, b = false, c) {}; alert(gotcha.length)
বালুপটন

2

টেকিং উত্তর পরিবর্তিত হয়েছিলো @ জ্যাক-অ্যালান আমি থেকে ফাংশন সামান্য যেমন ES6 ডিফল্ট বৈশিষ্ট্যাবলী করার অনুমতি:

function( a, b = 1, c ){};

এখনও ফিরে [ 'a', 'b' ]

/**
 * Get the keys of the paramaters of a function.
 *
 * @param {function} method  Function to get parameter keys for
 * @return {array}
 */
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var ARGUMENT_NAMES = /(?:^|,)\s*([^\s,=]+)/g;
function getFunctionParameters ( func ) {
    var fnStr = func.toString().replace(STRIP_COMMENTS, '');
    var argsList = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')'));
    var result = argsList.match( ARGUMENT_NAMES );

    if(result === null) {
        return [];
    }
    else {
        var stripped = [];
        for ( var i = 0; i < result.length; i++  ) {
            stripped.push( result[i].replace(/[\s,]/g, '') );
        }
        return stripped;
    }
}

1
ধন্যবাদ, এই থ্রেডে আপনারা একমাত্র যা আমার পক্ষে কাজ করেছিল।
যেমন AT

1

আমি সাধারণত এটি কীভাবে করি:

function name(arg1, arg2){
    var args = arguments; // array: [arg1, arg2]
    var objecArgOne = args[0].one;
}
name({one: "1", two: "2"}, "string");

এমনকি আপনি এই জাতীয় ফাংশন নাম দ্বারা আরগগুলি রেফার করতে পারেন:

name.arguments;

আশাকরি এটা সাহায্য করবে!


4
এবং ফাংশন পরামিতিগুলির নাম কোথায়?
আন্দ্রেজ

আহ ... আপনার মানে হ্যাশ-ফর্মে আপনি এটি চান? var args = name.arguments; console.log('I WANNa SEE', args);যেনে : আউটপুট "{arg1: {...}, arg2: 'স্ট্রিং'}" এর মতো কিছু? এই জিনিষ আপ পরিষ্কার করতে পারেন: (function fn (arg, argg, arrrrgggg) { console.log('#fn:', fn.arguments, Object.keys(fn.arguments)); }); fn('Huh...?', 'Wha...?', 'Magic...?');। ফাংশন আর্গুমেন্টগুলি একটি 'অ্যারে' -র মতো অবজেক্ট, যার মধ্যে অসংখ্য সূচক থাকে। আমি মনে করি না যে হ্যাশ-ম্যাপিং সম্ভব, তবে আপনি কেবল একটি অবজেক্ট-আক্ষরিক পাশ করতে পেরেছিলেন তবে যেভাবে যাইহোক আপনার 4 টিরও বেশি প্যারাম থাকলে ভাল অনুশীলন।
কোডি

1
//See this:


// global var, naming bB
var bB = 5;

//  Dependency Injection cokntroller
var a = function(str, fn) {
  //stringify function body
  var fnStr = fn.toString();

  // Key: get form args to string
  var args = fnStr.match(/function\s*\((.*?)\)/);
  // 
  console.log(args);
  // if the form arg is 'bB', then exec it, otherwise, do nothing
  for (var i = 0; i < args.length; i++) {
    if(args[i] == 'bB') {
      fn(bB);
    }
  }
}
// will do nothing
a('sdfdfdfs,', function(some){
alert(some)
});
// will alert 5

a('sdfdsdsfdfsdfdsf,', function(bB){
alert(bB)
});

// see, this shows you how to get function args in string

1

এর উত্তরের জন্য 3 টি পদক্ষেপ প্রয়োজন:

  1. প্রকৃত পরামিতিগুলির মানগুলি ফাংশনে পাস করার জন্য (আসুন এটি কল করুন argValues)। এটি যেমন সহজলভ্য তাই এটি সহজলভ্যarguments ফাংশন এটি ফাংশনের ভিতরে ।
  2. ফাংশনের স্বাক্ষর থেকে প্যারামিটারের নামগুলি পেতে (আসুন এটি কল করুন) argNames )। এটি তত সহজ নয় এবং ফাংশনটি বিশ্লেষণের প্রয়োজন। জটিল রেজেক্স নিজেই করা এবং প্রান্তের কেসগুলি (ডিফল্ট প্যারামিটার, মন্তব্য, ...) নিয়ে চিন্তিত না হয়ে আপনি ব্যাবিলনের মতো লাইব্রেরি ব্যবহার করতে পারেন যা ফাংশনটিকে একটি বিমূর্ত সিনট্যাক্স ট্রিতে পার্স করবে যেখানে থেকে আপনি প্যারামিটারের নামগুলি পেতে পারেন।
  3. শেষ পদক্ষেপটি হ'ল 2 টি অ্যারে এক সাথে 1 অ্যারে যুক্ত করা যাতে সমস্ত প্যারামিটারের নাম এবং মান রয়েছে।

কোডটি এরকম হবে

const babylon = require("babylon")
function doSomething(a, b, c) {
    // get the values of passed argumenst
    const argValues = arguments

    // get the names of the arguments by parsing the function
    const ast = babylon.parse(doSomething.toString())
    const argNames =  ast.program.body[0].params.map(node => node.name)

    // join the 2 arrays, by looping over the longest of 2 arrays
    const maxLen = Math.max(argNames.length, argValues.length)
    const args = []
    for (i = 0; i < maxLen; i++) { 
       args.push({name: argNames[i], value: argValues[i]})
    }
    console.log(args)

    // implement the actual function here
}

doSomething(1, 2, 3, 4)

এবং লগ করা বস্তু হবে

[
  {
    "name": "a",
    "value": 1
  },
  {
    "name": "c",
    "value": 3
  },
  {
    "value": 4
  }
]

এবং এখানে একটি কার্যকারী উদাহরণ https://tonicdev.com/5763eb77a945f41300f62a79/5763eb77a945f41300f62a7a


1
function getArgs(args) {
    var argsObj = {};

    var argList = /\(([^)]*)/.exec(args.callee)[1];
    var argCnt = 0;
    var tokens;

    while (tokens = /\s*([^,]+)/g.exec(argList)) {
        argsObj[tokens[1]] = args[argCnt++];
    }

    return argsObj;
}

1

বাহ ইতিমধ্যে অনেক উত্তর .. আমি নিশ্চিত যে এটি কবর দেওয়া হবে। তবুও আমি বুঝতে পেরেছি এটি কারওর জন্য কার্যকর হতে পারে।

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

এই ফাংশনটি ডিবাগিং উদ্দেশ্যে খুব দরকারী, উদাহরণস্বরূপ: লগিং এর প্যারামগুলি, ডিফল্ট প্যারাম মান এবং তর্কগুলি দিয়ে ফাংশন বলে।

আমি গতকাল এটিতে কিছুটা সময় ব্যয় করেছি, এই সমস্যাটি সমাধান করার জন্য সঠিক RegExp ক্র্যাক করেছিলাম এবং এটিই আমি সামনে এলাম। এটি খুব ভালভাবে কাজ করে এবং আমি ফলাফলটি দেখে খুব সন্তুষ্ট:

const REGEX_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
const REGEX_FUNCTION_PARAMS = /(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m
const REGEX_PARAMETERS_VALUES = /\s*(\w+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm

/**
 * Retrieve a function's parameter names and default values
 * Notes:
 *  - parameters with default values will not show up in transpiler code (Babel) because the parameter is removed from the function.
 *  - does NOT support inline arrow functions as default values
 *      to clarify: ( name = "string", add = defaultAddFunction )   - is ok
 *                  ( name = "string", add = ( a )=> a + 1 )        - is NOT ok
 *  - does NOT support default string value that are appended with a non-standard ( word characters or $ ) variable name
 *      to clarify: ( name = "string" + b )         - is ok
 *                  ( name = "string" + $b )        - is ok
 *                  ( name = "string" + b + "!" )   - is ok
 *                  ( name = "string" + λ )         - is NOT ok
 * @param {function} func
 * @returns {Array} - An array of the given function's parameter [key, default value] pairs.
 */
function getParams(func) {

  let functionAsString = func.toString()
  let params = []
  let match
  functionAsString = functionAsString.replace(REGEX_COMMENTS, '')
  functionAsString = functionAsString.match(REGEX_FUNCTION_PARAMS)[1]
  if (functionAsString.charAt(0) === '(') functionAsString = functionAsString.slice(1, -1)
  while (match = REGEX_PARAMETERS_VALUES.exec(functionAsString)) params.push([match[1], match[2]])
  return params

}



// Lets run some tests!

var defaultName = 'some name'

function test1(param1, param2, param3) { return (param1) => param1 + param2 + param3 }
function test2(param1, param2 = 4 * (5 / 3), param3) {}
function test3(param1, param2 = "/root/" + defaultName + ".jpeg", param3) {}
function test4(param1, param2 = (a) => a + 1) {}

console.log(getParams(test1)) 
console.log(getParams(test2))
console.log(getParams(test3))
console.log(getParams(test4))

// [ [ 'param1', undefined ], [ 'param2', undefined ], [ 'param3', undefined ] ]
// [ [ 'param1', undefined ], [ 'param2', '4 * (5 / 3)' ], [ 'param3', undefined ] ]
// [ [ 'param1', undefined ], [ 'param2', '"/root/" + defaultName + ".jpeg"' ], [ 'param3', undefined ] ]
// [ [ 'param1', undefined ], [ 'param2', '( a' ] ]
// --> This last one fails because of the inlined arrow function!


var arrowTest1 = (a = 1) => a + 4
var arrowTest2 = a => b => a + b
var arrowTest3 = (param1 = "/" + defaultName) => { return param1 + '...' }
var arrowTest4 = (param1 = "/" + defaultName, param2 = 4, param3 = null) => { () => param3 ? param3 : param2 }

console.log(getParams(arrowTest1))
console.log(getParams(arrowTest2))
console.log(getParams(arrowTest3))
console.log(getParams(arrowTest4))

// [ [ 'a', '1' ] ]
// [ [ 'a', undefined ] ]
// [ [ 'param1', '"/" + defaultName' ] ]
// [ [ 'param1', '"/" + defaultName' ], [ 'param2', '4' ], [ 'param3', 'null' ] ]


console.log(getParams((param1) => param1 + 1))
console.log(getParams((param1 = 'default') => { return param1 + '.jpeg' }))

// [ [ 'param1', undefined ] ]
// [ [ 'param1', '\'default\'' ] ]

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

অন্য একটি নোট, মন্তব্যে বর্ণিত হিসাবে এটি হ'ল একটি ডিফল্ট মান হিসাবে ইনিল্ডেড তীর ফাংশনগুলির সাথে কাজ করে না। এটি কেবল একটি রেজিপ্যাক্স ব্যবহার করে মানগুলি বের করা জটিলতর করে তোলে।

এটি আপনার জন্য দরকারী ছিল যদি আমাকে জানান! কিছু প্রতিক্রিয়া শুনতে চাই!


1

আমি নীচে একটি সংক্ষিপ্ত উদাহরণ দেবো:

function test(arg1,arg2){
    var funcStr = test.toString()
    var leftIndex = funcStr.indexOf('(');
    var rightIndex = funcStr.indexOf(')');
    var paramStr = funcStr.substr(leftIndex+1,rightIndex-leftIndex-1);
    var params = paramStr.split(',');
    for(param of params){
        console.log(param);   // arg1,arg2
    }
}

test();

সেই উদাহরণটি কেবল আপনার জন্য পরামিতিগুলির নাম পাওয়ার জন্য।
মায়জু

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

1

এই প্যাকেজটি এএসটি তৈরির জন্য পুনঃনির্ধারণ ব্যবহার করে এবং তারপরে প্যারামিটারের নামগুলি সংগ্রহ করা হয়, এটি এটি প্যাটার্ন মেলানো, ডিফল্ট আর্গুমেন্ট, তীর ফাংশন এবং অন্যান্য ES6 বৈশিষ্ট্যগুলিকে সমর্থন করে।

https://www.npmjs.com/package/es-arguments


1

আমি AngularJS থেকে নেওয়া সংস্করণটি পরিবর্তন করেছি যা Angular ছাড়া কাজ করার জন্য নির্ভরতা ইনজেকশন প্রক্রিয়া প্রয়োগ করে। আমি STRIP_COMMENTSসাথে কাজ করার জন্য রেজেক্সও আপডেট করেছি ECMA6, সুতরাং এটি স্বাক্ষরে ডিফল্ট মানগুলির মতো জিনিসগুলিকে সমর্থন করে।

var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(.+?)\1\s*$/;
var STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/mg;

function annotate(fn) {
  var $inject,
    fnText,
    argDecl,
    last;

  if (typeof fn == 'function') {
    if (!($inject = fn.$inject)) {
      $inject = [];
      fnText = fn.toString().replace(STRIP_COMMENTS, '');
      argDecl = fnText.match(FN_ARGS);
      argDecl[1].split(FN_ARG_SPLIT).forEach(function(arg) {
        arg.replace(FN_ARG, function(all, underscore, name) {
          $inject.push(name);
        });
      });
      fn.$inject = $inject;
    }
  } else {
    throw Error("not a function")
  }
  return $inject;
}

console.log("function(a, b)",annotate(function(a, b) {
  console.log(a, b, c, d)
}))
console.log("function(a, b = 0, /*c,*/ d)",annotate(function(a, b = 0, /*c,*/ d) {
  console.log(a, b, c, d)
}))
annotate({})


0

আপনি "আর্গুমেন্ট" বৈশিষ্ট্যটি ব্যবহার করে কোনও ফাংশনে পাস হওয়া আর্গুমেন্টের মানগুলি অ্যাক্সেস করতে পারেন।

    function doSomething()
    {
        var args = doSomething.arguments;
        var numArgs = args.length;
        for(var i = 0 ; i < numArgs ; i++)
        {
            console.log("arg " + (i+1) + " = " + args[i]);  
                    //console.log works with firefox + firebug
                    // you can use an alert to check in other browsers
        }
    }

    doSomething(1, '2', {A:2}, [1,2,3]);    

যুক্তি হ্রাস করা হয় না? উপরে আয়নট জি স্ট্যানের পরামর্শ দেখুন।
বিকাশদে

বিকাশে ঠিক আছে। argumentsকোনও ফাংশনের উদাহরণের সম্পত্তি অ্যাক্সেস করা হ্রাস করা হয়। বিকাশকারী.মোজিলা.আর.এন.এন.
কোর_জবাস্ক্রিপ্ট_1.5_ উল্লেখ /

0

এটা বেশ সহজ।

প্রথমে একটি অবহেলিত রয়েছে arguments.callee- নামক ক্রিয়াকলাপের একটি রেফারেন্স। দ্বিতীয়ত যদি আপনার ফাংশনটির কোনও রেফারেন্স থাকে তবে আপনি সহজেই তাদের পাঠ্য উপস্থাপনা পেতে পারেন। তৃতীয় স্থানে আপনি যদি আপনার ফাংশনটি কনস্ট্রাক্টর হিসাবে কল করেন তবে আপনার ওবজেক্ট.কমস্ট্রাক্টরের মাধ্যমে আপনার একটি লিঙ্কও থাকতে পারে। এনবি: প্রথম সমাধানটি হ্রাস পেয়েছে সুতরাং যদি আপনি এটি ব্যবহার না করতে পারেন তবে আপনাকে অবশ্যই আপনার অ্যাপের আর্কিটেকচার সম্পর্কে ভাবতে হবে। আপনার যদি সঠিক ভেরিয়েবলের প্রয়োজন না হয় তবে কেবলমাত্র একটি ফাংশন অভ্যন্তরীণ ভেরিয়েবলের ভিতরে ব্যবহার করুনarguments কোনও যাদু ছাড়াই কোনও ।

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee

তারা সকলেই স্ট্রিং কল করে পুনরায় প্রতিস্থাপন করতে চলেছে যাতে আমরা একটি সহায়ক তৈরি করতে পারি:

// getting names of declared parameters
var getFunctionParams = function (func) {
    return String(func).replace(/[^\(]+\(([^\)]*)\).*/m, '$1');
}

কিছু উদাহরণ:

// Solution 1. deprecated! don't use it!
var myPrivateFunction = function SomeFuncName (foo, bar, buz) {
    console.log(getFunctionParams(arguments.callee));
};
myPrivateFunction (1, 2);

// Solution 2.
var myFunction = function someFunc (foo, bar, buz) {
    // some code
};
var params = getFunctionParams(myFunction);
console.log(params);

// Solution 3.
var cls = function SuperKewlClass (foo, bar, buz) {
    // some code
};
var inst = new cls();
var params = getFunctionParams(inst.constructor);
console.log(params);

জেএসের সাথে উপভোগ করুন!

ইউপিডি: জ্যাক অ্যালানকে আসলে কিছুটা আরও ভাল সমাধান সরবরাহ করা হয়েছিল। জিজে জ্যাক!


আপনি যদি এর SomeFuncNameপরিবর্তে arguments.callee(ফাংশন অবজেক্টের উভয় বিন্দু) ব্যবহার করেন তবে এটি আরও সহজ হতে পারে ।
রাফেল শোয়েকার্ট

0

সমাধান যাই হোক না কেন, এটি জঘন্য ফাংশনগুলিতে ভাঙতে হবে না, যার toString()চেহারা দেখতে কেবল বিরল:

function  (  A,  b
,c      ,d
){}

কনসোল থেকে স্ক্রিনশট

এছাড়াও, কেন জটিল নিয়মিত ভাব প্রকাশ করবেন? এটি এর মতো করা যেতে পারে:

function getArguments(f) {
    return f.toString().split(')',1)[0].replace(/\s/g,'').substr(9).split(',');
}

এটি প্রতিটি ফাংশনের সাথে সর্বত্র কাজ করে এবং একমাত্র রেজেক্স হ'ল হোয়াইটস্পেস অপসারণ যা এমনকি পুরো স্ট্রিংটির কারণে প্রক্রিয়াও করে না .split ট্রিকের ।


0

ঠিক আছে তাই যথেষ্ট উত্তর সহ একটি পুরানো প্রশ্ন। এখানে আমার অফারটি হ'ল হোয়াইটস্পেস সরিয়ে ফেলার সাধারণ কাজ বাদে রেইগেক্স ব্যবহার করে না। (আমার মনে রাখা উচিত যে "স্ট্রিপস_কমেন্টস" ফাংশনটি প্রকৃতপক্ষে শারীরিকভাবে অপসারণের চেয়ে এগুলি তাদের বাইরে রেখে দেয় that's কারণ এটি অন্য কোথাও আমি ব্যবহার করি এবং বিভিন্ন কারণে মূল অ-মন্তব্য টোকেনগুলির অবস্থান অক্ষত থাকতে হবে)

এটি কোডের মোটামুটি দীর্ঘতর ব্লক কারণ এই পেস্টটিতে একটি মিনি পরীক্ষার কাঠামো অন্তর্ভুক্ত।

    function do_tests(func) {

    if (typeof func !== 'function') return true;
    switch (typeof func.tests) {
        case 'undefined' : return true;
        case 'object'    : 
            for (var k in func.tests) {

                var test = func.tests[k];
                if (typeof test==='function') {
                    var result = test(func);
                    if (result===false) {
                        console.log(test.name,'for',func.name,'failed');
                        return false;
                    }
                }

            }
            return true;
        case 'function'  : 
            return func.tests(func);
    }
    return true;
} 
function strip_comments(src) {

    var spaces=(s)=>{
        switch (s) {
            case 0 : return '';
            case 1 : return ' ';
            case 2 : return '  ';
        default : 
            return Array(s+1).join(' ');
        }
    };

    var c1 = src.indexOf ('/*'),
        c2 = src.indexOf ('//'),
        eol;

    var out = "";

    var killc2 = () => {
                out += src.substr(0,c2);
                eol =  src.indexOf('\n',c2);
                if (eol>=0) {
                    src = spaces(eol-c2)+'\n'+src.substr(eol+1);
                } else {
                    src = spaces(src.length-c2);
                    return true;
                }

             return false;
         };

    while ((c1>=0) || (c2>=0)) {
         if (c1>=0) {
             // c1 is a hit
             if ( (c1<c2) || (c2<0) )  {
                 // and it beats c2
                 out += src.substr(0,c1);
                 eol = src.indexOf('*/',c1+2);
                 if (eol>=0) {
                      src = spaces((eol-c1)+2)+src.substr(eol+2);
                 } else {
                      src = spaces(src.length-c1);
                      break;
                 }
             } else {

                 if (c2 >=0) {
                     // c2 is a hit and it beats c1
                     if (killc2()) break;
                 }
             }
         } else {
             if (c2>=0) {
                // c2 is a hit, c1 is a miss.
                if (killc2()) break;  
             } else {
                 // both c1 & c2 are a miss
                 break;
             }
         }

         c1 = src.indexOf ('/*');
         c2 = src.indexOf ('//');   
        }

    return out + src;
}

function function_args(fn) {
    var src = strip_comments(fn.toString());
    var names=src.split(')')[0].replace(/\s/g,'').split('(')[1].split(',');
    return names;
}

function_args.tests = [

     function test1 () {

            function/*al programmers will sometimes*/strip_comments_tester/* because some comments are annoying*/(
            /*see this---(((*/ src//)) it's an annoying comment does not help anyone understand if the 
            ,code,//really does
            /**/sucks ,much /*?*/)/*who would put "comment\" about a function like (this) { comment } here?*/{

            }


        var data = function_args(strip_comments_tester);

        return ( (data.length==4) &&
                 (data[0]=='src') &&
                 (data[1]=='code') &&
                 (data[2]=='sucks') &&
                 (data[3]=='much')  );

    }

];
do_tests(function_args);

0

এখানে একটি উপায়:

// Utility function to extract arg name-value pairs
function getArgs(args) {
    var argsObj = {};

    var argList = /\(([^)]*)/.exec(args.callee)[1];
    var argCnt = 0;
    var tokens;
    var argRe = /\s*([^,]+)/g;

    while (tokens = argRe.exec(argList)) {
        argsObj[tokens[1]] = args[argCnt++];
    }

    return argsObj;
}

// Test subject
function add(number1, number2) {
    var args = getArgs(arguments);
    console.log(args); // ({ number1: 3, number2: 4 })
}

// Invoke test subject
add(3, 4);

দ্রষ্টব্য: এটি কেবল সমর্থনকারী ব্রাউজারগুলিতে কাজ করে arguments.callee


2
সেই সময় লুপটি প্রদত্ত কোডের সাথে অসীম লুপের ফলাফল দেয় (20171121at1047EDT হিসাবে)
জর্জ ২.০ হপ

@ জর্জ ২.০ হ্যাপ এটি নির্দেশ করার জন্য ধন্যবাদ। আমি উত্তর আপডেট করব।
এটেস গোলাল

আরগস.টোসোর্স কোনও ফাংশন (লাইন 20) নয় ... তবে আপনি এটিকে পরিবর্তন করলেও: কনসোল.লগ (args.toString ()); ... আপনি পাবেন ... [অবজেক্ট অবজেক্ট] ... আপনি যদি আরও ভাল করেন: কনসোল.লগ (JSON.stringify (আরগস));
জর্জি ২.০ আশা

২০০৯ সাল থেকে পরিস্থিতি বেশ কিছুটা বদলে গেছে!
এটস গোলাল

1
যদি কেউ এখানে প্রতিক্রিয়ার জন্য প্রদর্শিত হয় তবে এই ফাংশনটি দুর্দান্ত aw এটি কঠোর মোডে কাজ করবে না।
স্বতন্ত্র 11

0

দ্রষ্টব্য: আপনি যদি শীর্ষ সমাধানের সাথে ES6 পরামিতি ডেস্ট্রাকচারিং ব্যবহার করতে চান তবে নীচের লাইনটি যুক্ত করুন।

if (result[0] === '{' && result[result.length - 1 === '}']) result = result.slice(1, -1)

-1

জেএসএন থেকে গতিশীল ফাংশন প্যারামিটার স্ট্রিং মান চিত্র । যেহেতু আইটেম.প্রডাক্ট_আইমেজ ২ টি ইউআরএল স্ট্রিং, আপনি যখন প্যারামিটারের ভিতরে চেঞ্জ ইমেজ কল করবেন তখন আপনাকে এটিকে উদ্ধৃতিতে রাখা দরকার।

আমার ফাংশন অনক্লিক

items+='<img src='+item.product_image1+' id="saleDetailDivGetImg">';
items+="<img src="+item.product_image2+"  onclick='changeImage(\""+item.product_image2+"\");'>";

আমার ফাংশন

<script type="text/javascript">
function changeImage(img)
 {
    document.getElementById("saleDetailDivGetImg").src=img;
    alert(img);
}
</script>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.