高程小tips

 

1、DOM操作往往是JS程序中开销最大的部分,应尽量减少DOM操作。-P285  P297例子

2、元素的classList属性: 元素的classLis即该元素的class的值的集合,是一个列表(数组)。-P290
针对classList操作的相关方法有:

👉add(value): 将给定的字符串(类名)值添加到列表中,如果值已经存在,就不添加了。
//添加'current'类
let box = document.getElementById('box');
box.classList.add('current');

👉contains(value): 检测列表中是否存在给定的值,存在则返回true,反之则返回false。
//检测box类名中是否存在'current'
console.log(box.classList.contains('current'));//true

👉remove(value): 从列表中删除给定的字符(类名)。
//删除类名'current'
box.classList.remove('current');
有了classList属性,除非你要删除所有类名,或者完全重写元素的class属性,否则也就用不到className属性了。

3、焦点管理: -P291

👉document.activeElement属性(在文档加载完成后)始终引用DOM中当前获得了焦点的元素。
var button = document.getElementById("myButton");
button.focus();
console.log(document.activeElement === button); //true

👉document.hasFocus()方法,用于确定文档是否获得了焦点。
var button = document.getElementById("myButton");
button.focus();
console.log(document.hasFocus()); //true

4、document.readyState -P292

readyState属性反应文档加载的状态,他有两个值:loading,即正在加载文档;complete,即,文档已加载完毕。
基本用法⬇️
if(document.readyState == 'complete'){
//...
}

5、自定义属性 -P293

为元素添加自定义属性须加前缀data-。
<div id="test" data-attr="try"><div>
可以通过元素的dataset属性来访问元素的自定义属性。
let box = document.getElementById('test');
console.log(box.dataset);//{attr: try}

6、innerHTML性能优化 -P297

创建和销毁html解析器会带来性能损失。
for (var i=0, len=values.length; i < len; i++){
ul.innerHTML += "<li>" + values[i] + "</li>"; //尽量避免这种操作
}
这种每次循环都设置一次innerHTML的做法效率很低,而且,
每次循环还要从innerHTML中读取一次信息,这就意味着每次循环要访问两次innerHTML。
最好的做法是单独构建字符串,然后再一次性地将结果字符串赋给innerHTML⬇️
var itemsHtml = "";
fot(let i = 0; i < values.length; i ++){
itemsHtml += "<li>" + values[i] + "</li>";
}
ul.innerHTML = itemsHtml;
这个例子的效率要高得多,因为它只对innerHTML执行了一次赋值操作。

7、scrollIntoView() -P298

其作用类似于为元素设置焦点,使浏览器滚动让特定元素出现在视口内⬇️
let box = document.getElementById('box');
box.scrollIntoView();

8、child与childNodes的区别: -P299

前者返回元素中还是元素的子节点,后者则返回所有子节点(包括文本节点,空白节点等)。

9、contains()方法,用于判断某个节点是不是另一个元素的后代节点,返回true/false。 -P300

console.log(box1.contains(box2));//判断box2是否为box1的后代节点

10、innerText属性(2016年被纳入规范,作用类似innerHTML) -P301

innerText读取时,将文档树中所有文本拼接起来。
<div id="content">
<p>This is a <strong>paragraph</strong> with a list following it.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul> </div>

console.log(document.getElementById('content').innerText);//输出以下内容

This is a <strong>paragraph</strong> with a list following it.
Item 1
Item 2
Item 3

innerText写入值时,会删除元素的所有子节点,插入包含相应文本值的文本节点。

 

 


1、getBoundingClientRect()方法。 -P324
该方法返回一个矩形对象,包含4个属性:left,top,bottom,right,即元素在页面中相对于视口的位置(与屏幕四周的距离)。

2、with语句。用于将代码的作用域设置到一个特定的对象中。 -P60
基本语法: with(expression)statement;
定义with语句的目的主要是为了避免多次编写同一个对象的工作,例如:
var qs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href;
以上几行代码都包含loaction对象,如果用with语句,可以把上面的代码改写成如下所示:
with(location){
var qs = search.substring(1);
var hostName = hostname;
var url = href;
}

ps:大量使用with语句会导致性能下降,不建议使用。

3、currentTarget与target。 -356
在事件处理程序内部,对象this始终等于currentTarget的值,而target只包含事件的实际目标(即,target在事件流的目标阶段;currentTarget在事件流的捕获,目标及冒泡阶段。event.currentTarget指向事件所绑定的元素,而event.target始终指向事件发生时的元素)。
若直接将事件处理程序指定给了目标元素,则this、currentTarget和target包含相同的值。
在需要通过一个函数处理多个事件时,可以使用type属性:
let btn = document.getElementById('btn');
let handler = () => {
switch(event.type){
case 'click':
console.log('event.type');
break;
case 'mouseover':
//...
break;
case 'mouseout':
//...
break;
}
};
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;

