JavaScript “跑马灯”抽奖活动代码解析与优化(一)

最近的项目中作了一个“跑马灯”的抽奖特效插件。上篇文章已经分享过htmlcss 的相关知识。这篇文章主要分享一些 JavaScript 相关的知识。这几天在写这篇文章的时候,也顺便把本身的代码重构了一下。
这里主要是来写写本身的优化过程。俗话说:javascript

一个程序猿的进步是从对本身的代码不满意开始的。css

开始以前先来看上篇文章遗漏的两个问题和几个知识点,是本身重构的过程当中须要用到的:html

1.移动端1px像素线的问题

对于设计师给个人手机端网页的设计稿都是2倍图。按照道理来讲,在写网页的时候,全部对象的实际尺寸都是会除2。可是对于1像素的线呢?
先来看两张图,设计稿的效果:java

这里写图片描述
在三星 S4下的实际显示效果:node

这里写图片描述
能够看到这个时候1px的线居然显示不出来了。这个问题是跟 S4手机的屏幕像素密度有关。关于屏幕像素密度和1px 线的关系有不少文章介绍,能够自行搜索了解。我这里的解决方案是,对1px 的线不作处理。是多少就写多少。就算个人基础单位是rem,也不是其它单位。git

{
    position: absolute;
    width: 13rem;
    height: 9.2rem;
    border:1px solid #000;
}

2.pc 端浏览器和移动端浏览器容错率的差别

先来看一段代码:github

$('[node-type=row-a').find('div');

很明显能够发现,我使用的选择器是有语法错误的。可是在浏览器中运行会有什么结果呢?看下图:
这里写图片描述web

很明显能够看出对于属性选择器,就算我有语法错误,PC 端浏览器也是能够正确解析的。可是在手机端,这种写法是不可以正确解析,代码不可以运行。数组

因此写代码的时候必定要注意一些小细节哈。。。浏览器

3.jQuery中选择器的使用

在使用 jQuery 或者是 Zepto 的过程当中最常用的选择器的写法就是下面这样吧,

$('div.testClass')

只是在$() 中写上本身须要的 Dom 节点的 class或者 ID 或 者使用属性选择器。
在查看 jQuery的文档,对于$()会有这样的描述:

jQuery([selector,[context]])

最重要的是看看对 context (它也是咱们平时使用中最容易忽略,可是却很是有用的一个参数)的描述:

默认状况下, 若是没有指定context参数,$()将在当前的 HTML document中查找 DOM 元素;若是指定了 context 参数,如一个 DOM 元素集或 jQuery 对象,那就会在这个 context 中查找。在jQuery 1.3.2之后,其返回的元素顺序等同于在context中出现的前后顺序。

刚开始学习 JavaScript 那会儿,就据说了操做 DOM 是很损耗浏览器性能,遍历 DOM 也是很影响程序性能的。
若是咱们在指定的范围内查找须要的 Dom 会不会比从整个document 中查找快不少。并且在咱们写 web 组件的过程当中,一个页面上组件可能出现不少次,那咱们怎么判断咱们要操做哪一个组件呢?这个context参数就会起到决定行的做用。具体请继续看哇。。。

4.jQuery对象到数组的转换

刚开始学习 jQuery的时候在一本书上看到一句话:

jQuery对象就是一个 JavaScript 数组。

并且在使用 jQuery的过程当中,都会遇到,js对象转 jQuery对象,jQuery对象转 js对象。关于这些基础不作过多介绍。
可是有时候咱们会想在 jQuery对象上运用一些原生Array对象的方法或者属性。来看一个简单的例子:
这里写图片描述

由图中的代码运行结果,能够知道在 jQuery对象上是没有咱们要使用reverse方法的。尽管test是一个数组
那么咱们怎么办才可让 jQuery对象使用原生的 Array对象的方法呢?

4.1使用原型链扩展

好比下面的代码:

jQuery.prototype.reverse=function(){
    //一些操做
}

使用prototype来扩展方法的时候,你们一直比较认为是缺点的就是可能会污染已经存在的原型链上的方法。还有就是访问方法的时候须要查找原型链。

4.2将 jQuery对象中的对象添加到数组中

看下面的代码

var test = $('div.test');
var a=[];
$(test).each(function(){
    a.push($(this));
});

a.reverse();

这样就能够将 jQuery对象翻转。

4.3使用 Array对象的 from()方法

这种方法也是本身在编写插件过程当中使用的方法。看一下文档描述:

Array.from() 方法能够将一个类数组对象或可迭代对象转换成真实的数组。

我的感受使用这个代码比较简洁。暂时还不知道有没有性能的影响。继续看下面的代码:

var test = $('div.test');
var a= Array.from(test);
a.reverse();

5.setInterval()和setTimeout()对程序性能的影响

由于setTimeout()setInterval()这两个函数在 JavaScript 中的实现机制彻底同样,这里只拿 setTimeout()验证

那么来看两段代码

var a ={
    test:function(){
        setTimeout(this.bbb,1000);
    },
    bbb:function(){
        console.log('----');
    }
};
a.test()

输出结果以下:
这里写图片描述

看下面的代码输出是什么

var a ={
    test:function(){
        setTimeout(function(){
            console.log(this);
            this.bbb();
        },1000);
    },
    bbb:function(){
        console.log('----');
    }
};
a.test();

运行这段代码的时候,代码报错
这里写图片描述

由以上的结果能够知道,当咱们在使用setInterval()setTimeout()的时候,在回掉中使用this的时候,this的做用域已经发生了改变,而且指向了 window

setTimeout(fn,0)的含义是,指定某个任务在主线程最先可得的空闲时间执行,也就是说,尽量早得执行。它在"任务队列"的尾部添加一个事件,所以要等到同步任务和"任务队列"现有的事件都处理完,才会获得执行。

意思就是说在咱们设置 setTimeout()以后,也可能不是当即等待多少秒以后就当即执行回掉,而是会等待主线程的任务都处理完后再执行,因此存在 "等待"超过本身设置时间的现象。同时也会存在异步队列中已经存在了其它的 setTimeout() 也是会等待以前的都执行完再执行当前的。

看一个 Demo:

setTimeout(function bbb(){},4000);

function aaa(){
    setTimeout(function ccc(){},1000);
}

aaa();

若是运行上面的代码,当执行完 aaa() ,JavaScript 线程空闲,这时开始计时:等待1秒后将 ccc()加入执行队列,等待4s 将 bbb() 加入执行队列。这时从 ccc()加入执行队列到 bbb()加入执行队列中间时间间隔是3s。

执行结果以下图:

这里写图片描述

这里写图片描述

相关文章
相关标签/搜索