2

javascript高质量代码(三)


主博客:http://homeway.me

最近在看《编写高质量代码-web前端修炼之道》,写了3篇博客,写写感想。


第一篇写了关于javascript封装以及模块化插件设计。

第二篇写了关于javascript面向对象思想以及原型和构造器。

第三篇主要写关于javascript的编写风格以及细节设计问题。


一、全局变量、全局函数
    如果是很多人一起开发一个项目,那么就会造成很多的重命名的事件。这个时候就要一个局部函数,替换全局函数。

    假设,程序员A写了段代码:

function a(){
    var a="a is in function a(), writed by B";
    alert("It's writed by A!!");
}

    然后程序员B写了端代码:

function a(){
    var a="a is in function a(), writed by B";
    alert("It's writed by B!!");
}

    如果我想要在一个页面同时包含这个两个函数,那么很简单,我们要用到匿名函数。

/*=========下面是A写的==========*/
(function a(){
    var a="a is in function a(), writed by B";
    alert("It's writed by A!!");
})();
/*=========下面是B写的==========*/
(function a(){
    var a="a is in function a(), writed by B";
    alert("It's writed by B!!");
})();
//它们不会互相影响

    但是,如果我想要在A写的函数和B写的函数间传值,那么要怎么办?全局变量?可是一般最尽量不要用全局变量。

    那就建个数组,造个对象,存放数据。

var global={ };
/*=========下面是A写的==========*/
(function a(){
    global.A.a="a is in function a(), writed by B";
    global.A.b=function(){alert("It's writed by A!!");};        
})();
/*=========下面是B写的==========*/
(function a(){
    global.B.a="a is in function a(), writed by B";
    global.B.b=function(){alert(global.A.a);};
    //return alert("alert("It's writed by A!!");
    //这样就实现了匿名函数间传值,又防止了命名冲突
})();

    这样子看起来是不是有些像prototype原型样式了。

var A;
A.prototype.a=function(){ };
A.prototype.b=function(){ };
A.prototype.c=function(){ };

    写个封装函数吧,不然每次都要写一大堆。

var globale={ };
global.namespace=function(str){
    var arr = str.split("."), o=global;
    for(i=(arr[0] == "global") ? 1 : 0 ; i<arr.length; i++){
        o[ arr[ i ] ] = o[ arr[ i ] ] = { };
        o=o[ arr[ i ] ];    
    } 
};
/*===========测试===========*/
global.namespace("A.start");
global.namespace("A.end");

global.A.start=function(){ alert("test:global.A.start") };
global.A.end=function(){ alert("global.A.end") };

二、函数入口
    javascript是种脚本语言,浏览器执行渲染工作,javascript加载到哪一行,就渲染哪一行的语句,所以js的排放位置很重要,js的函数入口也很重要。

function A(){
    alert("just test");
}
var B = function(){
    alert("just test");
}

    其实这两个函数都是一样的结果,但是,函数的意义不一样。当函数加载进来,就会直接执行A();然而函数B要调用。

  • 用window.onload监听,会在网页元素全部加载完毕后触发onload事件。
  • 用init();在DOMReady加载。

DOMReady只判断节点是否加载完毕,所以触发速度比window.onload快。
DOMReady不是原生的Javascript事件,要通过就是框架调用。

三、扩展原型函数

javascript是基于原型的语言,但是,并不是所有函数都要new实例化。

在js里面却没有each,clone等函数,所以我们可以拓展,重写内置类行为:

Array.pototype.each=function( callback ){
    for(var i=0; i<this.length; i++)
        callback( this[ i ], i );//对每个对象实行回调函数
}

Array.pototype.clone=function(){
    var o = [];
    this.each(function (k, v){
        o[ k ] = v;
    });
    return o;
    //我感觉我在写jquery的内核函数了。。 
}

并且,还可以扩展内置类了。所有类的祖先都是在Object里面。

Object.prototype.test=function(){
    return this.value;  
};
/*==========测试=========*/
var xiaocao={ };
xiaocao.value="小草是帅哥";

alert(xiaocao.test());
//return 小草是帅哥;

四、改变DOM

  • 方法一:

    <div class="test" id="test">测试</div>
    <script>
        document.getelementById("test").style="font-size:20px;";
    </script>
    

