如何在纯JS中实现jQuery.map()的等效功能

How to implement the equivalent for jQuery .map() in plain JS?

本文关键字:功能 map jQuery JS 实现      更新时间:2023-09-26

我正在努力将我的代码转换为纯JS,这真的很难。我需要一个函数来获得真正的滚动容器,而我拥有的这个函数是这样的,使用.map()

//get true container for scroll events
function getScrollContainer(c) {
	return $(c).map(function() {
		var cnt = this,
			isWin = !cnt.nodeName || $.inArray( cnt.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;
			if (!isWin) return cnt;
		var doc = (cnt.contentWindow || cnt).document || cnt.ownerDocument || cnt;
		return /webkit/i.test(navigator.userAgent) || doc.compatMode == 'BackCompat' ?
			doc.body :
			doc.documentElement;
    });
}
console.log(getScrollContainer(window));

有办法做到这一点吗?

Map只是一种奇特的方式来表示"将此函数应用于列表中的每个元素",因此它可以在for循环中轻松实现。

类似这样的东西:(不完美或测试,但应该给你一个想法)

    function getScrollContainer(c) {
        c = Object.prototype.toString.call( c ) === '[object Array] ? c : [c];
        for (var i = 0; i < c.length; i++) {
            var cnt = c[i],
                isWin = !cnt.nodeName || indexOf(cnt.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;
                if (!isWin) return cnt;
            var doc = (cnt.contentWindow || cnt).document || cnt.ownerDocument || cnt;
            return /webkit/i.test(navigator.userAgent) || doc.compatMode == 'BackCompat' ?
                doc.body :
                doc.documentElement;
        }                   
    }

根据您发布的代码,您不需要使用map方法。您的函数只接受一个参数,因此您可以删除var cnt = this,行并使用c参数。现在,您的函数不返回length为1的jQuery封装数组,而是返回HTMLElement对象。

如果要将数组传递给函数,可以使用Array.prototype.map方法:

function getScrollContainer(c) {
    return c.map(function(value, index, arr) {
        // ...
    });
}
console.log(getScrollConainer([window, 'foo']));

要替换jQuery $.inArray实用程序函数,可以使用Array.prototype.indexOf方法:

['iframe','#document','html','body'].indexOf(cnt.nodeName.toLowerCase()) != -1

请注意,IE8及以下版本不支持Array mapindexOf方法。如果你想支持这些浏览器,你可以使用polyfill。MDN建议对CCD_ 12进行这种多填充。

虽然以上答案在您的情况下有效,但并非在所有情况下都有效。jQuery的map创建一个新数组,并在将函数应用于数组中的每个项后返回该数组。

原型映射函数不创建新的数组,而是简单地将该函数应用于每个项。

这有时会产生相同的结果,而另一些则会产生不同的结果。

对于这个例子,你会得到相同的结果:

$.map([1,2,3], function(i){ return i+1; });
 => [2,3,4]
[1,2,3].map(function(i){ return i+1; });
 => [2,3,4]

然而,以下示例将提供不同的结果:

$.map([1,2,3], function(i){ if(i > 1){ return i; } });
 => [2,3]
[1,2,3].map(function(i){ if(i > 1){ return i; } });
 => [undefined,2,3]

如果有人感兴趣,如果您为Array原型创建了一个新函数,您可以在.map()中使用if语句:

Array.prototype.custom_Map = function(x) {
arr = [];
for (var i = 0; i < this.length; i++)
var _this = (x(this[i], i, this));
if(_this !== null) {
    arr.push(_this);
    return arr;
    };

您可以通过以下方式使用它:

x.custom_Map(function(a){ if(a>0) {return true;}});