我有一个类似于数组的对象。这意味着它具有数字属性(0
,1
,2
...)和length
属性。
在原型中,我声明了一种方法来清除它,如下所示:
'clear': function() {
Array.prototype.splice.call(this, 0, this.length);
return this;
}
这在大多数浏览器中都能正常工作,但不适用于Internet Explorer。
获取一个完全有效的类似数组的对象:
var arrayLike = {
length: 3,
'0': 'a',
'1': 'b',
'2': 'c'
};
并将其拼接清楚:
Array.prototype.splice.call(arrayLike, 0, arrayLike.length);
在符合标准的浏览器上,这是正确的结果:
arrayLike.length == 0 ;
arrayLike[0] == undefined;
arrayLike[1] == undefined;
arrayLike[2] == undefined;
但是在IE 8中,这就是你得到的:
arrayLike.length == 0 ; // (!!)
arrayLike[0] == 'a';
arrayLike[1] == 'b';
arrayLike[2] == 'c';
是的,它甚至不起作用,它可以按照它想要的那样工作。
现在,我认为Array.prototype.splice.call
是本机清除类数组对象的唯一方法。我可以在IE8的私有副本中填充它,也许(对其他浏览器造成一次性能损失,但只有一次)。
或许还有另一种清除对象的方法?这在IE8中也是原生的吗?有没有我没见过的东西?
Ps:JsFiddle让你在IE8中运行。
答案 0 :(得分:1)
IE搞砸了......似乎即使你扩展了一个数组对象,IE搞砸了拼接。请参阅下面的测试:
// create an object constructor
var arrayLike = function() {
this.clear = function() {
this.splice( 0, this.length );
};
};
// use prototypical inheritance to inherit array functionality
arrayLike.prototype = [];
arrayLike.constructor = arrayLike;
// testing clear method fails...
var arrayLikeObject = new arrayLike();
arrayLikeObject.push( 'foo' );
console.log( arrayLikeObject[ 0 ] ); // outputs foo
arrayLikeObject.clear();
console.log( arrayLikeObject[ 0 ] ); // outputs foo
// yet the same method works on a normal array
var test = [];
test.push( 'foo2' );
test.splice( 0, test.length );
console.log( test[0] ); // outputs undefined
到底是什么IE ...
答案 1 :(得分:0)
我的直觉是你不应该在不是 Array.prototype.splice.call
的对象上使用Array
。对我来说,这似乎是黑客。
是的,它可能适用于大多数浏览器,但是您尝试在不属于该原型的对象上执行为一个原型设计的操作。我不喜欢IE浏览器,但这对我来说就像hackery一样,所以当它无法解决时你就不会哭。
我的2¢是使用Array
作为原型创建新的“Array
- like”对象,例如:
var ArrayLike = function(){
this.push.apply(this, arguments);
};
ArrayLike.prototype = Array.prototype;
ArrayLike.constructor = function(){};
ArrayLike.prototype.clear = function(){
// Array.prototype.splice.call(this, 0, this.length);
this.splice(0, this.length); // all of Array's methods are available to ArrayLike
return this;
}
var arrayLike = new ArrayLike('a', 'b', 'c');
console.log(arrayLike.length); // 3
arrayLike.clear(); // clear
console.log(arrayLike.length); // 0
...或者编写自己的方法。
答案 2 :(得分:0)
伙计,这很有趣。在IE8中,Array.prototype.splice
以 非常奇怪的方式 被打破。
我必须告诉你(如果你愿意,请跳过它,下面的解决方案)。
如您所见,这会在IE中警告“a”,对吗?
// Create an array-like object.
var arrayLike = {
length: 1,
'0': 'a'
};
// Clean it with splice. This should work in ES5.
Array.prototype.splice.call(arrayLike, 0, 2);
// Note that IE does set the length to zero. We need to check an item.
alert(arrayLike[0]);
现在,如果我们将其设置为无效长度怎么办?特别是对于这种效果,“3”(“2”将在IE8中产生相同的结果)。
现在,在IE8中这个警报是什么?
var arrayLike = {
length: 3, // <--
'0': 'a'
};
Array.prototype.splice.call(arrayLike, 0, 2);
alert(arrayLike[0]);
无论如何,我不会依赖那种奇怪的工作方式,我不想在制作中有一个非常奇怪的错误。 您可以通过以下方式解决问题:
首先,您的代码是否包含在IIFE中?你应该。其次,检查您是否拥有Array.prototype.splice
的私人副本。我在IIFE开始时宣布这些事情。
// Call it whatever you want.
var protoSplice = Array.prototype.splice;
然后,在一些初始化方法上(或在你想要的任何时候,确保它在使用之前),调用polyfill方法。
polyfill();
调用测试和修复。
function polyfill() {
// ...
genericSpliceWorks() || fixGenericSplice();
// ...
}
以下是它使用的方法:
function genericSpliceWorks() {
// Create an array-like object.
var arrayLike = {
length: 1,
'0': true
};
// Clean it with splice. This should work in ES5.
protoSplice.call(arrayLike, 0, 2);
// Note that IE does set the length to 0. We need to check an item.
return !arrayLike[0];
}
function fixGenericSplice() {
// Re-set our local protoSplice variable to something that works.
// Note: this implementation only works with the first two arguments
// of splice. This means that it does not add extra elements to the
// array. It's as much as I need.
protoSplice = function(index, count) {
// If count is more than zero, run until it's zero, decrementing
// each time.
while (count--) {
// Remove an array item from index, while incrementing index
// for the next time.
delete this[index++];
// Decrement the length.
this.length--;
}
};
}
钽哒!它现在有效:)