Hvordan best å avgjøre om et argument ikke sendes til Javascript-funksjonen

stemmer
213

Jeg har nå sett 2 metoder for å bestemme om et argument er blitt ført til et Javascript-funksjon. Jeg lurer på om en metode er bedre enn den andre, eller hvis man er bare dårlig å bruke?

 function Test(argument1, argument2) {
      if (Test.arguments.length == 1) argument2 = 'blah';

      alert(argument2);
 }

 Test('test');

Eller

 function Test(argument1, argument2) {
      argument2 = argument2 || 'blah';

      alert(argument2);
 }

 Test('test');

Så vidt jeg kan fortelle, de begge resultat i det samme, men jeg har bare brukt den første før i produksjon.

Et annet alternativ som nevnt av Tom :

function Test(argument1, argument2) {
    if(argument2 === null) {
        argument2 = 'blah';
    }

    alert(argument2);
}

Per Juan kommentar, ville det være bedre å endre Tom forslag til:

function Test(argument1, argument2) {
    if(argument2 === undefined) {
        argument2 = 'blah';
    }

    alert(argument2);
}
Publisert på 04/01/2009 klokken 17:38
kilden bruker
På andre språk...                            


12 svar

stemmer
251

Det er flere forskjellige måter å sjekke om et argument ble sendt til en funksjon. I tillegg til de to du nevnte i ditt (original) spørsmålet - kontroll arguments.lengtheller ved hjelp av ||operatøren gir standardverdier - kan man også eksplisitt sjekke argumentene for undefinedvia argument2 === undefinedeller typeof argument2 === 'undefined'hvis man er paranoid (se kommentarer).

Bruk av ||operatøren har blitt standard praksis - alle de kule barna gjør det - men vær forsiktig: Standardverdien vil bli utløst hvis argumentet evalueres til false, noe som betyr at det kan faktisk være undefined, null, false, 0, ''(eller noe annet som Boolean(...)returnerer false).

Så spørsmålet er da å bruke som sjekk, som de alle gir litt ulike resultater.

Kontroll arguments.lengthutstillinger den 'mest riktig' atferd, men det kan ikke være mulig hvis det er mer enn ett valgfritt argument.

Testen for undefineder neste 'beste' - det bare 'svikter' hvis funksjonen er eksplisitt kalles med en undefinedverdi, som i all likelyhood bør behandles på samme måte som å utelate argument.

Bruken av ||operatøren kan utløse bruk av standardverdien selv om et gyldig argument er gitt. På den annen side, kan dens oppførsel faktisk være ønsket.

For å oppsummere: Bare bruk det hvis du vet hva du gjør!

Etter min mening, hjelp ||er også veien å gå hvis det er mer enn ett valgfritt argument og en ikke ønsker å passere et objekt bokstavelig som en midlertidig løsning for navngitte parametre.

En annen fin måte å gi standardverdier ved bruk arguments.lengther mulig ved å falle gjennom etikettene av en bryter uttalelse:

function test(requiredArg, optionalArg1, optionalArg2, optionalArg3) {
    switch(arguments.length) {
        case 1: optionalArg1 = 'default1';
        case 2: optionalArg2 = 'default2';
        case 3: optionalArg3 = 'default3';
        case 4: break;
        default: throw new Error('illegal argument count')
    }
    // do stuff
}

Dette har den ulempen at programmererens intensjon er ikke (visuelt) åpenbare og bruker 'magiske tall'; Det er derfor muligens feilutsatt.

Svarte 04/01/2009 kl. 17:46
kilden bruker

stemmer
3

Jeg beklager, jeg fremdeles ennå ikke kommentere, så å svare Tom svar ... I javascript (udefinert! = Null) == false faktisk som fungerer wont arbeide med "null", bør du bruke "udefinert"

Svarte 04/01/2009 kl. 17:48
kilden bruker

stemmer
12

Dette er en av de få tilfellene hvor finner jeg testen:

if(! argument2) {  

}

fungerer ganske bra og bærer riktig implikasjon syntaktisk.

(Med den samtidige begrensning at jeg ikke ville tillate en legitim nullverdi for argument2som har en annen mening, men det ville være veldig forvirrende.)

REDIGERE:

Dette er et veldig godt eksempel på en stilistisk forskjell mellom løst-skrevet og sterke skrevet språk; og en stilistisk alternativ som javascript gir i bøtter og spann.

Min personlige preferanse (med ingen kritikk ment for andre preferanser) er minimalisme. Jo mindre koden har å si, så lenge jeg er konsekvent og konsis, jo mindre noen andre har å forstå til riktig antyde min mening.

En implikasjon av at preferanser er at jeg ikke vil - ikke finner det nyttig å - hoper seg opp en haug med typeavhengighetstester. I stedet prøver jeg å gjøre koden mener hva det ser ut som det betyr; og bare test for hva jeg virkelig trenger å teste for.

En av de aggravations jeg finner i noen andres kode er som ønsker å finne ut hvorvidt de forventer, i større sammenheng, for å faktisk kjøre inn i de sakene de tester for. Eller hvis de prøver å teste for alt mulig, på sjansen for at de ikke forventer sammenheng helt nok. Hvilket betyr at jeg ender opp med å måtte spore dem grundig i begge retninger før jeg kan trygt refactor eller endre noe. I figuren at det er en god sjanse de kanskje har satt de forskjellige testene på plass fordi de forutså omstendigheter der de skulle være nødvendig (og som vanligvis ikke er klart for meg).

