干掉 htmlCollection 到 Array 调用
DRY up htmlCollection to Array calls
我有一个函数当前正在使用 JavaScript 中的 .getElementBy...
DOM 调用。
var $ = function (selector) {
var elements = [];
var lastSelector = selector.substring(selector.search(/[^#.]+$/), selector.length);
if(selector.includes('#') !== true || selector.includes('.') !== true) {
elements.push(document.getElementsByTagName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
}
return elements;
};
函数中还有许多其他 if 语句使用代码:
elements.push(document.getElementsByTagName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
或
elements.push(document.getElementsByClassName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
理想情况下,我想干掉重复的内容:
elements = Array.prototype.slice.call(elements[0]);
但我无法在 if
语句之前定义它,因为尚未填充元素。因此,它会尝试 运行 空数组上的代码并出错。
有什么建议吗?
您可以使用所有浏览器(包括 IE8+)中可用的标准 querySelectorAll()
,而不是使用选择器选择元素的自制有限函数。
至于将类似数组的对象(例如 DOM 集合)转换为真正的 Array
(Array.prototype.slice.call()
在您的代码中的用途),我使用以下函数:
var arrayFrom = function(arrayLike) {
if (Array.from) {
return Array.from(arrayLike);
}
var items;
try {
items = Array.prototype.slice.call(arrayLike, 0);
}
catch(e) {
items = [];
var count = arrayLike.length;
for (var i = 0; i < count; i++) {
items.push(arrayLike[i]);
}
}
return items;
};
或其以下简化版本,如果浏览器不支持将非 Array
参数传递给 Array.prototype.slice.call()
(IE8- 如果我没记错的话)无关紧要:
var arrayFrom = function(arrayLike) {
return Array.from
? Array.from(arrayLike);
: Array.prototype.slice.call(arrayLike, 0);
};
当然要考虑@marat-tanalin 的回答。在无法使用 querySelectorAll()
的情况下,以下对我有用,感谢@master565 的帮助:
开始,换行:
elements.push(document.getElementsByTagName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
在函数中:
function pushByTag(selector) {
elements.push(document.getElementsByTagName(selector));
elements = Array.prototype.slice.call(elements[0]);
}
干货很多。然后为 if
参数设置一个变量很有帮助:
if(selector.includes('#') !== true || selector.includes('.') !== true)
变成了:
var noClassOrId = selector.includes('#') !== true || selector.includes('.') !== true;
这两个重构都允许我将我的 if
语句单行化为我认为相当可读的内容:
if (noClassOrId) pushByTag(lastSelector);
我有一个函数当前正在使用 JavaScript 中的 .getElementBy...
DOM 调用。
var $ = function (selector) {
var elements = [];
var lastSelector = selector.substring(selector.search(/[^#.]+$/), selector.length);
if(selector.includes('#') !== true || selector.includes('.') !== true) {
elements.push(document.getElementsByTagName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
}
return elements;
};
函数中还有许多其他 if 语句使用代码:
elements.push(document.getElementsByTagName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
或
elements.push(document.getElementsByClassName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
理想情况下,我想干掉重复的内容:
elements = Array.prototype.slice.call(elements[0]);
但我无法在 if
语句之前定义它,因为尚未填充元素。因此,它会尝试 运行 空数组上的代码并出错。
有什么建议吗?
您可以使用所有浏览器(包括 IE8+)中可用的标准 querySelectorAll()
,而不是使用选择器选择元素的自制有限函数。
至于将类似数组的对象(例如 DOM 集合)转换为真正的 Array
(Array.prototype.slice.call()
在您的代码中的用途),我使用以下函数:
var arrayFrom = function(arrayLike) {
if (Array.from) {
return Array.from(arrayLike);
}
var items;
try {
items = Array.prototype.slice.call(arrayLike, 0);
}
catch(e) {
items = [];
var count = arrayLike.length;
for (var i = 0; i < count; i++) {
items.push(arrayLike[i]);
}
}
return items;
};
或其以下简化版本,如果浏览器不支持将非 Array
参数传递给 Array.prototype.slice.call()
(IE8- 如果我没记错的话)无关紧要:
var arrayFrom = function(arrayLike) {
return Array.from
? Array.from(arrayLike);
: Array.prototype.slice.call(arrayLike, 0);
};
当然要考虑@marat-tanalin 的回答。在无法使用 querySelectorAll()
的情况下,以下对我有用,感谢@master565 的帮助:
开始,换行:
elements.push(document.getElementsByTagName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
在函数中:
function pushByTag(selector) {
elements.push(document.getElementsByTagName(selector));
elements = Array.prototype.slice.call(elements[0]);
}
干货很多。然后为 if
参数设置一个变量很有帮助:
if(selector.includes('#') !== true || selector.includes('.') !== true)
变成了:
var noClassOrId = selector.includes('#') !== true || selector.includes('.') !== true;
这两个重构都允许我将我的 if
语句单行化为我认为相当可读的内容:
if (noClassOrId) pushByTag(lastSelector);