搜索
首页web前端js教程在JS开发中最实用的问题解答

在JS开发中最实用的问题解答

May 17, 2018 am 11:26 AM
javascript实际的问题解答

可维护性

编写可维护的代码很重要,因为大部分开发人员都花费大量时间维护他人代码。很难从头开始开发新代码的,很多情况下是以他人成果为基础的。确保自己代码的可维护性,以便其他开发人员在此基础上更好的开展工作。

什么是可维护的代码?

可理解性:其他人可以接手代码并理解它的意图和一般途径,而无需原开发人员的完整解释

直观性:代码中的东西一看就能明白,不管其操作过程多么复杂

可适应性:代码以一种数据上的变化不要求完全重写的方法撰写

可扩展性:在代码架构上已考虑到在未来允许对核心功能进行扩展

可调试性:当有地方出错时,代码可以给予你足够的信息来尽可能直接地确定问题所在

代码约定

代码约定是一种让代码变得可维护的简单途径是形成一套JavaScript代码的书写约定。 
可读性:要让代码具有可维护性,首先他必须可读。可读性的大部分内容都是和代码缩进相关的,还有一方面是注释。包括以下几个方面:

函数和方法:每个函数或方法都应该包含一个注释,描述其目的和用于完成任务所可能使用的算法。陈述事先的假设也非常重要,如参数代表什么,函数是否有返回值

大段代码:用于完成某个任务的多行代码应该在前面放一个描述任务的注释

复杂的算法: 如果你使用了一种独特的方式解决某个问题,则要在注释中注释你是如何做的。这不仅仅可以帮助其他浏览你代码的人,也能在下次你自己查阅代码的时候帮助理解。

Hack:因浏览器差异问题,js代码一般会包含一些hack。如果因为某种浏览器无法使用普通的方法,所以你需要用一些不同的方法,请放入注释中。

变量和函数名

命名规则如下:

变量名应为名词如car或person

函数名应以动词开始,如getName()。返回布尔值的函数以is开头,如isEnable()

变量名和函数都应使用合乎逻辑的名字,不要担心长度。长度可以通过后处理和压缩来缓解

变量类型透明

有三种方式表明变量数据类型的方式:

初始化:当定义一个变量后,它应该被初始为一个值,来暗示它将来如何应用。 
比如:var found = false; 
初始化为一个特定的数据类型可以很好的指明变量的类型。但缺点是它无法用于函数声明中的参数。

使用匈牙利标记法来指定变量类型 
“o”代表对象,”s”代表字符串,”i”代表整数,”f”代表浮点数,”b”代表布尔型 
比如:var bFound;//布尔型 
匈牙利标记法的好处是函数参数一样可以使用。但是缺点是让代码某种程度上难以阅读,阻碍了没有用它时代码的直观性和句子式的特质。

使用类型注释

var found/*:Booldan*/=false;1

类型注释的缺点是你不能使用多行注释一次性注释大块的代码,因为类型注释也是多行注释,两者会冲突。

松散耦合

只要应用的某个部分过分依赖于另一部分,代码就是耦合过紧、难于维护。典型的问题如:对象直接引用另一个对象,并且当修改其中一个的同时需要修改另外一个。紧密耦合的软件难于维护并且需要经常重写。

解耦html/javascript

html和javascript各自代表了解决方案中的不同层次:html是数据,javascript是行为。因为他们天生就需要交互,所以有多种不同的方法将这两个技术关联起来。

情况一:直接写在html中的javascript,使用包含内联代码的3f1c4e4b6b16bbbd69b2ee476dc4f83a元素或者使用Html属性来分配事件处理程序,都是过于紧密的耦合。 
比如: 
从技术上说都是正确的,但是在实践中,它们将表示数据的html和定义行为的JavaScript紧密耦合在了一起。**理想情况是:**html和JavaScript应该完全分离,并通过外部文件和使用DOM附件行为来包含JavaScript。 
当两者耦合在一起时,出现javascript错误时就要先判断错误出现在Html部分还是javascript文件中。还会引入和代码是否可用的相关问题。 
情况二: 
html和javascript的机密耦合也可以在相反的关系上成立:javascript包含了Html.这通常会出现在使用innerHtml来插入一段Html。 
将html和JavaScript解耦可以在调试过程中节省实践,更加容易确定错误的来源,也减轻维护的难度,更改行为只需要在JavaScript文件中进行,而更改标记则只要在渲染文件中。

