【问题标题】:tiny implementation of jqueryjquery的微小实现
【发布时间】:2015-06-21 08:14:21
【问题描述】:

1) 我的任务是在 Javascript 上实现 jQuery。 但由于某种原因,我的方法每个都不起作用。 比如我写的时候

$('.a').each(function (index) {$(this).append('<b>' + index + '</b>')})

返回

DOMException:无法在“文档”上执行“querySelectorAll”:“[object Object]”不是有效的选择器。

我也不能在其他函数中使用this.each。例如,如果我在 append 中使用 each 而不是 forEach,它将不起作用。


<script type="text/javascript">
(function() {
  function $(selector) {
    if (this instanceof $) return this.search(selector)
      return new $(selector);
  }
  $.prototype = {
    constructor: $,
    length: 0,

    search: function(selector) {
      var that=this;
      var elems=Array.prototype.slice
          .call(document.querySelectorAll(selector));
      elems.forEach(function(x,i){that[i]=x;});
      this.length = elems.length;
      return this;
    },

    append: function(text) {
      if (text instanceof $) {
        this[0].appendChild(text[0]);
        for(var i = 1; i < this.length-1; i++) {
          var p = text[0].cloneNode(true);
          this[i].appendChild(p);
        }
      } else Array.prototype.slice
          .call(this).forEach(function(x){
              x.innerHTML  =  x.innerHTML  +  text;
          });

      return this;
    },  

    each: function(callback){
      for (var i=0;i<this.length;i++){
        this[i]=callback.call(this,this[i])
      };
      return this;
    },

  }
  window.$ = $;
}());

【问题讨论】:

  • “我的任务是在 Javascript 上实现 jQuery。” 呃....jQuery 实现了“ on" (in) JavaScript。
  • 它正在处理小提琴这里是demo
  • 顺便说一下,在选择 #id(单个元素)的选择器上使用 .each() 方法完全没有意义。
  • 好的,我已经更正了使用它来上课。但感觉是一样的。我不能使用 $(this) 并且 this.each 无论如何都不能在其他方法中工作..
  • @ozil:你使用的是真正的 jQuery。 OP 正在尝试重新实现 jQuery,(开始)使用问题中的代码。

标签: javascript jquery this each


【解决方案1】:

比如我写的时候

$('#id').each(function (index) {$(this).html('<b>' + index + '</b>')})

返回

DOMException:无法对“文档”执行“querySelectorAll”:“[object Object]”不是有效的选择器。

您在 each 回调中执行 $(this)。这样调用$ 并将this 设置为DOM 元素,而不是instanceof $,因此您调用new $(selector) 传递DOM 元素。最终调用this.search(selector),其中selector 是DOM 元素。然后你打电话给querySelectorAll(selector)。 QSA 接受字符串,而不是 DOM 元素,因此元素被转换为字符串 "[object Object]"(或在某些引擎上为 "[object HTMLElement]"),然后失败。

您可以使用浏览器中内置的调试器逐条检查代码语句来诊断这些错误。如果您出于某种原因要重新实现 jQuery,则需要养成这样做的习惯:大量使用调试器,找出问题所在并修复它。

在这种情况下,例如,您需要检测 selector 不是字符串并处理它,例如有点像这样:

search: function(selector) {
  var that=this, elems;
  if (typeof selector === "string") {
    elems = Array.prototype.slice.call(document.querySelectorAll(selector));
    elems.forEach(function(x,i){that[i]=x;});
    this.length = elems.length;
  } else {
    this[0] = selector;
    this.length = 1;
  }
  return this;
},

但除此之外,您还会遇到很多其他事情,您需要调试器。

【讨论】:

  • 我不明白为什么当我离开附加函数时这看起来没问题,但下一步是每个函数,现在 this[0] 是未定义的。
  • 我明白了!我的每个函数都写错了!
  • 我还有 1 个问题!当我编写 .children() 函数时,我希望更改“this”并将其返回。当我删除所有属性时我是对的吗:0,1,2...直到'this'中的长度,然后用作为this子级的新属性替换它们?还是有更优雅的方法来做到这一点?
【解决方案2】:

这适用于您的用例,但实现所有边缘情况会有点复杂:

(function() {
  function $(selector) {
    if (!(this instanceof $)){//forgot new
      return new $(selector);
    }
    if(typeof selector === 'string'){ 
      return this.search(selector);
    }
    //assuming selector is a dom object
    this[0]=selector;
    this.length=1;
  }
  $.prototype = {
    constructor: $,
    length: 0,

    search: function(selector) {
      var that=this;
      var elems=Array.prototype.slice
          .call(document.querySelectorAll(selector));
      elems.forEach(function(x,i){that[i]=x;});
      this.length = elems.length;
      return this;
    },
    append: function(text) {
      if (text instanceof $) {
        this[0].appendChild(text[0]);
        for(var i = 1; i < this.length-1; i++) {
          var p = text[0].cloneNode(true);
          this[i].appendChild(p);
        }
      } else {
           this.each(function(x){
              this.innerHTML  =  this.innerHTML  +  text;
          });
      }
      return this;
    },  
    // callback is called with the invoking object to be the dom element
    each: function(callback){
      for (var i=0;i<this.length;i++){
        this[i]=callback.call(this[i],i);
      };
      return this;
    },

  }
  window.$ = $;
}());
$('.a').each(function (index) {return $(this).append('<b>' + index + '</b>')})

【讨论】:

  • 你的回答很有帮助,但也应该改变每个函数,以便只调用回调而不是分配给 this[i]
猜你喜欢
  • 2020-09-20
  • 2013-07-12
  • 1970-01-01
  • 2011-03-19
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-02
相关资源
最近更新 更多