使用forEach模仿$ jQuery选择器会产生undefined

时间:2018-04-07 14:14:25

标签: javascript jquery selectors-api

我知道有很多轻量级JavaScript库可以完成这项工作,但出于我的好奇心,我尝试了这个:

function $(a) {

    b = document.querySelectorAll(a);

  [].forEach.call(b, function(d) {

    return d

  });
}

$(".tobered,#illbered").style.border = '1px solid #f00'

当然我的控制台说:TypeError: $(...) is undefined

让我们更清楚:

简化'功能':

var $ = document.querySelectorAll.bind(document)

调用哪个有效:

$(".tobered,#illbered")[0].style.border = '1px solid #f00'

我需要打电话,但需要一行:

 $(".tobered,#illbered")[0].style.border = '1px solid #f00'
 $(".tobered,#illbered")[1].style.border = '1px solid #f00'
 $(".tobered,#illbered")[2].style.border = '1px solid #f00'
 $(".tobered,#illbered")[...].style.border = '1px solid #f00'

更明确的

这是如何运作的? https://api.jquery.com/multiple-selector/

无法通过阅读jquery.js文件

来弄明白

2 个答案:

答案 0 :(得分:0)

那里存在一个概念上的误解。

$ 已声明,但其返回值为 undefined 。它没有返回任何东西。因此,您无法执行undefined.style

但即使它返回了某些东西,你也会访问它返回的style属性。该功能已在此时执行。

function $(a) {
    b = document.querySelectorAll(a);
    //Calling forEach of an empty array
    //              Each call with b as this
    //                 And the function as parameter
    [].forEach.call(b, function(d) {
        //This actually will never run because there're no elements
        //But if it did, d would be returned to the forEach call
        //and forEach wouldn't do anything with the returned value
        return d
    });
    //The forEach calls returned nothing
    //Function ended and nothing is returned
}
var r=$(...);
//r $(...) is undefined

请注意,jQuery使用方法来实现此目的,例如

$(a).style(b);

$(a)返回一个对象,返回对象 style()的方法将样式b应用于所选元素,这些元素也有所定义在返回的对象中。

所以做你想做的事情的方法是在$()中使用属性和方法返回一些对象来应用样式。或者使用单个函数执行$(selector,styles)或两个函数,一个$()选择(或仅使用querySelectorAll)和style()执行forEach事务(如{{1} }})。

答案 1 :(得分:0)

基于 t-niese 的评论和 Gabriel 的回答。

那优雅吗?因为它对我有用:)

const $ = function(a) {

  let b = [];

  function Reach(els) {
    if (typeof a == "string") {
      b.length = els.length;
      for (var i = 0; i < b.length; i++) {
        b[i] = els[i];
      }
    } else {
      b.push(els);
    }
  }

  Reach.prototype.css = function(prop, val) {
    for (var i = 0; i < b.length; i++) {
      b[i].style[prop] = val;
    }
  }

  Reach.prototype.on = function(evt, fn) {
    for (var i = 0; i < b.length; i++) {
      if (b[i].addEventListener) {
        b[i].addEventListener(evt, fn, false);
      } else if (b[i].attachEvent) {
        b[i].attachEvent('on' + evt, fn);
      } else {
        return false
      }
    }
  }

 if (typeof a == "string") {
   return new Reach(document.querySelectorAll(a))
 } else {
   return new Reach(a)
 }

$(".tobered, #illbered").css("color","red")

$(window).on("click",function(){
  alert('Red is definitely a beautiful color')
})

但我怀疑使用for(typeof a == "string") ?两次的事实。

另外,我失去了使用$("#id")[0]作为简单选择器的能力。如果没有方法,它就不起作用。

我努力寻找如何确定是否使用Object.prototype.isPrototypeOf()instanceof调用某个方法来返回其他内容,但我失败了。

正确地知道,我必须使用另一个“功能”:

const $$ = document.querySelectorAll.bind(document)