4、常用事件兼容
获取事件对象⬇️
element.onclick = (e)=>{
var e = e || window.event;
//...
}
阻止默认事件⬇️
element.onclick = (e)=>{
var e = e || window.event;//window可省略不写
e.preventDefault ? e.preventDefault() : e.returnValue = false;
//...
}
清除拖拽默认⬇️
document.ondragstart = ()=>{
return false;
}
添加事件监听⬇️
element.attachEvent('onclick',fn);//IE
element.addEventListener('click',fn,false);//其他
解除事件监听⬇️
element.detachEvent('onclick',fn);
element.removeEventListener('click',fn,false);
事件源⬇️
ie: window.event.srcElement
标准: event.target
阻止冒泡⬇️
function stopPropagation(){
var e = e || window.event;//window可省略不写
if(e.stopPropagation){
e.stopPropagation();
}else{
e.cancelBubble = true;
}
}

5、addEventListener()的优点在于可以为一个元素的同一个事件添加多个事件处理程序⬇️ -p351

btn.addEventListener('click',fn1,false);
btn.addEventListener('click',fn2,false);
这两个事件处理程序会按照添加它们的顺序触发。
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除,移除时传入的参数与添加处理程序时使用的参数相同,这也意味着通过addEventListener()添加的匿名函数无法移除。
btn.addEventListener('click',function(){
console.log('test');
},false);
//...
btn.removeEventLisenter('click',function(){//无效
console.log('test');
},false);

6、EventUntil(跨浏览器的事件对象)、addHandler与removeHandler -P354
作用:视情况分别使用DOM0级方法、DOM2级方法或IE方法来添加事件。该方法属于一个名叫EventUtil的对象,这个对象可用来处理浏览器之间的差异。
addHandler接受三个参数:要操作的元素,事件名称,事件处理程序函数。
与addHandler对应的方法是removeHandler(),它也接受相同的参数。这个方法的作用是移除之前添加的事件处理程序--无论该事件是采取什么方式添加到元素中的。

这两个方法的实现原理(封装)⬇️
var EventUtil = {

addHandler: function(element,type,handler){
if(element.addEventListener){
element.addEventListener(element,type,handler);
}else if(element.attachEvent){
element.attachEvent('on' + type,handler);
}else{
element['on'+type] = handler;
}
},

removeHandler: function(){
if(element.removeEventLisenter){
element.removeEventLisenter(type,hadler,false);
}else if(element.dettachEvent){
element.dettachEvent('on' + type,handler);
}else{
element['on'+type] = null;//使用方括号语法来将属性名指定为事件处理程序。
}
}

}
基本用法⬇️
var btn = document.getElementById('btn');
var fn = ()=>{
console.log('clicked');
}
EventUtil.addHandler(btn,'click',fn);
//...
EventUtil.removeHandler(btn,'click',fn);

可参考:https://www.cnblogs.com/joyco773/p/6076635.html  跨浏览器事件对象及其封装自己的函数

 

 

 

1.call()和applay()用于在特定的作用域中调用函数,实际上等于设置函数体内this对象的值(扩充函数赖以运行的作用域)。
首先,apply()方法接受两个参数,一个是在其中运行的作用域,另一个是参数数组。其中,第二个参数可以是Array的实例,也可以是arguments对象。
如:sum.apply(this,arguments)/sum.apply(this,[n1,n2,n3]);
call()和apply()方法的作用相同,他们的区别在于接收参数的方式不同。在使用call()方法时,传递给函数的参数必须逐个列举出来。如sum.call(this,n1,n2,n3);
在不给函数传参的情况下,使用哪个方法都一样。P116

 

2.arguments.callee,虽然arguments的主要用图是保存函数参数,但他的callee属性是一个指针,指向拥有这个arguments对象的函数。P113

 

3.setInterval()的缺点:某些间隔会被跳过、多个定时器的代码执行之间的间隔可能会预期的小。
解决:使用链式setTimeout()调用。P611
setTimeout(function(){
//...
setTimeout(arguments.callee,interval);
},interval)

 

4.DOM操作比非DOM交互需要更多的内存和CPU时间,故应尽量减少DOM操作。P614

 

5.使用定时器对函数进行节流,基本思想:某些代码不可以在没有间断的情况连续执行。第一次调用函数,创建一个定时器,在指定的间隔之后运行代码。当第二次调用该函数
时,他会清除前一次的定时器并设置另一个。函数节流常用语onresize等频繁触发的事件中。P614

 

6.indexOf()和lastIndexOf()都接收两个参数,要查找的项和(可选的)表示查找起点位置的索引。其中,indexOf()从数组的开头向后找,lastIndexOf()则从数组的末尾开始向前查找P95。

 

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

 

posted @ 2018-01-08 09:11  LLLLily  阅读(153)  评论(0编辑  收藏  举报