解耦css/javascript

另外一个web层则是css,它主要负责页面的显示。 
最常见的紧密耦合例子是使用javascript来更改某些样式,如下所示:

//css对javascript的紧密耦合  
element.style.color = "red";  element.style.backgroundColor = "blue";  123

由于CSS负责页面的显示,当显示出现问题时应该只是查看CSS文件来解决。然而,当使用了JavaScript来更改某些样式的时候,如上面代码所示,就出现了第二个可能已更改的和必须检查的地方。结果是JavaScript也在某种程度上负责了页面的显示,并与CSS紧密耦合了。如果将来需要修改样式,CSS和JavaScript文件可能都需要修改,这会给维护人员带来噩梦。 
解耦合的原则: 
虽然不可能完全将css和javascript解耦,但是还是能让耦合更松散的,这是通过动态改变样式类而非特定样式来实现的,如下所示:

//css对javascript的松散耦合   element.className = "edit";  12

通过只修改某个元素的css类,就可以让大部分样式信息严格保留在css中。JavaScript可以改变样式类,但并不会直接影响到元素的样式,只要使用了正确的类,那么任何显示问题都可以直接追溯到css而非JavaScript。

第二类紧密耦合仅会在IE中出现(标准模式下的IE8不会出现),它可以在css中通过表达式嵌入javascript,例如:

/*javascript对css的紧密耦合*/   div{   
width:expression(document.body.offsetwidth-10+"px");  
}1234

通常要避免使用表达式,因为他们不能跨浏览器兼容,还因为它们所引入的JavaScript和css之间的紧密耦合。 
好的层次划分是非常重要的。显示问题的唯一来源应该是css,行为问题的唯一来源应该是javascipt.在这些层次之间保持松散耦合可以让你的整个应用更加易于维护。

解耦应用逻辑/事件处理程序

很少有能仔细得将应用逻辑从事件处理程序中分离的。例如:

fuction handleKeyPress(event){  
if(event.keyCode == 13){  
 var target = eventUtil.getTarget(event);  
 //应用逻辑部分
 var value = 5 * parseInt(target.value);  
 if(value >10){    
 document.getElementById("error-msg").style.display = "block";   
            }  
        }  
}12345678910

这段代码除了包含应用逻辑,还进行了事件的处理。 
这种方式的问题有其双重性:首先,除了通过事件之外就再没有方法执行应用逻辑,让调试变得困难。如果没有发生预想的结果怎么办?是不是表示事件处理程序没有被调用还会死指应用逻辑失败?其次,如果一个后续的事件引发同样的应用逻辑,那就必须复制功能代码或将代码抽取到一个单独的函数中。无论如何,都要做比实际所需更多的改动。

较好的方法是将应用逻辑和时间处理程序分离,这两者分别处理各自的东西。一个事件处理程序应该从事件对象中提取相关信息,并将这些信息传送到处理应用逻辑的某个方法中。例如前面的代码重写为:

//处理应用逻辑function validateValue(value){  
var value = 5 * parseInt(value);  
 if(value >10){  
 document.getElementById("error-msg").style.display = "block";   
}  
} 
//事件处理函数  fuction handleKeyPress(event){  
 if(event.keyCode==13){  
var target = EventUtil.getTarget(event);  
validateValue(target.value);  
}  
} 1234567891011121314

好处:从事件处理程序中分离应用逻辑有几个好处。首先,可以让你更容易更改触发特定过程的事件。如果最开始由鼠标点击事件触发过程,但现在按键也要进行同样处理,这种更改就很容易。其次,可以在不附加到事件的情况下测试代码,使其更容易创建单元测试或者是自动化应用流程。 
以下是要牢记的应用和业务逻辑之间松散耦合的几条原则:

