使用更高级的javascript模式的困难

时间:2012-12-03 02:14:48

标签: javascript jquery libraries

我在使用一个小Javascript库时遇到了一些麻烦,我正在为模仿jQuery和其他库的实践创建它。截至目前,它不起作用。我对Javascript和脚本编写很新,因为我只是开始自学,所以很可能我只是遗漏了一些对大多数人来说很明显的东西。我一直试图寻找解决方案,但我找不到一个解决方案,所以我自己就一直在询问。

这是图书馆本身:

(function(window, undefined) {
var document = window.document
var $m = function(obj) {
if (typeof obj === "object") {
    return obj
}
else {
    return document.getElementById(obj)
}

class: function(name){
    var ele = document.getElementsByTagName('*')
    var objects = []

    for (var q = 0 ; q < ele.length ; ++q){
    if (ele[q].className === name){
        objects.push(ele[q])
    }
    }
    return objects
}

s: function(){
    return this.style
}

window.$m = $m

})(window)

简短编辑:$ m旨在成为具有方法类和s的对象。

这是在一个简单的测试页面中引用它的方式:

<h1 class="heading" onmouseover="$m(this).s.setAttribute('text-decoration', 'underline')" onmouseout="$m(this).s.setAttribute('text-decoration', 'none')">Testing.</h1>

另一个编辑:我试图这样做,虽然它没有抛出任何错误但它无法正常工作。对于究竟没有被召唤的东西,我有点难过。

这是新图书馆:

(function(window, undefined) {
    //set document to this local scope
    var document = window.document
    //create $m object
    var $m = function(obj) {
    //if it is anything but an element return itself
        if (typeof obj === "object") {
        return new init(obj);
        }
    //if it is an element return that element
        else {
        return new init(document.getElementById(obj));
        }
    }

    function init(elem){
        //set properties
        this.elem = elem;
    }

    init.prototype = {
        //return style
        sty: function() {
            return this.elem.style;
        },

            //return all objects with a certain class

        cla: function() {
        var allelem = document.getElementsByTagName('*')
        var give = []

        //gather all elements in the document and get those with matching class
            for (var q = 0 ; q < allelem.length ; ++q){
        if (allelem[q].className === this.elem.className){
            give.push(allelem[q]);
        }
        }
        //return found elements
        return give;
    }
    }
    //expose $m to global scope
    window.$m = $m;
})(window)

并试图修复它的引用方式:

<h1 class="heading" id="test" onmouseover="$m(this).sty.textDecoration='underline'" onmouseout="$m(this).sty.textDecoration='none'">Testing.</h1>

2 个答案:

答案 0 :(得分:1)

这里有一些问题。 首先,正如user1689607所说,你的语法无效;你想(我认为)最后一部分如下:

function class(name){
    var ele = document.getElementsByTagName('*')
    var objects = []

    for (var q = 0 ; q < ele.length ; ++q){
        if (ele[q].className === name){
            objects.push(ele[q])
        }
    }
    return objects
}

function s() {
    return this.style
}

但这仍然不起作用,因为classreserved word

此外,您的代码将不再允许您在HTML中执行您要执行的操作。您正在寻找的是创建一个新对象,其中包含您作为字段传递给$的参数,其中包含您已定义为成员的函数。

尝试以下方法:

function MyObjConstructor(param) {
    this.field = param;
}

MyObjConstructor.prototype = 
{
    s:function(){...}//As your S function, but replace "this" with "this.field"
    clazz:function(){...}//As your class function, but replace "this" with "this.field"
}

最后

function $m(obj) {
    if (typeof obj === "object") {
        return new MyObjConstructor(obj);
    }
    else {
        return new MyObjConstructor(document.getElementById(obj));
    }
}

这会导致传递给$函数的每个对象被包装,并公开适当的方法。我不确定jQuery是如何做到的,但这可能是一个很好的起点。

答案 1 :(得分:0)

class: function(name){ … }

s: function(){ … }

我不知道你对这些陈述的期望。通常,这样的东西出现在对象文字中,但在这里你只有labeled statements。此外,你在某个地方缺少一个右大括号。

根据您的使用情况,您似乎希望它们是返回对象的属性。当您返回一个普通的DOM元素时,您需要使用这些自定义属性扩展它们:

var el = document.getElementById(obj);
el["class"] = function(name){ … }; // notice that "class" is a reserved word,
//                           you should not use it as a (property) identifier
el.s = function(name){ … }; // notice this defines a /function/,
//                   which you still had to invoke - you can't just use ".s…"
return el;

这通常是considered bad practice,你不会为此感到高兴。阅读文章以获得更好的模式。

顺便说一下,style声明没有DOM元素所具有的setAttribute方法。您可以直接分配给某个媒体资源,也可以使用setProperty method

此外,ssty属性是一个函数。在访问样式声明对象之前,您需要调用它:$m(this).sty().textDecoration = …; “getStyle”可能是一个更合适的名称。