$("#kk").bind("mouseover", function() {
$(this).html("...").css({...}); // 報錯:$(this) 非預期對象
});
自定義 `$` 函數的 getNodes 方法未處理 this 為 window 或 DOM 元素對象的情況,導致選擇器解析失敗。
$.fn.prototype.getNodes = function(selector) {
// 1. 支持 window 對象直接傳入
if (selector == window) {
this.elements = selector; // 直接賦值,不做查找
return this;
}
// 2. 支持 DOM 元素對象直接傳入
if (selector instanceof HTMLElement || selector instanceof Node) {
this.elements = selector;
return this;
}
// 3. 原有字符串選擇器邏輯
var a = selector.substring(0, 1);
if (a == "#") {
this.elements = document.getElementById(selector.replace(/#/gi, ""));
}
// 可擴展 .class、tag 等選擇器
return this;
};
"bind": function(mouse, fn) {
var self = this; // 保存當前 $ 對象實例
$.addHandler(this.elements, mouse, function(e) {
// 關鍵:調用 fn 時將 this 綁定為 DOM 元素
fn.call(self.elements, e);
// 或創建新 $ 實例包裝
// fn.call($(self.elements), e);
});
}
<!DOCTYPE html>
<html>
<body>
<div id="kk">kk</div>
<script>
// 簡易 $ 庫實現
var $ = function(selector) {
return new $.fn(selector);
};
$.fn = function(selector) {
return $.fn.prototype.getNodes(selector);
};
$.fn.prototype.getNodes = function(selector) {
if (selector == window || selector instanceof Node) {
this.elements = selector;
return this;
}
var a = selector.substring(0, 1);
if (a == "#") {
this.elements = document.getElementById(selector.replace(/#/gi, ""));
}
return this;
};
$.extend = function(fn) {
for (var item in fn) {
$.fn.prototype[item] = fn[item];
}
};
$.addHandler = function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
}
};
$.extend({
"html": function(a) {
if (this.elements) this.elements.innerHTML = a;
return this;
},
"css": function(css) {
if (this.elements) {
var str = "";
for (var item in css) str += item + ":" + css[item] + ";";
this.elements.style.cssText = str;
}
return this;
},
"bind": function(mouse, fn) {
var self = this;
$.addHandler(this.elements, mouse, function(e) {
fn.call(self.elements, e); // 關鍵:綁定上下文
});
return this;
}
});
// 測試
$("#kk").bind("mouseover", function() {
$(this).html("啦聖誕節弗拉聖誕")
.css({"color":"red","font-weight":"bold"});
});
</script>
</body>
</html>
getNodes 支持 window/DOM 元素直接傳入bind 使用 fn.call(element, e) 確保回調內 this 指向 DOM 元素$(this) 會重新調用 getNodes,此時 this 為 DOM 元素,滿足條件 1 正常工作
4. 返回 this 支持鏈式調用