测试自己属性的晦涩方法
Obscure way to test for own properties
在书 Javascript:权威指南第六版 David Flanagan 的第 147 页中,作者讨论了使用 for..in 循环遍历数组时的警告,以下是引用(粗体)是我的)
...For this reason you should not use a for/in loop on an array unless
you include an additional test to filter out unwanted properties.
You might use either of these tests:
for(var i in a) {
if (!a.hasOwnProperty(i)) continue; // Skip inherited properties
// loop body here
}
for(var i in a) {
// Skip i if it is not a non-negative integer
if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
}
现在第一个代码片段对我来说很清楚了,继承的属性将被跳过。
但是,我根本不清楚第二个代码片段。
根据我的理解,第二个代码片段将跳过 数组的任何非数字 属性(无论是自己的 属性 还是不是(不像第一个代码片段))
但如果是这样的话,你不能只使用像这样的简化测试:
if (Number(i) != i) continue;
那么作者为什么要用这么复杂的表达方式呢?
我是不是漏掉了什么?
不,这里有一些会失败的例子:
浮点数:
var a = [1, 2, 3];
a['1.5'] = 'busted';
for(var i in a) {
if (Number(i) != i) continue;
document.getElementById('output1').textContent += i + '\n';
}
for(var i in a) {
if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
document.getElementById('output2').textContent += i + '\n';
}
<h3>Number(i) != i</h3>
<pre id="output1"></pre>
<h3>String(Math.floor(Math.abs(Number(i)))) !== i</h3>
<pre id="output2"></pre>
负数:
var a = [1, 2, 3];
a['-5'] = 'busted';
for(var i in a) {
if (Number(i) != i) continue;
document.getElementById('output1').textContent += i + '\n';
}
for(var i in a) {
if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
document.getElementById('output2').textContent += i + '\n';
}
<h3>Number(i) != i</h3>
<pre id="output1"></pre>
<h3>String(Math.floor(Math.abs(Number(i)))) !== i</h3>
<pre id="output2"></pre>
这就是 Math.abs
和 Math.floor
呼叫所要防范的。
顺便说一句,对数组索引使用 for in 循环确实没有任何优势。我建议使用基于索引的循环。
在书 Javascript:权威指南第六版 David Flanagan 的第 147 页中,作者讨论了使用 for..in 循环遍历数组时的警告,以下是引用(粗体)是我的)
...For this reason you should not use a for/in loop on an array unless you include an additional test to filter out unwanted properties. You might use either of these tests:
for(var i in a) { if (!a.hasOwnProperty(i)) continue; // Skip inherited properties // loop body here } for(var i in a) { // Skip i if it is not a non-negative integer if (String(Math.floor(Math.abs(Number(i)))) !== i) continue; }
现在第一个代码片段对我来说很清楚了,继承的属性将被跳过。
但是,我根本不清楚第二个代码片段。
根据我的理解,第二个代码片段将跳过 数组的任何非数字 属性(无论是自己的 属性 还是不是(不像第一个代码片段))
但如果是这样的话,你不能只使用像这样的简化测试:
if (Number(i) != i) continue;
那么作者为什么要用这么复杂的表达方式呢?
我是不是漏掉了什么?
不,这里有一些会失败的例子:
浮点数:
var a = [1, 2, 3];
a['1.5'] = 'busted';
for(var i in a) {
if (Number(i) != i) continue;
document.getElementById('output1').textContent += i + '\n';
}
for(var i in a) {
if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
document.getElementById('output2').textContent += i + '\n';
}
<h3>Number(i) != i</h3>
<pre id="output1"></pre>
<h3>String(Math.floor(Math.abs(Number(i)))) !== i</h3>
<pre id="output2"></pre>
负数:
var a = [1, 2, 3];
a['-5'] = 'busted';
for(var i in a) {
if (Number(i) != i) continue;
document.getElementById('output1').textContent += i + '\n';
}
for(var i in a) {
if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
document.getElementById('output2').textContent += i + '\n';
}
<h3>Number(i) != i</h3>
<pre id="output1"></pre>
<h3>String(Math.floor(Math.abs(Number(i)))) !== i</h3>
<pre id="output2"></pre>
这就是 Math.abs
和 Math.floor
呼叫所要防范的。
顺便说一句,对数组索引使用 for in 循环确实没有任何优势。我建议使用基于索引的循环。