【问题标题】:Working equivalent for method .some() in javascript or jquery?javascript 或 jquery 中方法 .some() 的等效工作?
【发布时间】:2013-04-29 02:53:18
【问题描述】:

正在寻找“等效于 javascript 中的某些方法”和“如果在数组中则只返回一个值”,但只看到了确定变量类型或太多不必要的方法的答案。

我绕过了 html 中的所有输入,我想要这样的东西:

$('#goodsFilter')
    .find('input[type="number"]')
    .some(function(i,el){
        return (isNumber($(el).val())) ? 1 : 0;
});

但它会抛出一个错误:

“TypeError: 'undefined' is not a function”(例如 Safari 6.0.4)。


UPD:错误来自最后一行,是的,});。 isNumber:

function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); }

这应该检查每个输入信息是否存在,如果其中至少一个不为空,则返回 1,否则返回 0。 如何替换它以在大多数现代浏览器中工作?

统一更新: 问题解决了。我在选择答案时有点困惑。 @RobG 实现 .some() 的代码对于初学者(我也是)更容易理解,所以我换了票。

【问题讨论】:

  • $(el).val()el.value 更有效。 isNumber 函数有什么作用?您可能会使用return !isNaN(el.value);
  • 那么,.some() 是什么?为了完整起见
  • @Alexander——我猜它要么是内置的 Array.prototype.some 要么是本机仿真。
  • @RobG,好吧,如果它是内置的,那就错了,因为他在 jQuery 方法之后链接它 - 这太天真了
  • @RobG,感谢el.value 是的,这个函数是这样做的:function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); }

标签: javascript equivalent


【解决方案1】:

对于其他来此线程的人,您可以通过这种方式在 jQuery 对象上使用 some()

 $.makeArray($(...)).some(function(x) { ... })

jQuery.makeArray() 将 jQuery 对象转换为 Array,因此您可以在其上使用 some()


根据@alf-eaton 的建议,您可以使用:

$(…).toArray().some(function(node) { … })

【讨论】:

  • 或者更简单,使用toArray():$(…).toArray().some(function(node) { … })
  • 假设您已将 Array.prototype.some 添加到非 ES5 主机。 ;-) 接受的答案将 .some 添加到 jQuery 中,因此您只需执行 $(...).some(...).
【解决方案2】:

Array.prototype.some 返回真或假,所以你可以这样做:

.some(function(el){
        return !isNaN(el.value);
}

你不说错误是从哪里来的,是对isNumber的调用吗?

编辑

啊,所以你的问题是 some

如果你想要一个 jQuery some 方法,那么它至少应该模仿内置的 ECMAScript some,它有两个参数:一个回调函数和一个可选的 这个参数。

回调函数应采用三个参数:值、索引(可选)和用作this 参数的可选值。它应该按升序访问数字成员,并且只访问实际存在的成员。

所以它应该是这样的(注意 jQuery.fn === jQuery.prototype):

jQuery.fn.some = function(fn, thisArg) {
  var result;

  for (var i=0, iLen = this.length; i<iLen; i++) {

    if (this.hasOwnProperty(i)) {

      if (typeof thisArg == 'undefined') {
        result = fn(this[i], i, this);

      } else {
        result = fn.call(thisArg, this[i], i, this);
      }

      if (result) return true;
    }  
  }
  return false;
}

所以如果你现在想要,你可以这样做:

var result = $('#goodsFilter')
              .find('input[type="number"]')
              .some(function(el) {
                 return isNumber(el.value); 
              })? 1 : 0; 

或者您可以执行以下任一操作将 true 强制为 1 并将 false 强制为 0:

var result = Number($('#goodsFilter')
              .find('input[type="number"]')
              .some(function(el) {
                 return isNumber(el.value); 
              }));

var result = +($('#goodsFilter')
              .find('input[type="number"]')
              .some(function(el) {
                 return isNumber(el.value); 
              }));

以上只是简单测试,可选的thisArg参数可能是多余的。

【讨论】:

  • 哦,谢谢你的详细解答。如果我需要继续使用.some(),那么您的选择将帮助我少写多做。我在选择答案时有点困惑——“什么是 hack,什么是功能”。但是,您的实现代码.some() 对于初学者(我也是)更容易理解,所以我改变了我的投票。感谢您的关注和时间!
  • 您真的应该在 for 之前执行 if (typeof(thisArg) == 'undefined') { thisArg = window; } 以避免在每次循环迭代中出现这种情况。在循环内只需使用 .call 版本else 版本),它应该可以正常工作。
  • ECMA-262If a thisArg parameter is provided, it will be used as the this value for each invocation of callbackfn. If it is not provided, undefined is used instead。因此,如果未提供 thisArg,则不应将其设置为 window,它必须保持未定义。这样它将在严格模式下保持未定义,否则默认为窗口,并与 Array.prorotype.some 和 Array.string.some 保持一致。额外的测试是微不足道的开销,远低于$(this[i])
  • 请注意,您不能使用 fn.call(thisArg ...) 并将 thisArg 留给传递的任何内容,因此该方法是因为在 ES5 中,使用 callundefinedthisArg 将在函数中将 this 设置为 undefined,这又与内置的不一致一些.
  • 感谢您的意见,请尽可能彻底地测试它,如果您愿意,可以发布更好的东西。
【解决方案3】:

您可以使用.filter 方法,然后检查长度。