(Jeg anser at en alvorlig ulempe i måten disse folkene bruke dynamiske språk. Altfor ofte folk ikke ønsker å gi opp alle de statiske tester, og ender opp med falsk det.)

Jeg har sett dette mest glaringly i å sammenligne omfattende Actionscript 3 kode med elegant javascript-kode. Den AS3 kan være 3 eller 4 ganger størstedelen av js, og påliteligheten jeg mistenker er i det minste noe bedre, nettopp på grunn av antallet (3-4 ganger) av kode beslutningene som ble gjort.

Som du sier, Shog9, YMMV. : D

Svarte 04/01/2009 kl. 17:53
kilden bruker

stemmer
7

Det er betydelige forskjeller. La oss sette opp noen test tilfeller:

var unused; // value will be undefined
Test("test1", "some value");
Test("test2");
Test("test3", unused);
Test("test4", null);
Test("test5", 0);
Test("test6", "");

Med den første metoden du beskriver, vil bare den andre testen bruker standardverdien. Den andre metoden vil misligholde alle, men den første (som JS vil konvertere undefined, null, 0, og ""i boolean false. Og hvis du skulle bruke Tom metode, vil bare den fjerde testen bruke standard!

Hvilken metode du velger er egentlig avhengig av din tiltenkte atferd. Hvis andre enn verdiene undefineder tillatte for argument2, så vil du sannsynligvis ha litt variasjon på den første; hvis en ikke-null, er ikke-null, ikke-tom verdi er ønskelig, da den annen metode er ideelt - ja, blir det ofte brukt til raskt å eliminere et slikt bredt område av verdier fra betraktning.

Svarte 04/01/2009 kl. 17:57
kilden bruker

stemmer
6
url = url === undefined ? location.href : url;
Svarte 21/08/2012 kl. 09:51
kilden bruker

stemmer
2

Det kan være praktisk å nærme argument deteksjon av fremkaller din funksjon med et objekt av valgfrie egenskaper:

function foo(options) {
    var config = { // defaults
        list: 'string value',
        of: [a, b, c],
        optional: {x: y},
        objects: function(param){
           // do stuff here
        }
    }; 
    if(options !== undefined){
        for (i in config) {
            if (config.hasOwnProperty(i)){
                if (options[i] !== undefined) { config[i] = options[i]; }
            }
        }
    }
}
Svarte 05/03/2013 kl. 02:22
kilden bruker

stemmer
15

Hvis du bruker jQuery, ett alternativ som er fin (spesielt for kompliserte situasjoner) er å bruke jQuery forlenge metode .

function foo(options) {

    default_options = {
        timeout : 1000,
        callback : function(){},
        some_number : 50,
        some_text : "hello world"
    };

    options = $.extend({}, default_options, options);
}

Hvis du kaller funksjonen så slik ut:

foo({timeout : 500});

Alternativ variable vil da være:

{
    timeout : 500,
    callback : function(){},
    some_number : 50,
    some_text : "hello world"
};
Svarte 30/04/2013 kl. 18:16
kilden bruker

stemmer
2

Hvorfor ikke bruke !!operatør? Dette operatør, plassert foran variabelen, snu den til en boolsk (hvis jeg har forstått godt), så !!undefinedog !!null(til og med !!NaN, som kan være ganske interessant) vil returnere false.

Her er en exemple:

function foo(bar){
    console.log(!!bar);
}

foo("hey") //=> will log true

foo() //=> will log false
Svarte 30/12/2015 kl. 13:01
kilden bruker

stemmer
1

Noen ganger kan også være lurt å sjekke for type, spesielt hvis du bruker funksjonen som getter og setter. Følgende kode er ES6 (vil ikke kjøre i ECMAScript 5 eller eldre):

class PrivateTest {
    constructor(aNumber) {
        let _aNumber = aNumber;

        //Privileged setter/getter with access to private _number:
        this.aNumber = function(value) {
            if (value !== undefined && (typeof value === typeof _aNumber)) {
                _aNumber = value;
            }
            else {
                return _aNumber;
            }
        }
    }
}
Svarte 18/05/2016 kl. 19:06
kilden bruker

stemmer
0

Det er en vanskelig måte i tillegg til å finne, om en parameter føres til en funksjon eller ikke . Ta en titt på eksempelet nedenfor:

this.setCurrent = function(value) {
  this.current = value || 0;
};

Denne nødvendige betyr at hvis verdien av valueer ikke til stede / bestått - angi den til 0.

Ganske kul he!

Svarte 24/03/2017 kl. 18:44
kilden bruker

stemmer
2

I ES6 (ES2015) kan du bruke standardparametere

function Test(arg1 = 'Hello', arg2 = 'World!'){
  alert(arg1 + ' ' +arg2);
}

Test('Hello', 'World!'); // Hello World!
Test('Hello'); // Hello World!
Test(); // Hello World!

Svarte 23/07/2017 kl. 22:14
kilden bruker

stemmer
-1

fnCalledFunction (Param1, Param2, window.YourOptionalParameter)

Hvis ovenfor funksjonen kalles fra mange steder, og du er sikker på første 2 parametere sendes fra alle der, men ikke sikker på om tredje parameter så kan du bruke vinduet.

window.param3 vil håndtere hvis det ikke er definert fra den som ringer metoden.

Svarte 28/06/2018 kl. 05:56
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more