1)我有一个在Javascript上实现jQuery的任务。 但出于某种原因,我的方法都不起作用。 例如,当我写
$('.a').each(function (index) {$(this).append('<b>' + index + '</b>')})
它返回
DOMException:无法执行&#39; querySelectorAll&#39; on&#39; Document&#39;:&#39; [object Object]&#39;不是有效的选择器。
我也不能在其他功能中使用this.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.$ = $;
}());
答案 0 :(得分:5)
例如,当我写
时$('#id').each(function (index) {$(this).html('<b>' + index + '</b>')})
它返回
DOMException:无法执行&#39; querySelectorAll&#39; on&#39; Document&#39;:&#39; [object Object]&#39;不是有效的选择器。
您在$(this)
回调中正在each
进行操作。因此$
调用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;
},
但是,除了那些你将需要调试器的其他东西之外,还会有很多其他的东西。
答案 1 :(得分:0)
这适用于您的用例,但实现所有边缘情况会更复杂一些:
(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>')})