$('#goodsFilter')
    .find('input[type="number"]')
    .filter(function(i,el){ return isNumber($(el).val())); })
    .length > 0

【讨论】:

  • 谢谢@xdazz 的回答!但是为什么要使用 .filter() 呢? ` var n = $('#goodsFilter') .find('input[type="number"]') .filter(function(el){ console.log(el); return isNumber($(el).val( )); }) .length > 0;控制台.log(n); ` 在“jquery.js”中显示“TypeError:'undefined' 不是对象(评估 'o.nodeName.toLowerCase')”。感谢您提供使用 .length 的想法!它对我来说既简单又有用(:
  • @RobG, .some() 不起作用。完全适合我(请参阅帖子中的错误)。
  • 那么你需要一个“垫片”来提供它。您的问题只是说“它不起作用”而不说“它”是什么。
  • 我像这样使用 shim:&lt;script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"&gt;&lt;/script&gt;&lt;head&gt; 标记中,jquery 和我的脚本——就在&lt;/body&gt; 之前。如何改进我的问题?
  • 如果有任何元素 - 数字,此代码应返回 1。否则 - 0。尝试使用 .some() 时出现错误。 .each() 只返回数组元素,而不是一个布尔值。
【解决方案4】:

。 .在最基本的版本中,您可以只创建一个“some”函数:

function eSome(arr, f) { var i = 0, n = arr.length;
  for (;i<n;i++) { if (!i in arr) { continue }
    if (f(i, arr[i])) { return true; }
  } return false;
}

var list = [0, 1, 2, 3, 4, 5];
var testFunction = function (i, e) { return e === 2; };
console.log(eSome(list, testFunction));
//returns true and the loop ran only for the necessary three times.

。 .如果您想在 jQuery 对象中链接 .some 调用,您也可以将其添加为 jQuery 函数,使用类似这样的示例(现已测试和修复):

jQuery.fn.some = function (f) { var i = 0, n = this.length;
  for (;i<n;i++) { if (!i in this) { continue }
    if (f(i, this[i])) { return true; }
  }
  return false;
}

$('.a').some(function (i, el) { return ($(el).text() == 'weeee!'); });

。 .正如@RobG 在 cmets 中指出的那样,本机 Array.prototype.some 实现使用一组不同的参数调用您的回调。我正在关注 OP 的示例代码,但您可以在循环内使用 if (f(this[i], i, this)) { return true; } 来模仿 ECMA 实现的参数。

。 .您也可以在 Array.prototype.some 上填充它,但我强烈建议不要对内置原型进行任何直接修改。

【讨论】:

  • 太好了,这正是我想要的!链接看起来更有吸引力。
  • 你为什么使用for-in?你明白这在 JavaScript 中做了什么吗?此外,您正在创建一个隐式全局变量 l
  • 使用l.get(i)而不是l.eq(i)可能与其他jQuery回调更一致,然后示例将使用$(el).text()
  • @squint 我不是一个真正的 jQuery 人,所以我像在数组中一样使用“for in”(完全没有问题)。很好地指出它可能会导致 jQuery Object 和未声明的变量出现问题。我修好了,谢谢。 @Paulpro 我的想法是在循环中返回一个 jQuery 对象,这样用户就不必在每次迭代中再次调用 $()
  • @DiegoNunes——不要建议“填充”Array.prototype,已经有一个 Array.prototype.some。上述问题:1)参数的顺序与现有 some 方法中的顺序相反 2)现有 some 方法返回 true 和 false,不是 1 和 0 3) 本机方法只访问现有成员,上面假设一组连续的成员从 0 到 length 4) 没有意义分配 @ 987654333@,只使用 this 5) 使用 this[i] 比使用 l.eq(i)l.get(i) 更有效(这是 eqget i> 在内部使用并删除不必要的函数调用)。
【解决方案5】:

$(...).is(function) 也应该可以工作。 jQuery API 文档状态(强调我的):

根据选择器、元素或 jQuery 对象检查当前匹配的元素集,如果这些元素中至少有一个与给定参数匹配,则返回 true

因此,使用问题中的示例,我们会得到如下内容:

var result = $('#goodsFilter')
              .find('input[type="number"]')
              .is(function(idx, el) {
                  return isNumber(el.value); 
              })? 1 : 0; 

【讨论】:

  • 请记住,即使在找到至少 1 个 true 之后,此函数也会继续检查; 一些在找到匹配项后停止。
【解决方案6】:

Vanilla Javascript 中的实现(带有箭头语法)

function some(arr,callback){
  for(let i=0;i<arr.length;i++){
    if(callback(arr[i],i,arr)){
      return true;
    }
  }
  return false;
}

一些用途:

检查一个数组是否有偶数:

function hasEvenNum(arr){
  return arr.some(value=>{
    return value % 2 === 0;
  });
}

【讨论】:

    【解决方案7】:

    尝试使用[].prototype.call 方法,第一个参数将是一个类似数组的值,第二个参数是一个函数,将在每个元素上调用。

    [].some.call($('#goodsFilter').find('input[type="number"]'), function (el) {
        return isNumber($(el).val());
    });
    

    【讨论】:

      猜你喜欢
      • 2011-01-24
      • 2012-06-27
      • 2016-02-03
      • 1970-01-01
      • 2021-01-18
      • 1970-01-01
      • 2012-01-21
      • 2015-05-17
      • 1970-01-01
      相关资源
      最近更新 更多