Skip to content

Instantly share code, notes, and snippets.

@yuanchuan
Created June 21, 2011 14:11
Show Gist options
  • Save yuanchuan/1037937 to your computer and use it in GitHub Desktop.
Save yuanchuan/1037937 to your computer and use it in GitHub Desktop.
代码优化尝试

今天出于好奇,读了下一款 webgame 的源代码。从整体上看,代码很简单,但也很复杂。简单是因为程序的设计思路很容易懂,除了很多全局变量以外,全是一个接一个的函数;复杂是因为每当从一个函数当中读到一个的变量名时,或是看到一个函数调用的话,总要到其它地方去找,然后再回来,加上一个函数通常都很长,冗余很多,理解起来就变得复杂了。假如让我接手这些代码的话,维护起来一定相当费劲,耦合的太紧,不容易理清楚。要是程序继续像这样下去,一不小心,就会变得跟 “意大利面条“ 一样。

这款游戏还处在开发阶段,但是想要向更大规模发展的话,以现在的程序结构来看不太容易,因为控制不了复杂性。除此之外,某些地方的性能方面也有待改进,毕竟游戏不像其它的应用程序,它的要求比较高。下面是我对一些代码的优化尝试。

避免 if else 过多

太多的 if else 看上去不够简洁优美,总是提醒你还可以写得更好。 在constant.js当中有这么两个函数:
//与配置文件的转换
function getEffect(xmlEffect){
    if (xmlEffect == "get") {
        return EFFECT_GET;
    }else if (xmlEffect == "add") {
        return EFFECT_ADD;
    }else if (xmlEffect == "addp") {
        return EFFECT_ADDP;
    }else if (xmlEffect == "odds") {
        return EFFECT_ODDS;
    }else if (xmlEffect == "speed") {
        return EFFECT_SPEED;
    }else if (xmlEffect == "rise") {
        return EFFECT_RISE;
    }else if (xmlEffect == "tribute") {
        return EFFECT_TRIBUTE;
    }else if (xmlEffect == "drawing") {
        return EFFECT_DRAWING;
    }else if (xmlEffect == "famous") {
        return EFFECT_FAMOUS;
    }else{
        return EFFECT_NULL;
    }
}

//根据科技取得道具配置文件中的国家状态
function getStateByScience(sicenType){
    var state = "";
    if(sicenType == "0"){//B
        state = "1";
    }else if(sicenType == "1"){//A
        state = "2";
    }else if(sicenType == "2"){//G
        state = "3";
    }else if(sicenType == "3"){//J
        state = "4";
    }
    return state;
}

两个函数的复杂度都是 O(n), 最坏的的情况是当参数挨个都比较一下。JavaScript 当中的 {} 可以当哈希表一样用,因此两个程序当中比较的值可以存放在一个 {} 当中,然后用键来查找对应的值,这样复杂度变成 O(1):

var getEffect = (function () {
  var hash =  {
    get: EFFECT_GET,
    add: EFFECT_ADD,
    addp: EFFECT_ADDP,
    odds: EFFECT_ODDS,
    speed: EFFECT_SPEED,
    rise: EFFECT_RISE,
    tribute: EFFECT_TRIBUTE,
    drawing: EFFECT_DRAWING,
    famous: EFFECT_FAMOUS
  };
  return function(effect) {
    return hash[effect] || EFFECT_NULL;
  };
}());

function getStateByScience(type) {
  var hash = {0:1,1:2,2:3,3:4};
  return hash[type] || '';
}

其实第二个函数还可以这样写:

function getStateByScience(type){
  return /^[0123]$/.test(type)
    ? +type + 1 + ''
    : '';
}

这个测试比较了两种 getEffect()函数的性能,可见改进之后比以前大约快了 5 倍之多: http://jsperf.com/if-else-vs-hash。 同样,下面这两个吓人的函数也可以照样改进一下:

function getTheoryIndex(name){
    var str = "";
    if(name==g_m138){
        str = "1";
    }else if(name==g_m139){
        str = "2";
    }else if(name==g_m140){
        str = "3";
    }else if(name==g_m141){
        str = "4";
    }else if(name==g_m142){
        str = "5";
    }else if(name==g_m143){
        str = "6";
    }else if(name==g_m144){
        str = "7";
    }else if(name==g_m145){
        str = "8";
    }else if(name==g_m146){
        str = "9";
    }else if(name==g_m147){
        str = "10";
    }else if(name==g_m148){
        str = "11";
    }else if(name==g_m149){
        str = "12";
    }else if(name==g_m150){
        str = "13";
    }else if(name==g_m151){
        str = "14";
    }else if(name==g_m152){
        str = "15";
    }else if(name==g_m153){
        str = "16";
    }else if(name==g_m154){
        str = "17";
    }else if(name==g_m155){
        str = "18";
    }else if(name==g_m156){
        str = "19";
    }else if(name==g_m157){
        str = "20";
    }else if(name==g_m158){
        str = "21";
    }else if(name==g_m159){
        str = "22";
    }else if(name==g_m160){
        str = "23";
    }else if(name==g_m161){
        str = "24";
    }
    return str;
}

function getTheoryName(index){
    var str = "";
    if(index=="1"){
        str = g_m138;
    }else if(index=="2"){
        str = g_m139;
    }else if(index=="3"){
        str = g_m140;
    }else if(index=="4"){
        str = g_m141;
    }else if(index=="5"){
        str = g_m142;
    }else if(index=="6"){
        str = g_m143;
    }else if(index=="7"){
        str = g_m144;
    }else if(index=="8"){
        str = g_m145;
    }else if(index=="9"){
        str = g_m146;
    }else if(index=="10"){
        str = g_m147;
    }else if(index=="11"){
        str = g_m148;
    }else if(index=="12"){
        str = g_m149;
    }else if(index=="13"){
        str = g_m150;
    }else if(index=="14"){
        str = g_m151;
    }else if(index=="15"){
        str = g_m152;
    }else if(index=="16"){
        str = g_m153;
    }else if(index=="17"){
        str = g_m154;
    }else if(index=="18"){
        str = g_m155;
    }else if(index=="19"){
        str = g_m156;
    }else if(index=="20"){
        str = g_m157;
    }else if(index=="21"){
        str = g_m158;
    }else if(index=="22"){
        str = g_m159;
    }else if(index=="23"){
        str = g_m160;
    }else if(index=="24"){
        str = g_m161;
    }
    return str;
}

把它们写到一起,这样看起来好得多:

(function(){
  var names = [
    g_m138, g_m139, g_m140, g_m141, g_m142, g_m143,
    g_m144, g_m145, g_m146, g_m147, g_m148, g_m149,
    g_m150, g_m151, g_m152, g_m153, g_m154, g_m155,
    g_m156, g_m157, g_m158, g_m159, g_m160, g_m161
  ];
  
  var indexes = {}, i = 0, n;
  
  while ( n = names[i] ) {
    indexes[n] = ++i;
  };
  
  window.getTheoryIndex = function(name) {
    return indexes[name] || '';  
  }
  
  window.getTheoryName = function(index) {
    return names[index + 1] || '';
  }
})();

<未完待续>

@makestory
Copy link

是那个webgame呢?

@yuanchuan
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment