如何在普通JS中实现jQuery .map()的等价物?

时间:2015-03-01 13:53:29

标签: javascript jquery

我正在努力将我的代码转换为普通的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));

有没有办法实现这个目标?

4 个答案:

答案 0 :(得分:2)

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;
        }                   
    }

答案 1 :(得分:1)

根据您发布的代码,您不需要使用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及以下版本不支持数组mapindexOf方法。如果您想支持这些浏览器,可以使用polyfill。 MDN为Array.prototype.indexOf建议this polyfill

答案 2 :(得分:1)

虽然上述答案适用于您的情况,但并非在所有情况下都是如此。 jQuery的映射创建一个新数组,并在将该函数应用于数组中的每个项目后返回该数组。

原型地图功能不会创建新数组,而只是将函数应用于每个项目。

这有时会产生相同的结果,而其他会产生不同的结果。

您将获得与此示例相同的结果:

$.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]

答案 3 :(得分:0)

如果有人感兴趣,如果为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;}});