勿将event对象传递给其他方法;只传来自event对象中所需的数据

任何可以在应用层面的动作都应该可以在不执行任何事件处理程序的情况下进行;

任何事件处理程序都应该处理事件,然后将处理转交给应用逻辑。

牢记着几条可以在任何代码中都获得极大的可维护性的改进,并且为进一步的测试和开发制造了很多可能。

js性能

优化DOM交互

在js中,DOM毫无疑问是最慢的一部分。DOM操作与交互要消耗大量时间,因为它们往往需要重新渲染整个页面或者一部分。理解如何优化与DOM的交互可以极大提高脚本完成的速度。

最小化现场更新

一旦你需要访问的DOM部分是已经显示的页面的一部分,那么你就是在进行一个现场更新,因为需要立即对页面对用户的显示进行更新。 
每一个更改,不管是插入单个字符,还是移除整个片段,都有一个性能惩罚,因为浏览器要重新计算无数尺寸以进行更新。现场更新进行得越多,代码完成执行所花的时间就越长,完成一个操作所需的现场更新越少,代码就越快。 
demo1:

<body><ul id="list"></ul><script type="text/javascript">var oList = document.getElementById("list");
console.time("计时器1");for(var i=0;i<1000;i++){    var item = document.createElement("li");
    list.appendChild(item);
    item.appendChild(document.createTextNode("item"+i));
}
console.timeEnd("计时器1");</script></body>12345678910111213

上面这段代码为列表添加了1000个项目,添加每个项目时,都需要2个现场更新:一个添加25edfb22a4f469ecb59f1190150159c6元素,另一个给它添加文本节点。这样添加1000个项目,这个操作总共要完成2000个现场更新。 
修正这个瓶颈(需要减少现场更新的数量)有两种方法: 
1.将列表从页面上移除,最后进行更新,最后再讲列表插回到同样的位置。这个方法的问题在于:每次页面更新的时候都会出现不必要的闪烁。 
2.使用文档碎片来构建DOM结构,接着将其添加到List元素中。这种方式避免了现场更新和页面闪烁的问题。(请看Demo2) 
Demo2:

<body><ul id="list"></ul><script type="text/javascript">var oList = document.getElementById("list");var fragment = document.createDocumentFragment();
console.time("计时器2");for(var i=0;i<1000;i++){    var item = document.createElement("li");
    fragment.appendChild(item);
    item.appendChild(document.createTextNode("item"+i));
}//记住,当给appendChild()传入文档碎片时,只有碎片中的子节点被添加到目标,碎片本身不会被添加的list.appendChild(fragment);
console.timeEnd("计时器2");</script></body>12345678910111213141516

在这个例子中只有一次现场更新,它发生在所有项目都创建好之后。文档碎片用作一个临时的占位符,放置新创建的项目,然后使用appendChild()将所有项目添加到列表中。 
一旦需要更新DOM,考虑使用文档碎片来构建DOM结构,然后再将其添加到现在的文档中。 
两个Demo的执行时间比较: 

使用innerHTML

在页面上创建DOM节点的方法: 
1.使用诸如createElement()和appendChild()之类的DOM方法 
2.使用innerHTML 
对于小的DOM更改而言,两种方法效率都差不多,然而,对于大的DOM更改,使用innerHTML要比使用标准DOM方法创建同样的DOM结构快得多。 
原因:当把innerHTML设置为某个值时,后台会创建一个HTML解析器,然后使用内部的DOM调用来创建DOM结构,而非基于JavaScript的DOM调用。由于内部方法是编译好的而非解释执行的,所以执行快得多。 
Demo:

<body><ul id="list"></ul><script type="text/javascript">var oList = document.getElementById("list"),
    html = "",
    i;for(i=0;i<2000;i++){
    html += "<li>item " + i +"</li>";
}
oList.innerHTML = html;//这里构建好一个字符串然后一次性调用innerHTML,这样也只发生一次现场更新</script></body>12345678910111213

使用事件代理

