组织Javascript

整理脚本

您应该拥有什么:

  • 基本的Java语言理解
  • 符合标准的浏览器
其他好处:
  • 装有Firebug插件的Firefox
1. Javascript,旧方法内联模型

在Web编码的早期,动态功能是使用onEvent属性添加到网站的。

<span onclick="doSomething()">click me</span>
因此,对于每个事件,您都有一个单独的功能,该功能在脚本标签中定义(最好位于<head>中
<script type="text/javascript">
function doSomething()
{
    // sample code
    alert("you have successfully clicked me");
}
</script>
2.再次播放,Sam传统模型

随着时间的流逝,人们开始将他们的代码放在一个外部javascript文件中,以使标记和行为分开,因为这样您可以更好地维护代码。

仍然通过onEvent属性维护功能。

<script type="text/javascript">
function doSomething()
{
    // sample code
    alert("page finished loading");
} 
// attach the function to an event attribute
window.onload = doSomething;
</script>
尽管通过这种方式可以更好地组织脚本,但是您仍然可以悬吊函数,此外,您还必须应对新问题。 内联方法直接应用功能时,外部脚本必须先查找需要更改的元素。

这就是文档对象模型(DOM)发挥作用的地方。 乍一看,这可能看起来很乏味,但是当您使用Javascript前进时,您会看到它带来的好处(无需在HTML代码中调用Javascript,包含Javascript就足够了)。

// HTML
<span id="submit">click me</span>
// Javascript
function doSomething()
{
    // sample code
    alert("you have successfully clicked me");
}
// this will only work, if the element is already loaded into the browser
document.getElementById("submit").onclick = doSomething; 
// to delay any function call after the page load, you have to use the onload event
window.onload = function()
{
    document.getElementById("submit").onclick = doSomething;
}
注意:Firebug插件可让您查看当前文档树(DOM树)。

所有这些代码都有一个真正的缺点:每个事件(和元素)只能应用一个函数调用,即,如果您包含多个脚本,则只有最后一个window.onload调用才起作用(原因是,每个元素仅具有onEvent属性) )。

3. Javascript,下一代DOM生活方式

当W3C释放DOM Level 2时,所有这些都改变了。现在,您可以通过函数处理事件:addEventListener和removeEventListener,它们为选定事件绑定一个函数到一个元素。

function doSomething()
{
    // sample code
    alert("you have successfully clicked me");
} 
function doSomethingElse()
{
    // code comes here...
} 
function init()
{
    document.getElementById("submit").addEventListener("click", doSomething, false);
    document.getElementById("submit").addEventListener("click", doSomethingElse, false);
}
window.addEventListener("load", init, false);
现在,您可以根据需要向一个元素(从任何脚本中)添加尽可能多的事件。

注意:我只在这里刮过Event主题,因为虽然事件处理是Javascript的核心(也是一个很好的例子),但在短篇文章中几乎没有对它进行解释。

进一步的注意:我不能在这里介绍IE的错误和解决方法,因为那将需要自己的一篇文章。

4.清理代码

已经有好的文章了,如何编写好的代码:

简洁的Javascript, 从DHTML到DOM脚本-如何替换过时JavaScript技术的示例。 维生素功能»可维护JavaScript的重要性

到目前为止,我们已经使用函数来组织脚本,只要没有太多的代码就可以了。 假设您有3个脚本文件,并且每个文件都有自己的init()函数! 这肯定会导致问题。 所以现在怎么办? 如果您有3rd party脚本,则无法真正重写它们的代码...

由于Javascript具有OOP功能(诚然与Java不匹配),因此我们可以使用它来阻止我们的功能相互干扰。

要了解其工作原理,我们必须了解范围(例如,此处:

Digital Web Magazine-JavaScript的范围 )。 Javascript中的每个变量都有一个范围(定义它的上下文)。 重要的是全局作用域 (变量在脚本中的任何位置均可访问)和局部作用域 (变量仅可在其定义的函数内部访问)。 因此,我们定义的任何函数(如我们所做的那样)都将具有全局范围。 在每个脚本文件中。

因此,如果定义了两个函数,则最后一个将获胜,因为它将覆盖前一个函数(无论是否在不同文件中定义了它们)。

function init() 
    alert(1); 
} 
// somewhere else but later
function init() 
    alert(2); 
} 
// alerts '2'
init();

