Actually,simplicity is not simple

JS 不使用临时数组变量删除所有偶数项

var arr = [0,1,2,3,4,5,6,7,8,9];

删除arr中的所有偶数项,

要求

  • 不使用临时数组变量
  • 考虑连续奇偶项的情况
  • 尽情想像

以下是群中以及我自己想到的方法

  • 我听看到问题想到的方法

    arr = arr.join(',').replace(/\d+,(\d+)(,?)/g, "$1$2").split(',');
    console.log(arr);
    

    不足:

    • 未考虑连续奇偶情况
    • 变量的类型全转为String了
  • 伟哥的方法

    for(var i =0,len = arr.length;i<len ;i++){
        if(arr[len -i-1]%2 == 0){
            arr.splice(len -i-1,1)
        }
    }
    console.log(arr);
    
  • 刚子想像中的方法

    arr.join(',').repalce(/(\d+)(,?)/g, function($0, $1, $2){
        return ($1 && $1%2 == 0) ? $1 + $2 : '';
    }).split(',');
    console.log(arr);
    

    不足

    • 变量的类型全转为String了
    • 可能会在结果中加入一空项
  • 再次看下,这就是对数组做过滤嘛,高级一点的方法

    var arr = arr.filter(function(item){
        return item%2 == 1
    });
    console.log(arr);
    

    不足:

    • IE6/7歇菜了,不工作了
  • sfai写的

    var temp = [];
    while(arr.length){
        if(arr[arr.length-1]%2==1){
            temp.push(arr[arr.length-1]);
        }
        arr.length = arr.length - 1;
    }
    arr = temp;
    console.log(arr);
    

这方法使用了temp这数组变量不满足题目要求~~~~

  • 刚子写的

    for(var i = 0, j = 0, len = arr.length; i < len; i++){
        i % 2 == 0 && (arr.splice(j, 1), j++);
    }
    console.log(arr);
    
  • 苟子写的

    for(var len = arr.length; len > -1; len--){
        len % 2 == 0 && arr.splice(len, 1);
    }
    console.log(arr);
    

上面两位果然有愿啊!下面省略几万字。。。。。

  • 我再来了一个

    var i = 0
    while(i != arr.length){
        if(arr[i]%2 == 0)
            arr.splice(i, 1);
        else
            i++
    }
    console.log(arr);
    
  • 上一方法的缩减版

    var i = 0;
    while(i != arr.length){
        if(arr[i++]%2 == 0)
            arr.splice(--i, 1);
    }
    console.log(arr);
    

innerHTML操作的改进

function asyncInnerHTML(HTML, callback) {
    var temp = document.createElement('div'),
        frag = document.createDocumentFragment();
    temp.innerHTML = HTML;
    (function(){
        if(temp.firstChild){
            frag.appendChild(temp.firstChild);
            setTimeout(arguments.callee, 0);
        } else {
            callback(frag);
        }
    })();
}

看看上面的代码,对平常我们用的innerHTML做了些许改进,不管在用处上还是浏览器呈现上都有所进化。

  • 使用setTimeout防止出现浏览器堵塞现象(及长时间没反应,突然一下子呈现的现象)
  • 使用DocumentFragment提升效率

再来看下它的作用吧

var htmlStr = '<div><p>...</p><p>...</p><div><div>...</div>';
asyncInnerHTML(htmlStr, function(fragment){
    // You can treat 'fragment' as a regular node.
    document.body.appendChild(fragment);
});

我想这已经很明了了,这函数强于 string 转 DOM 并得到转化后的DOM对象,做点记录方便以后使用吧!

这函数的出处看这里

用JS动态监听CSS加载

周五时有个工作时需求等CSS加载完后后再执行些JS代码,但发现使用onload在Firefox chrome下不行但IE8下却可以。

第一次发现IE也有让我省心的时候啊!