页面上的事件处理程序的数量和页面响应用户交互的速度之间是负相关。为了减少这种惩罚,最好使用事件代理。 
事件代理:用到了事件冒泡。任何可以冒泡的事件都不仅仅可以在事件目标上进行处理,目标的任何祖先节点上也能处理。利用这一点,就可以将事件处理程序附加到更高层的地方负责多个目标的事件处理。如果在文档级别附加事件处理程序,这样可以处理整个页面的事件。 
Demo:

<!DOCTYPE html><html><head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>事件委托</title></head><body><ul id="list1">
    <li><a href="#">正在监听1</a></li>
    <li><a href="#">正在监听1</a></li>
    <li><a href="#">正在监听1</a></li>
    <li><a href="#">正在监听1</a></li></ul><ul id="list2">
    <li><a href="#">正在监听2</a></li>
    <li><a href="#">正在监听2</a></li>
    <li><a href="#">正在监听2</a></li>
    <li><a href="#">正在监听2</a></li></ul><a href="#" id="add-items">添加更多节点</a><script type="text/javascript">var oList1 = document.querySelector("#list1");var aList = oList1.querySelectorAll("li");var oList2 = document.querySelector("#list2");var oBtn = document.querySelector("#add-items");for(var i=0,len=aList.length;i<len;i++){
    aList[i].onclick = function(){
        alert("正在监听1");
    }
}
oList2.onclick = function(){
    alert("正在监听2");
}    var html = "<li><a href=&#39;#&#39;&#39;>我是动态新增节点</a></li>";
oBtn.onclick = function(){
    oList1.innerHTML += html;
    oList2.innerHTML += html;
}</script></body></html>123456789101112131415161718192021222324252627282930313233343536373839404142

事件委托好处: 
1.能够有效减少页面上事件处理程序的数量 
2.对于动态增加的子节点,依旧能够实现事件的绑定

最小化访问HTMLCollection的次数

最小化访问HTMLCollection的次数可以极大地改进脚本的性能

<body><script type="text/javascript">//这里关键在于长度length存入了len变量,而不是每次都去访问HTMLCollection的length属性var images = document.
getElementsByTagName
("img"),
    image,
    i,len;for(i=0,len=images.length;i<len;i++){
    image = images[i];    //其他处理}</script></body>123456789101112

注意作用域

避免全局查找

可能优化脚本性能最重要的就是注意全局查找。使用全局变量和函数肯定要比局部的开销更大,因为要涉及作用域链上的查找。 
下面的代码包含了3个对于全局document对象的引用。如果在页面上有多个图片,那么for循环中的document引用就会被执行多次甚至上百次,每次都会进行作用域链查找。

<script type="text/javascript">/*
通过创建一个指向document对象的局部变量,就可以通过限制一次全局查找来提升这个函数的性能。
 */function updateUI(){
    var imgs = document.getElementsByTagName("img");    for(var i=0,len=imgs.length;i<len;i++){
        imgs[i].title = document.title + "image" +i;
    }    var msg = document.getElementById("msg");
    msg.innerHTML = "Update complete";
}function updateUI(){
    //缓存全局变量,减少全局变量的查找。这样就减少了话费在作用域上查找的时间,就能提升脚本的性能。改进后的函数只有一次全局查找。
    var doc = document;    var imgs = doc.getElementsByTagName("img");    for(var i=0,len=imgs.length;i<len;i++){
        imgs[i].title = doc.title + "image" +i;
    }    var msg = doc.getElementById("msg");
    msg.innerHTML = "Update complete";
}</script>123456789101112131415161718192021222324

下面的例子中通过创建一个指向document对象的局部变量,就可以通过限制一次全局查找来提升这个函数的性能。

<script type="text/javascript">function updateUI(){
    //缓存全局变量,减少全局变量的查找。这样就减少了话费在作用域上查找的时间,就能提升脚本的性能。改进后的函数只有一次全局查找。
    var doc = document;    var imgs = doc.getElementsByTagName("img");    for(var i=0,len=imgs.length;i<len;i++){
        imgs[i].title = doc.title + "image" +i;
    }    var msg = doc.getElementById("msg");
    msg.innerHTML = "Update complete";
}</script>123456789101112

避免with语句

with语句会创建自己的作用域,因此会增加其中执行的代码的作用域链的长苏。由于额外的作用域链查找,在with语句中执行的代码肯定会比外面执行的代码要慢。 
看下面这个例子:

<script type="text/javascript">/*
大多数情况下,可以使用局部变量完成相同的事情而不必引入新的作用域
 */function updateBody(){
    with(document.body){
        console.log(tagName);//这里将代码的作用域设置到document.body对象中
        innerHTML = "Hello world";
    }
}function updateBody(){
    var body = document.body;
    console.log(body.tagName);//这里将代码的作用域设置到document.body对象中
    body.innerHTML = "Hello world";
}</script>123456789101112131415161718

大多数情况下,可以使用局部变量完成相同的事情而不必引入新的作用域

<script type="text/javascript">function updateBody(){
    var body = document.body;
    console.log(body.tagName);//这里将代码的作用域设置到document.body对象中
    body.innerHTML = "Hello world";
}</script>

上面是我整理给大家的JS开发中最实用的问题解答,希望今后会对大家有帮助。

相关文章:

重点解答js的几种提交方式

详细讲解JS中Windows对象课程

如何在3f1c4e4b6b16bbbd69b2ee476dc4f83a2cacc6d41bbb37262a98f745aa00fbf0标签中一样可以使用el表达式

以上是在JS开发中最实用的问题解答的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
幕后:什么语言能力JavaScript?幕后:什么语言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来:趋势和预测Python和JavaScript的未来:趋势和预测Apr 27, 2025 am 12:21 AM

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

Python vs. JavaScript:开发环境和工具Python vs. JavaScript:开发环境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

JavaScript是用C编写的吗?检查证据JavaScript是用C编写的吗?检查证据Apr 25, 2025 am 12:15 AM

是的,JavaScript的引擎核心是用C语言编写的。1)C语言提供了高效性能和底层控制,适合JavaScript引擎的开发。2)以V8引擎为例,其核心用C 编写,结合了C的效率和面向对象特性。3)JavaScript引擎的工作原理包括解析、编译和执行,C语言在这些过程中发挥关键作用。

