2011-12-23 11 views
5

zdefiniowałem dwie funkcje tablicy:Jak wywołać zewnętrzne "to" w funkcji wewnętrznej?

Array.prototype.remove = function(obj) { 
    var i = this.length; 
    while (i--) { 
     if (this[i] === obj) { 
      this.removeAt(i); 
     } 
    } 
}; 
Array.prototype.removeAll = function(array2) { 
    array2.forEach(function(item) { 
     this.remove(item); // remove not found!! 
    }); 
} 

Ale w funkcji removeAll, donosi, że function remove is not found. Naprawię to tak:

Array.prototype.removeAll = function(array2) { 
    var outer = this; 
    array2.forEach(function(item) { 
     outer.remove(item); 
    }); 
} 

Ale to jest brzydkie. Czy istnieje lepszy sposób?

+0

Nie sądzę, że jest to niesamowicie brzydkie i działa. "To" w twoim foreach zostało zmienione na pozycję w iteracji, więc nie widzę zbyt wiele możliwości. – Paddy

Odpowiedz

6

Przekazywanie this przez inną zmienną, jak to robisz, to podejście idiomatyczne. Nie ma w tym nic brzydkiego. (Częściej jednak wywoływana jest zmienna that lub self)

1

Istnieje Function.bind i podobne.

array2.forEach((function(item) { 
    this.remove(item); 
}).bind(this)); 

To nie jest technicznie tak samo, jak poprzedni „wewnętrzny ta” jest obecnie zasłonięta/Lost (a nowy funkcja owinięcie jest tworzony), ale działa dobrze w niektórych kontekstach.

W przeważającej części, wolę średnia var self = this ...

Szczęśliwa kodowania.

+0

O ile mi wiadomo, "Function.bind" to ECMAScript 5, który obsługuje tylko najnowsza przeglądarka (nie jest obsługiwana w IE8, FF3.6, FF3.6, Safari 4, Safari 5, Safari 5.1 i Opera 10.50 - 11.50) –

+0

@StefanGehrig Masz rację, stąd "i podobne" :-) Łatwo jest zaimplementować taką funkcję, a dokumentacja MDC stanowi taki przykład. Tę samą funkcjonalność można znaleźć w wielu frameworkach. –

+0

Chciałam tylko zwrócić uwagę na ten ważny szczegół ... ;-) –

2

Podając kolejny argument do forEach, który będzie kontekstem this w funkcji zwrotnej, W twoim przypadku this odnosi się do obiektu okna.

Array.prototype.removeAll = function(array2) { 

    array2.forEach(function(item) { 
     this.remove(item); 
    },this); 
} 
+0

Bardzo miło, nie wiedziałem o tym. –

+3

należy pamiętać, że nie jest to obsługiwane w wersjach ie8 i wcześniejszych. –

2

Alternatywą korzystania bind (jeśli trzeba wspierać starych przeglądarek i nie chcą przedłużyć Function.prototype) jest po prostu owinąć zwrotnego w funkcji immidate i paszy this jako argument tak:

Array.prototype.removeAll = function(array2) { 
    array2.forEach(function(outer){ 
    return function(item) { 
     outer.remove(item); 
    };}(this)); 
} 

lub możesz napisać prostą funkcję użytkową curry i używać jak to

function curry() { 
    var fn = Array.prototype.shift.call(arguments), 
     args = Array.prototype.slice.call(arguments); 
    return function curryed() { 
    return fn.apply(this, args.concat(Array.prototype.slice.call(arguments))); 
    }; 
}; 



Array.prototype.removeAll = function(array2) { 
    array2.forEach(curry(function(item) { 
     outer.remove(item); 
    },this)); 
} 

Jeśli nie przeszkadza Rozszerzając Function.prototype możesz użyć binda, jak to już opisali inni, możesz znaleźć doskonałe rozszerzenie kompatybilności na MDN tutaj: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

Powiązane problemy