2016-05-19 12 views
7

Rozważmy następujący kod: powyżejzdefiniować funkcję z zagnieżdżonych funkcji i domyślnej funkcji

function test() { 
    this.foo = function() { 
     console.log('foo'); 
     return; 
    } 

    this.bar = function() { 
     console.log('bar'); 
     return; 
    } 
} 

var action = new test(); 
action.foo(); //prints 'foo' 

Kod działa poprawnie w przypadku muszę zadzwonić akcję foo lub bar wewnątrz działania test. Jednak sama akcja powinna być funkcją wywoływalną. Myślałem, że byłoby super, gdyby JavaScript pozwolił mi stworzyć coś podobnego (patrz poniżej), ale, zgodnie z oczekiwaniami, mówi:

TypeError: action is not a function

function test() { 
    this.foo = function() { 
     console.log('foo'); 
     return; 
    } 

    this.bar = function() { 
     console.log('bar'); 
     return; 
    } 

    return function() { 
     console.log('default'); 
     return; 
    }(); 
} 

var action= new test(); 
action();  //prints 'default' 
action.bar(); //printf 'bar' 

Czy to możliwe, aby osiągnąć coś podobnego?

Odpowiedz

4

Jest to możliwe. Wystarczy utworzyć funkcję wewnątrz i dodać inne właściwości bezpośrednio do obiektu funkcyjnego:

function test() { 
 
    
 
    var result = function() { 
 
     console.log('default'); 
 
    }; 
 
    
 
    result.foo = function() { 
 
     console.log('foo'); 
 
     return; 
 
    } 
 

 
    result.bar = function() { 
 
     console.log('bar'); 
 
     return; 
 
    } 
 

 
    return result; 
 
} 
 

 
var test = new test(); 
 
test();  //prints 'default' 
 
test.bar(); //printf 'bar'

+0

mogą one funkcję prototypowania być zagnieżdżonym? Powiedzmy, że 'test.foo' jest tak naprawdę funkcją z możliwymi metodami, takimi jak' test.foo.buzz' lub 'test.foo.bar'. – lolbas

1

W javascript można dodawać właściwości również do funkcji. Aby zrobić coś takiego:

function test() { 
    function defaultFn() { 
     console.log('default'); 
    } 
    defaultFn.foo = function() { 
     console.log('foo'); 
     return; 
    } 
    defaultFn.bar = function() { 
     console.log('bar'); 
     return; 
    } 
    return defaultFn; 
} 
0

To wywoła poniższy kod jak najszybciej utworzyć instancję tej funkcji. Podobnie jak _konstruktor.

return function() { 
     console.log('default'); 
     return; 
    }(); 
+0

Tak, rzeczywiście, źle zrozumiałem błąd parsera i kompiluje on dobrze, jednak nadrzędny konstruktor nie był celem, który chciałem osiągnąć. – lolbas

0

Mam coś jak następuje:

function userClass(name, func) { 
    this.name = name; 
    this.func = func;  
} 

function test(flag) { 
    this.foo = function() { 
     console.log('foo'); 
     return; 
    } 

    this.bar = function() { 
     alert('bar'); 
     return; 
    } 

    return function() { 
      var obj = {}; 
     obj["bar"] = new userClass("bar", function(){alert('bar');}); 
     alert('default'); 
     return obj; 
    }(); 
} 

var test = new test(); 
//test();  //prints 'default' 
console.log(test); 
test.bar.func(); //printf 'bar' 

JSFiddle

1

Podczas gdy inni, że zwrócił uwagę, że jest to możliwe, po prostu chciałem zwrócić uwagę, że to jest na ogół złą praktyką funkcje konstruktora zwracają obiekt, który nie jest instancją utworzoną przez new.

Patrząc na przykład:

function Test() { 
    this.foo = function() {} 

    this.bar = function() {} 

    return function() {}(); 
} 

var test = new Test(); 

(I przemianowany swoją funkcję test do Test ponieważ jest to konwencja do wielkich funkcji, które można oczekiwać, aby być wywołana z new)

Co JS kiedy wywołanie new Test() polega na tym, że tworzy nową instancję obiektu {} i przekazuje ją do funkcji Test() jako kontekstu this. Domyślnie ten obiekt jest również zwracany przez wywołanie new.

Więc to, co robisz, to dołączanie funkcji foo i bar do nowo utworzonego obiektu isntance.

Wtedy return inna funkcja, która następnie zostaje zwrócony na podstawie zaproszenia do new Test() zamiast instancji obiektu, który ma foo i bar na to ... że obiekt jest po prostu stracił/śmieci zebrane.

"Zwracanie innego obiektu z funkcji konstruktora" jest złym zwyczajem i prowadzi do zamieszania.Plus to się dzieje:

function Test() {} 

var test = new Test(); 
test instanceof Test; // returns TRUE 

jednak jeśli coś jeszcze powrócić:

function Test() { 
    return function() {}; 
} 

var test = new Test(); 
test instanceof Test; // returns FALSE (confusing!!!) 

byłoby czystsze uniknąć new i po prostu zrobić:

function test() { 
    var newFunc = function() { 
     console.log('default'); 
     return; 
    }; 

    newFunc.foo = function() { 
     console.log('foo'); 
     return; 
    } 

    newFunc.bar = function() { 
     console.log('bar'); 
     return; 
    } 

    return newFunc; 
} 

var t = test(); 
t();  // default 
t.foo(); // foo 
t.bar(); // bar 
+0

To jest naprawdę dobre wytłumaczenie na temat zwracania obiektu innego niż "to" i zasługuje na upominek, jednak w moim przypadku robiłem to tylko w celu pokazania, aby pokazać, co chciałem osiągnąć. – lolbas

Powiązane problemy