2012-08-08 14 views
7

Czy mogę ograniczyć dostęp funkcji generowanej przez ciąg (przy użyciu konstruktora funkcji) do zakresów nadrzędnego/globalnego?Tworzenie piaskownicy wokół funkcji() w JavaScript

Na przykład: poniższy kod, taki jaki jest, drukuje false, ponieważ funkcja zapisuje/modyfikuje zmienną a w oknie.

window.a = 4; 
Function("a=3;")() 
console.log(a === 4); 

Czy mogę ograniczyć dostęp do okna/zakres dominującej i uczynić go wydrukować „true”?

Odpowiedz

5

Nie sądzę. Można wymienić globalnych, które chcesz chronić w parametrach tak, że ich cień:

window.a = 4; 
Function("a", "a=3;")() 
console.log(a === 4); 

ale funkcja ma mieć dostęp do globalnych bez względu na to, czego spróbować ... to dlaczego to się nazywa globalny.

W zależności od tego, co próbujesz zrobić, są inne work-aroundy, takie jak pracownicy sieci ... i jak zawsze, hidden iframe hacks.

+1

Cóż, można zdefiniować 'window' i' document' jako parametry, aby uniemożliwić bezpośredni dostęp do je (jak już powiedziałeś), a następnie dodaj 'use strict ';' do kodu, aby zapobiec niejawnej definicji globali. To może zadziałać. Oczywiście nie uniemożliwia to dostępu do istniejących globali, o ile nie "cienia" ich za pomocą parametrów. Może można iterować po wszystkich właściwościach 'window' i automatycznie utworzyć listę parametrów. –

+0

@FelixKling Brzmi nieźle, mam zamiar spróbować kilku hacków, aby sprawdzić, czy nadal mogę uzyskać dostęp do globalnego numeru – Esailija

+0

@FelixKling tutaj jest mój obecny, może działać, jeśli śledzisz 'Function' http://jsfiddle.net/dFmyd/ – Esailija

2

@ Odpowiedź Esailiji jest słuszna. Dodatkowo, zaleciłbym ograniczenie liczby globalnych zmiennych, które musisz chronić w pierwszej kolejności. Umieścić wszystko, co normalnie można umieścić w globalnej przestrzeni nazw w zakresie APP że sterowanie:

var APP = (function() { 
    return { 
     a: 4 
    }; 
}()); 

Nie ma sposobu, aby całkowicie ograniczyć dostęp do zasięgu globalnym, ale przynajmniej w ten sposób trzeba tylko chronić jeden obiekt : APP.

9

Oto dodatkowy pomysł, który może być dość potężny wraz z propozycją Esailiji (patrz uwagi na temat jego odpowiedzi na dyskusję).

Można utworzyć sztuczną ramkę iframe i użyć jej funkcji Function. Utworzona funkcja będzie miała domyślnie dostęp do zakresu elementu iframe, ale może się z niego wyrwać. Na szczęście łatwo temu zapobiec, tak jak zasugerowała Esailija.

mogłem wyobrazić funkcję być tak:

function sandboxed(code) { 
    var frame = document.createElement('iframe'); 
    document.body.appendChild(frame); 

    var F = frame.contentWindow.Function, 
     args = Object.keys(frame.contentWindow).join(); 

    document.body.removeChild(frame); 

    return F(args, code)(); 
} 

DEMO

Opcjonalnie można również dodać 'use strict'; do kodu.


Działa to przynajmniej w Chrome. Czy funkcja stworzona w ten sposób ma dostęp do globalnej zakresu iframe lub zasięgu globalnym strony mogą być łatwo testowane:

(function() { 
    var frame = document.createElement('iframe'); 
    document.body.appendChild(frame); 
    var same = window === frame.contentWindow.Function('return window;')(); 
    alert(same ? ':(' : ':)'); 
    document.body.removeChild(frame); 
}()); 
+1

Bardzo twórczy: D +1 otrzymuję ':)' we wszystkich oprócz IE8, gdzie rzuca 'nie obsługuje właściwości lub metody Funkcja' – Esailija

+0

@Esailija: Dzięki za testowanie (nie mam IE). Może źródło iframe musi być ustawione jawnie w IE (powinno to zrobić 'frame.src = 'about: blank'') lub własność jest inaczej nazwana inaczej (nie" contentWindow "). Jeśli musisz ustawić źródło, być może musisz poczekać na zdarzenie 'load' zanim będziesz mógł uzyskać dostęp do okna, ale oczywiście nie ma problemu, aby' sandboxed' zaakceptował wywołanie zwrotne dla wyniku :) –

+0

Tak, ustawiając 'frame .src' działa. – Esailija

Powiązane problemy