w pewnym momencie trzeba zaufać, co jest dostępne w oknie. Oznacza to albo buforowanie funkcji, z których planujesz korzystać, albo próby piaskowania kodu.
„simple” rozwiązanie wywołaniem call
jest tymczasowo ustawić właściwość:
var safeCall = (function (call, id) {
return function (fn, ctx) {
var ret,
args,
i;
args = [];
// The temptation is great to use Array.prototype.slice.call here
// but we can't rely on call being available
for (i = 2; i < arguments.length; i++) {
args.push(arguments[i]);
}
// set the call function on the call function so that it can be...called
call[id] = call;
// call call
ret = call[id](fn, ctx, args);
// unset the call function from the call function
delete call[id];
return ret;
};
}(Function.prototype.call, (''+Math.random()).slice(2)));
ten można wykorzystać jako:
safeCall(fn, ctx, ...params);
Należy pamiętać, że parametry przekazywane do safeCall będzie skumulowany razem w tablicy. Aby to poprawnie działało, potrzebujesz apply
, a ja próbuję tutaj uprościć zależności.
ulepszona wersja safeCall
dodając zależność do apply
:
var safeCall = (function (call, apply, id) {
return function (fn, ctx) {
var ret,
args,
i;
args = [];
for (i = 2; i < arguments.length; i++) {
args.push(arguments[i]);
}
apply[id] = call;
ret = apply[id](fn, ctx, args);
delete apply[id];
return ret;
};
}(Function.prototype.call, Function.prototype.apply, (''+Math.random()).slice(2)));
ten może być stosowany jako:
safeCall(fn, ctx, ...params);
Alternatywnym rozwiązaniem do bezpiecznego wywołanie połączenia jest użycie funkcje z innego kontekstu okna.
Można to zrobić po prostu tworząc nowe iframe
i funkcje przechwytywania z jego okna. Nadal musisz założyć pewną ilość uzależnienia od manipulacji DOM funkcje są dostępne, ale to się dzieje w kroku konfiguracji, tak że wszelkie przyszłe zmiany nie będą miały wpływu na istniejący skrypt:
var sandboxCall = (function() {
var sandbox,
call;
// create a sandbox to play in
sandbox = document.createElement('iframe');
sandbox.src = 'about:blank';
document.body.appendChild(sandbox);
// grab the function you need from the sandbox
call = sandbox.contentWindow.Function.prototype.call;
// dump the sandbox
document.body.removeChild(sandbox);
return call;
}());
ten może następnie być używany jako:
sandboxCall.call(fn, ctx, ...params);
Zarówno safeCall
i sandboxCall
są bezpieczne od przyszłości zmiany Function.prototype.call
, ale jak c widzą, że polegają na niektórych istniejących funkcjach globalnych, aby działały w środowisku wykonawczym. Jeśli złośliwy skrypt wykona przed tego kodu, twój kod nadal będzie zagrożony.
Zajęło mi 3 czytania ... ale dobre pytanie! –