不实用。

  • 方法二:

    <style>
        class_name:{font-size:30px;}
    </style>
    <div id="test">测试</div>
    <script>
        var node = document.getelementById("test").style="font-size:20px;";
        node.className="class_name";
    </script>   
    
  • 方法三:

    <script> function addStyle(str){ var style_node = document.creatElement("style"); style_node.type="text/css"; if (style_node.styleSheet ){ style_node.styleSheet.cssText = str; }else{ style_node.innerHTML = str; } document.getElementByTagname("head")[0].appendChild(style_node); } /*==============可以调用了============*/ addStyle("#test{font-size:30px;}"); </script>

获取节点的属性:

<div id="test" nick_name="xiaocao"></div>
<script>
    var node=document.getElementById("test");
    function(){
        alert(node.nick_name);
        //IE==>>xiaocao
        //firfox==>>null

        alert(node.getAttribute);
        //IE&&firfox==>>xiaocao
    }
</script>

也就是说,自定义标签属性,最好用attribute节点访问。



五、看看自己究竟写了什么恶心的代码:

    其实,让我们来看个几个我以前写代码风格的例子,就会发现,一些问题。

function count_keys(symbol){
    var key;
    var _key=localStorage.getItem("result1");
    var _key_=localStorage.getItem("result2");
    var key_=localStorage.getItem("result3");

 if(symbol.slice(0,1)==symbol.slice(1))//符号为+ +,- -,x x
key=count(count(_key,_key_,symbol.slice(0,1)),key_,symbol.slice(1));
    if(symbol.slice(0,1)==1 && symbol.slice(1)==0 || symbol.slice(0,1)==0 && symbol.slice(1)==1)//符号为- +;+ -
key=count(count(_key,_key_,symbol.slice(0,1)),key_,symbol.slice(1));
    if(symbol.slice(0,1)==0 && symbol.slice(1)==2 || symbol.slice(0,1)==1 && symbol.slice(1)==2)//符号为+ x;- x
key=count(_key,count(_key_,key_,symbol.slice(1),symbol.slice(0,1)));
    if(symbol.slice(0,1)==2 && symbol.slice(1)==0 || symbol.slice(0,1)==2 && symbol.slice(1)==1) 
key=count(count(_key,_key_,symbol.slice(0,1)),key_,symbol.slice(1));  //符号为x + ; x -

    return key;
}   

    看自己以前写的代码真觉得,很多废话,最主要的是,感觉逻辑性好差,构思一个代码段真的很难,高质量代码也好难,要先想好多逻辑性问题,列表,流程图,不然都是废话。
    还有一点就是,参数逻辑性不强,每个函数的对接性不强,模式化基本没有。

var test=JSON.stringify(test);
var students = JSON.stringify(datas);
storage.setItem('data',students);
storage.setItem('xiaocao.test.1',test);
//var obj = storage.getItem('data');
var obj = eval( "(" + storage.getItem('data') + ")" );//将json转化为对象
console.log('数量是:'+obj[1]+obj[2]+obj[3]+obj[4]+'哈哈哈哈'+obj.num);
//console.log('名称分别是:'+obj.2);

全局变量很多,函数的封装性很差,没有模式化。总的来说,就是,功能实现了,但是,没头没脑想到什么写什么。

看几个例子:

很喜欢腾讯alloy团队那种封装好的代码。

addEvent=function(selector, eventType, func){
            var proName = "";
            switch(true){
                case /^\./.test(selector) :
                    proName = "className";
                    selector = selector.replace(".", "");
                    break;
                case /^\#/.test(selector) :
                    proName = "id";
                    selector = selector.replace("#", "");
                    break;
                default: 
                    proName = "tagName";
            }

            document.body.addEventListener(eventType,function(e){
                    function check(node){
                        if(! node.parentNode) return;

                        if(node[proName] == selector){
                            func.call(node, e);
                        };
                        check(node.parentNode);
                    }
                    check(e.target);
            }, false);
        }
    //这段超爱,后来,我就收藏了。

javascript进阶就到这里了。

接下来要做的事情就是准备后台了。先练熟python,然后用web.py和tornado.py框架做web。


夏日小草
2013/12/5 19:57:13

夏日小草
2.2k 声望139 粉丝

[链接]