注意:在讨论范围时,还有一种非常有用的技术称为Closures,您可能会发现它很方便(

假人JavaScript封闭| 发展中的思想-莫里斯·约翰(

现在我们知道范围了,这将给我们带来什么好处? 上面的两个函数具有相同的名称(“ init”)和相同的范围(全局)。 为了使它们与众不同,我们需要至少更改其中之一。 当然,您可以发明出无数个名称,包括“ init”,但是我们首先选择了该名称,因为它最能说明(并且至今)功能。

这样就可以选择更改范围,但是我们该怎么做呢? 这就是面向对象编程(OOP)发挥作用的地方。 OOP意味着处理对象。

简而言之,对象是一种构造,具有(可以具有)仅属于该对象的值(称为属性)和函数(称为方法)。

对象的用法如下:

// define a new value for the property
object.property = x; 
// assign the property value to a variable
var y = object.property; 
// call a method
object.method(); 
// call a method with arguments
object.method(arg1, arg2); 
// doesn't work
property = x;
var y = property;
method();
如果您睁开眼睛,睁开大脑,您可能会发现这如何解决我们的示波器问题。 对于剩下的内容,我会告诉您: 对象定义了其方法(函数)和属性(值)的范围。

因此:obj1.init()和obj2.init()是两个不同的函数。 得到它了?

为了解决我们的范围问题,我们仅将函数定义为不同对象的方法。

注意:这不是OOP的初衷,但我在这里不解释OOP(这可能会花费很长时间,超出了本文的讨论范围)。

让我们继续。 我们如何定义这些对象? 有一种书写方式(称为对象文字(

等我来! »博客存档»对对象文字表示爱 ))我们可以在这里使用。
var object_name = {
    property_1 : "value_1",
    property_2 : "value_2",
    method_1 : function()
    {
        alert("method 1 executing");
    },
    method_2 : function(x)
    {
        if (this.x)
        {
            alert(this.x);
        }
    }
} 
// alerts “method 1 executing”
object_name.method_1(); 
// does nothing (value_1 is not the name of a valid property)
object_name.method_2("value_1"); 
// alerts “value_2”
object_name.method_2('property_2');
在知道如何定义对象之后,我们可以从上面重写'init'示例。
// since we define the objects (not its methods) in global scope, 
// we can omit the var keyword
NS1 = {
    init : function()
    {
        alert(1);
    }
} 
NS2 = {
    init : function()
    {
        alert(2);
    }
} 
// alerts “1”
NS1.init(); 
// alerts “2”
NS2.init();
现在,我们已经成功地为每个init()函数应用了不同的作用域! 5.构建脚本

在编写脚本时,(在大多数情况下)您只需要执行少量任务(例如事件处理(某些单击事件,可能是鼠标悬停事件),动态内容加载(AJAX,子菜单)或表单验证)。 要开始使用它们,每个任务一个init()函数就足够了。 周围的所有其他功能仅帮助那些启动器功能完成工作。 因此,您可以轻松地将启动程序功能周围的帮助程序功能分组。 每个组都可以分配到自己的范围。

当然,您也可以构造范围…(但是仅对于大型库才需要)

例:

myName.menu      // function group for menu creation
myName.forms     // function group for form validation
myName.commons   // functions used in many groups 
                 // e.g. event handling, loop functions, …
如果您已阅读有关OOP的文章,则可能听说过某个对象可能具有私有属性和方法(此处的关键字是“(数据)封装”),这些属性和方法只能在对象内部调用,而不能从外部访问(无论它是什么范围)。 将组的所有帮助程序功能设为私有不是有用的(如果仅在组中使用该功能,为什么要授予全局访问权限)?

我们也可以做到。 在代码中稍作更改,我们就可以设置公共和私有属性和方法!

// our scope (let's call it namespace …)
bytes = {
    // subclasses
    // technically not necessary, but providing an overview
    // esp. if you have many subclasses
    josah : new Object,
    msquared : new Object 
    // you can define metadata here (dublincore.org)
} 
// object with only public members
bytes.msquared = { 
    favouriteColour : "purple", 
    hateColour : "gray", 
    state : function()
    {
        alert("I like " + this.favouriteColour);
    }, 
    stateNot : function()
    {
        alert("I hate " + this.hateColour);
    }
} 
// alerts "I hate gray"
bytes.msquared.stateNot(); 
// alerts "I like blue"
bytes.msquared.favouriteColour = "blue";
bytes.msquared.state(); 
// an object with private and public members
// I didn't go for real functions here……… ;-)
bytes.josah = function() { 
    // this is a private property
    var hateColour = "purple"; 
    // this is a private function
    // the 'this' keyword does not necessarily
    // point to bytes.josah!
    function throw()
    {
        this.lift();
        this.move();
        this.drop();
    } 
    return { 
        // this is a public function
        defenestrate : function(num)
        {
            var OP = thread[num].firstChild;
            OP.addEventListener("unlike", throw, true); 
            // you can call members from different scopes
            bytes.msquared.hateColour = hateColour;
            bytes.msquared.stateNot();
        }
    };
}(); 
// doesn't work
bytes.josah.throw(); 
// works (but I wouldn't try it)
// defenestrates #666 and alerts "I hate purple"
bytes.josah.defenestrate(666);
现在,您可以将所有函数分组在类中,并且组织起来非常完美。

最后是一个真实的例子

描述:单击注册的元素时弹出一个图像(或在window.open()中可以执行的其他任何操作)。 只要将元素的id属性注册为弹出窗口,元素就可以不受限制。 您甚至可以打开一个以上的弹出窗口,尽管不要太多(用户可能会因此而烦恼)。


/*
#########################################################
#         Popup script by Dormilich, bytes.com          #
# http://bytes.com, If you use this script on your site #
# Please keep this comment at the top of the javascript #
#########################################################
*/
Dormilich.Popup = function() { 
    /**
     * [private] array to store the objects holding the necessary information for window.open()
     */
    var IMG = new Array; 
    /**
     * [private] calling window.open() on event
     * since the image info object is not part of the element, the correct image object
     * is identified by ID comparison
     *
     * @return (void)
     */
    function pop() 
    {
        var l = IMG.length;
        for (var j=0; j<l; j++) 
        {
            // because pop() is used by addEvent() 'this' points to the object
            // having the event attached to
            if (IMG[j].id == this.id) 
            {
                window.open(IMG[j].src, IMG[j].titel, IMG[j].props);
            }
        }
    } 
    return { 
        /**
         * [public] create an image info object that hold the parameters for window.open() and put
         * it in the private storage array. src, titel & props are the parameters for window.open()
         *
         * @param (string) ID   id of the element to apply the onclick event to
         * @param (string) LOC  the location of the image to popup
         * @param (string) TTL  title of the popup window
         * @param (int) HGT     image height
         * @param (int) WDT     image width
         * @return (void)
         */
        create : function(ID, LOC, TTL, HGT, WDT) 
        {
            var obj = {
                id    : ID,
                src   : LOC,
                titel : TTL,
                props : "height=" + HGT + ",width=" + WDT + ",menubar=no,resizable=yes,scrollbars=yes"
            }
            IMG.push(obj);
        }, 
        /**
         * [public] loop through all element in the private storage array and attach the private pop() method
         * with the onclick event handler. (interestingly, even though the addEvent() method comes from a
         * different class it's executed in the local scope)
         *
         * @return (void)
         */
        register : function()
        {
            var l = IMG.length;
            for (var i=0; i<l; i++) 
            {
                var z = document.getElementById(IMG[i].id);  
                if (z) 
                {
                    z.style.cursor = "pointer";
                    // currently Tino Zijdel's addEvent() function namespaced
                    Events.addEvent(z, "click", pop);
                }
            }       
        } 
    };  
}(); 
Events = {
    addEvent : function(obj, evType, fn, useCapture)
    {
        // full code see http://therealcrisp.xs4all.nl/upload/addEvent2
        // of course you can use any other addEvent() function you like
    }
}; 
样本用法:

/* Javascript */
// add image
// assigning the image "test.png" to the element with the id "test"
// a new 500x700 popup (inner size) will appear onclick Dormilich.Popup.create('test', 'test.png', 'TST', 500, 700); 
// open a PDF in a new window (just used a random size) Dormilich.Popup.create('oath', 'slayers_try_prophecy.pdf', 'TRY', 387, 632); 
// register elements/images Events.addEvent(window, "load", Dormilich.Popup.register);  
/* HTML */
// show a full size image when clicking on a thumbnail <img src="test_thumb.jpg" width="50" height="70" alt="test image for popup" title="click for full image" id="test" class="thumbnails" /> 
// show the full text of an essay <div id="oath" class="shortdesc" title="click for full text">There shall come a controller of a dark star who shall call forth the light. (…)</div>  
终(末)

多米利奇

From: https://bytes.com/topic/javascript/insights/858838-organizing-javascripts

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值