问谷大叔得知研究这问题的人还挺多的:

  • 在射雕的lab中发现有两个测试 load js css css preload,讲得挺多的,而且在其seajs中已经运用上了,拜之~~
  • 在国外一相当大的专业问答网站中找到相同问题,也有不少人给出了解答 javascript capturing load event on link。主要讲到两种方案:
    1. 使用settimeout循环判断不同浏览器中当CSS加载完或失败时的特性,射雕使用的方案也是这种,但特性有所不同;
    2. 方案挺有意思的,同时创建link、img标签并将CSS的URL同时赋于两个标签,用img标签的onerror事件做为加载监听器,但这种方案会产生两个请求,并且img标签所发出的请求会标注不支持gzip。
  • Cross Browser Stylesheet Preloading中也提供了一解决方案,但代码是基于mootools写的,最重要的一点是延时判断link标签的ownerNode或owningElement属性,没用过这两个属性,不懂!!!

继续问谷大叔找到关于ownerNode(返回节点与此相关联的样式表文件的。)以及owningElement(返回附加到元素节点上的属性)的定义。

this.link.id = this.getID(); // 创建link标签时给标签加上了ID属性
// 注意 这里的file = document.styleSheets[0]; 或 document.getElementsByTagName('link')[0].sheet;
var owner = file.ownerNode ? file.ownerNode : file.owningElement;
if(owner && owner.id == this.getID()) {
    this._onready();
    return;
}

并且看到了对link标签事件支持情况:

IE6-IE9、opera  都支持link标签的 onload  onerror事件
firefox chrome  safari 都不支持link标签的 onload  onerror事件

input只能输入数字的方法

昨天写后台的表单时的需求,发现自己对这方面的了解很不够,在网友steven_2005的这博文中的实现方式不错,但和我的需求还差一点,所以改进了下(一个输入字符不能是小数点):

// input只能输入数字和小数点
function DigitInput(el,e) {
    //8:退格键、46:delete、37-40: 方向键
    //48-57:小键盘区的数字、96-105:主键盘区的数字
    //110、190:小键盘区和主键盘区的小数
    //189、109:小键盘区和主键盘区的负号
    var e = e || window.event; //IE、FF下获取事件对象
    var cod = e.charCode||e.keyCode; //IE、FF下获取键盘码
    //小数点处理
    if (cod == 110 || cod == 190){
        (el.value.indexOf(".")>=0 || !el.value.length) && notValue(e);
    } else {
        if(cod!=8 && cod != 46 && (cod<37 || cod>40) && (cod<48 || cod>57) && (cod<96 || cod>105)) notValue(e);
    }
    function notValue(e){
        e.preventDefault ? e.preventDefault() : e.returnValue=false;
    }
}

使用方式很简单,要注意的是函数得绑定在onKeydown事件上

<input type="text" onkeydown = "DigitInput(this,e);" />

或用事件绑定的方式(jQuery的代码):

$('input').bind('keydown', function(e){
    DigitInput(this, e);
});

实现IE下Array.indexOf函数

我一直觉得Array的indexOf函数很好用,可惜微软的IE浏览到IE8都还不支持,只有自己拓展了,下面的代码我认为是比较的实现。

if(!Array.prototype.indexOf){
    Array.prototype.indexOf=function(el, index){
        var n = this.length>>>0, i = ~~index;
        if(i < 0) i += n;
        for(; i < n; i++) if(i in this && this[i] === el) return i;
        return -1;
    }
}

这函数里的~~很有意思。~~是由两个~(按位“非”)运行符组成,发现实用性还是有的。

~~true; //1 Number
~~false; //0  Number
~~'123'; //123  Number
~~'0fs'; //0  Number

上面的测试代码可以告诉我们‘~~’对来对纯数字的String或布尔值转为数字很有用。以前写过这样的代码

[console.log, alert][!!document.all?1:0]('nootn.com简单其实不简单!');

现在可以这样写了

[console.log, alert][~~!!document.all]('nootn.com简单其实不简单!');