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

Mimicking $ jQuery selector with forEach yields undefined

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

function $(a) {

    b = document.querySelectorAll(a);

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

    return d

  });
}

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

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

让我们做的更清楚:

简化 'function' :

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文件无法弄清楚

这里存在概念上的误解。

$ 声明 但其 return 值为 未定义。它没有 return 任何东西。因此你不能做 undefined.style.

但即使它 return 编辑了某些内容,您也可以访问它 return 编辑的任何内容的 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) return 是一个对象,returned 对象的 方法 style() 应用样式b 到 selected 元素,这些元素也在 returned 对象中有所定义。

所以做你想做的事情的方法是 return $() 中的一些对象,具有属性和 方法 来应用样式。或者有一个函数可以完成 $(selector,styles) 之类的所有事情,或者有两个函数,一个 $() 到 select (或者只使用 querySelectorAll)和 style() 做 forEach 事情(像 style(elems,styles)).

基于 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 调用到 return 其他东西,但我失败了。

所以知道,我必须使用另一个 "function" :

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