JavaScript的角色:使网络交互和动态JavaScript的角色:使网络交互和动态Apr 24, 2025 am 12:12 AM

JavaScript是现代网站的核心,因为它增强了网页的交互性和动态性。1)它允许在不刷新页面的情况下改变内容,2)通过DOMAPI操作网页,3)支持复杂的交互效果如动画和拖放,4)优化性能和最佳实践提高用户体验。

C和JavaScript:连接解释C和JavaScript:连接解释Apr 23, 2025 am 12:07 AM

C 和JavaScript通过WebAssembly实现互操作性。1)C 代码编译成WebAssembly模块,引入到JavaScript环境中,增强计算能力。2)在游戏开发中,C 处理物理引擎和图形渲染,JavaScript负责游戏逻辑和用户界面。

从网站到应用程序:JavaScript的不同应用从网站到应用程序:JavaScript的不同应用Apr 22, 2025 am 12:02 AM

JavaScript在网站、移动应用、桌面应用和服务器端编程中均有广泛应用。1)在网站开发中,JavaScript与HTML、CSS一起操作DOM,实现动态效果,并支持如jQuery、React等框架。2)通过ReactNative和Ionic,JavaScript用于开发跨平台移动应用。3)Electron框架使JavaScript能构建桌面应用。4)Node.js让JavaScript在服务器端运行,支持高并发请求。

Python vs. JavaScript:比较用例和应用程序Python vs. JavaScript:比较用例和应用程序Apr 21, 2025 am 12:01 AM

Python更适合数据科学和自动化,JavaScript更适合前端和全栈开发。1.Python在数据科学和机器学习中表现出色,使用NumPy、Pandas等库进行数据处理和建模。2.Python在自动化和脚本编写方面简洁高效。3.JavaScript在前端开发中不可或缺,用于构建动态网页和单页面应用。4.JavaScript通过Node.js在后端开发中发挥作用,支持全栈开发。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器