JavaScript跑马灯开发:移动端适配、jQuery技巧与定时器陷阱解析

作者:木棉

时间:2026-10-29

浏览:406

本文解析JavaScript跑马灯开发中的关键技术细节。针对移动端1px像素线显示异常,提出直接书写像素值的解决方案。对比PC与移动端浏览器对CSS选择器容错率的差异。深入探讨jQuery对象转为原生数组的三种方法:原型扩展、each遍历及Array.from,并分析setTimeout/setInterval中this指向window的问题及执行时机机制。

文章目录

JavaScript跑马灯开发概述

近期开发的项目中涉及跑马灯抽奖功能的需求,该功能主要依赖JavaScript技术实现。下文将详细解析相关代码与优化思路。

在正式进入核心功能前,先回顾重构过程中涉及的几个关键问题与知识点:

移动端适配与浏览器容错率

一、移动端1px像素线的渲染问题

设计师提供的手机端网页设计稿通常为2倍图。按照常规逻辑,网页中所有对象的实际尺寸应除以2进行缩放。然而,对于1像素宽的线条,这种处理方式会导致显示异常。

首先观察两张对比图片,分别为设计稿的预期效果:

JavaScript跑马灯开发概述 

以及在三星S4设备上的实际显示效果:

JavaScript跑马灯开发概述 

从上图可见,1像素的线条在三星S4上无法显示。这与S4手机的屏幕像素密度有关。关于屏幕像素密度与1px线条显示关系的原理已有大量文章介绍,此处不再赘述。本文采用的解决方案是对1px线条不做特殊处理,直接按原始尺寸编写,无论基础单位是rem还是其他单位。


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

二、PC端与移动端浏览器容错率的差异

首先参考以下代码片段:


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

可以明显看出,上述代码中的选择器存在语法错误。但在浏览器中运行会产生何种结果?请见下图:

JavaScript跑马灯开发概述

结果显示,对于属性选择器,即便存在语法错误,PC端浏览器仍能正确解析。然而,在移动端浏览器中,这种写法无法被正确解析,导致代码无法运行。

因此,在编写代码时需特别注意此类细节。

jQuery选择器与对象转换技巧

三、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参数在此起到决定性作用。具体应用请继续阅读。

四、jQuery对象转换为数组的方法

初学jQuery时,书中曾提及:

jQuery对象本质上是一个JavaScript数组。

在使用jQuery的过程中,常涉及JS对象与jQuery对象的相互转换,此处不再赘述基础概念。但有时需在jQuery对象上调用原生Array对象的方法或属性。示例如下:

JavaScript跑马灯开发概述

由代码运行结果可知,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();

定时器机制与性能分析

五、setInterval()和setTimeout()对程序性能的影响

由于setTimeout()和setInterval()在JavaScript中的实现机制完全相同,此处仅以setTimeout()进行验证。

参考以下两段代码:


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

输出结果如下:

JavaScript跑马灯开发概述

观察以下代码的输出情况:


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

运行该段代码时,程序报错。

JavaScript跑马灯开发概述

由上述结果可知,在使用setInterval()和setTimeout()时,若在回调中使用this,其作用域已发生改变,并指向window。

setTimeout(fn, 0)的含义是指定某个任务在主线程最早可得的空闲时间执行,即尽可能早地执行。它在“任务队列”的尾部添加一个事件,因此需等待同步任务和“任务队列”中现有事件全部处理完毕后,才会执行。这意味着,设置setTimeout()后,回调并非立即等待指定秒数后执行,而是等待主线程任务处理完毕后再执行,因此存在“等待”时间超过设定时间的现象。同时,若异步队列中已存在其他setTimeout(),也需等待之前的任务执行完毕后再执行当前任务。

参考以下Demo:


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

若运行上述代码,当执行完aaa()并等待一秒后,并不会立即执行ccc(),而是等待bbb()执行完毕后再执行ccc(),此时距离主线程运行结束已过去4秒。

以上内容针对JavaScript实现跑马灯抽奖活动实例代码解析与优化(一),下篇将继续分享JavaScript实现跑马灯抽奖活动实例代码解析与优化(二),感兴趣的朋友敬请关注。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章