存在编码不良的脚本,需要包含在网页中。
这些脚本通过以下方式污染全局范围:
Object
和Array
)及其原型我希望包含脚本而不会产生不良副作用。我认为可以通过在iframe中加载脚本并将对象导出为父窗口的属性来实现。这是我到目前为止所得到的:
<script>
(function(){
var g=this, frameIndex=frames.length, f=document.createElement('iframe');
// hide it like this instead of display:none, because some old browser ignores
// iframes with display:none, or is this an ancient habit I can drop?
f.style.width='0px'; f.style.height='0px';
f.style.border='none'; f.style.position='absolute';
// append it to document.body or document.documentElement?
// documentElement seems to work before body is loaded,
// but is it cross-browser safe?
document.body.appendChild(f);
// window object for our iframe
var w=frames[frameIndex];
// callback function pulls the object into the current window when script loads
w.cb=function(){ g.SomeObject=w.SomeObject };
// will this work on IE, or do I need to use document.createElement?
// wanted to avoid document.createElement in this case because I'm not sure
// whether to call it from window.document or frames[frameIndex].document
w.document.innerHTML='<script onload="cb()" src="myscript.js"><\/script>';
}());
</script>
如果脚本修改了内置原型并将其移动到另一个窗口,或者我父窗口的内置插件是否保持干净并且一切都“正常工作?”
<是否存在潜在的破坏? / LI>这个想法是否适用于'大多数'浏览器,还是有一个显示阻止?到目前为止,还没有对chrome和moz之外的任何东西进行过测试。
我想在将对象拉入当前窗口后删除iframe,但如果删除iframe,moz将丢失对象引用。有没有人知道如何解决这个问题?
这已经完成,还是有更好的方法来实现我的目标?如果是这样,我应该寻找的脚本或技术的名称是什么?
(问题移植自here)
答案 0 :(得分:1)
要复制一个函数,你可以把它转换成一个字符串然后评估它....下面的代码也证明了这样做后iframe可以删除,你的副本保持不变。
使用FF的以下代码示例
Child.html代码段
<script>
//
// modify the prototype
//
Object.prototype.test = function(msg)
{
alert(msg);
};
//
// Simply declare a function
//
var whoo_hoo = function(){alert("whoo hoo");}
</script>
使用iframe的父级:
<iframe id="help_frame" src="http://localhost/child.html"
onLoad="javascript:Help.import_functions(this)"></iframe>
<script>
var Help = {
imported_function :null,
import_functions : function(iframe)
{
this.imported_function = String(iframe.contentWindow.whoo_hoo);
eval("this.imported_function = " + this.imported_function);
iframe.parentNode.removeChild(iframe);
//
// displays 'whoo hoo' in an alert box
//
this.imported_function();
try
{
//
// If the Object prototype was changed in the parent
// this would have displayed 'should not work' in an alert
//
this.test('should not work');
}
catch(e){alert('object prototype is unmodified');}
},
</script>
答案 1 :(得分:1)
这可能是一个可能的解决方案:
我认为这应该解决所有问题。
根据我的建议,你的样本
var badA = "hahaha";
this.badB = "hehehe";
badC = "hohoho";
String.prototype.star = function(){ return '***' + this + '***' }
var somethingUseful = {
doStuff: function () {
alert((badA + badB + badC).star());
}
}
应该是这样的
// Identifies the added properties to prototypes (ie String and Function)
// for later filtering if you need a for-in loop.
var stringAddons = [];
var functionAddons = []
var _string = new String();
var _function = function() {};
for (var property in _string) { if (!_string.hasOwnProperty(property)) { stringAddons.push(property); }}
for (var property in _function) { if (!_function.hasOwnProperty(property)) { functionAddons.push(property); }}
// Wraps the undeclared identifiers
var global = function()
{
this.badA = "hahaha";
this.badB = "hehehe";
this.badC = "hohoho";
String.prototype.star = function(){ return '***' + this + '***' }
this.somethingUseful = {
doStuff: function () {
alert((global.badA + global.badB + global.badC).star());
}
}
}
var global = new Global();
global.somethingUseful.doStuff();
棘手的部分是制作所有未声明的标识符全局属性。 也许一个好的正则表达式脚本可以成功。我对正则表达式不太好:)。
答案 2 :(得分:1)
根据加布里埃尔的回答发表评论的代码..
var r = {
init : null,
_init: function(){
var obj = new XMLHttpRequest();
obj.onreadystatechange = function(){
if ((this.status == 200) && this.readyState==4){
try{
eval("r.init = function(){" + this.responseText + "}");
r.init();
} catch(e){/*something bad in the script...*/}
}
}
obj.open("GET","/jspolute_bad.js", true);
obj.send();
}
}
r._init();
如果将方法添加到原型中,如果一个或两个导出的函数在外部代码中修改该方法,则可能会遇到麻烦。我想到的繁琐的解决方案是在为array.prototype,string.prototype评估它之前使用Regex的responseText并修复它。将尝试并让你知道..但它主要迎合简单的脚本。
答案 3 :(得分:0)
到目前为止,答案似乎都没有像iframe一样好用。我相信iframe监狱将成为问题的解决方案。我现在把我现有的解决方案作为答案,因为它似乎比目前提供的其他答案更好。我真的很想将这种iframe技术改进成万无一失的技术,我很想了解修改过的原型是如何工作的。此示例适用于chrome和moz。
var badA = "hahaha";
this.badB = "hehehe";
badC = "hohoho";
String.prototype.star = function(){ return '***' + this + '***' }
var somethingUseful = {
doStuff: function () {
alert((badA + badB + badC).star());
}
}
<html>
<head>
<script>
/**
safeLoad - load a script in an iframe jail
@param {String} scriptPath path to a javascript file
@param {String} target name of global object to import
@param {Function} callback function to execute after script loads
*/
function safeLoad (scriptPath, target, callback) {
var g=this, f=document.createElement('iframe'), frameIndex=frames.length;
f.style.width='0px';
f.style.height='0px';
f.style.border='none';
f.style.position='absolute';
f.onload=function(){
var w=frames[frameIndex];
var s=w.document.createElement('script');
s.src=scriptPath;
s.onload=function(){
g[target]=w[target];
if (callback && callback.apply) callback(w);
};
w.document.body.appendChild(s);
}
document.documentElement.appendChild(f);
}
</script>
<script>
safeLoad('test.js', 'somethingUseful', function init () {
// next line should give ***hahahahehehehohoho***
somethingUseful.doStuff();
// next line should give undefinedundefinedundefinedundefined
alert(typeof badA + typeof badB + typeof badC + String.prototype.star);
});
</script>
</head>
</html>