关于《Javascript Dom 编程艺术(第二版)》

变量的作用域
如果一个函数的内部使用了全局变量的名字,即使本意是用于局部变量,JS也会认为是全局变量,当对这个变量进行赋值,全局变量也会被改变。
let global = 1;
function para(){
let local = 10;
global += local;
}
para();
alert(global); //此时global=11
此时,解决这个问题只需要一个小的修改
let global = 1;
function para(){
let local = 10;
let global = 0;
return global+local;
}
para();
alert(global); //此时global=10
内建对象
数组也是一种内建对象,内建对象是JS已经定义好可以直接用的方法。
const beatles = new Array(); //定义新数组
const currenttime = new Date(); //获得当前日期
const year = currenttime.getYear(); //获得年
const month = currenttime.getMonth(); //获得月
const day = currenttime.getDay(); //获得日
...
const num = 5.1234
const integer = Math.round(num); //四舍五入取整
Math内建对象
assert(Math.ceil(0.3),"答案为1"); //取值为浮点数“大于”的整数
assert(Math.floar(0.9),"答案为0"); //与ceil相反,取“小于”的整数
assert(Math.round(0.5),"答案为1");
assert(Math.round(0.4),"答案为0"); //常用的四舍五入
3种DOM方式获取元素
document.getElementById('Id'); //获得一对一
document.getElementByTagName('Tagname'); //获得一个数组
document.getElementByClassName('class'); //获得的也是一个数组
//特殊
<div class="div1 div2 div3"></div>
...
let div = document.getElementByClassName('div1 div2 div3'); //顺序颠倒也可以
assert(div.length != null,"这是一个数组");
高效加载JS代码文件
包含脚本的最佳方式就是使用外部文件
<script src="scripts/function1.js"></script>
<script src="scripts/function2.js"></script>
<script src="scripts/function3.js"></script>
<script src="scripts/function4.js"></script>
这种方式是不高效率的,可以吧4个JS文件放置在一个JS文档中,页面发送请求次数减少。同时,当一个Html文件需要多个JS文件需要使用,建议将JS代码放在一个scripts文件夹,提高性能。
再者,脚本文件建议放置最后位置,如下图显示。
<!Doctype html>
<html>
<head>...</head>
<body>
....
<script src="./scripts/math.js"></script> //在body最后
</body>
</html>
网页会等其余所有文件加载完成后才会加载脚本,不会影响用户体验。
同时,压缩脚本也是一种办法,将原来的工作副本xxx.js复制粘贴一份,作为精简文件xxx.min.js,将文件空格,注释清空。
function preparelinks(){if(!document.getElementsByTagName) return false;let tagArrays=document.getElementsByTagName("a");for(let index=0;index<tagArrays.length;index++){
...
网上有代码压缩工具,可以百度下载。
调用JS函数方法
function popUp(URL){
window.open(URL,"新网页","width:350 height:400");
//BOM下window对象的open函数:window.open(url,name,features);
}
“javascript:伪协议调用”
<a href="javascript:popUp('http://shermanblog.xyz');">点击链接</a>
“内嵌的事件处理函数”
<a href="#" onclick="popUp('http://shermanblog.xyz');return false;">点击链接</a>
但是这两种方法一旦浏览器禁用JS就毫无作用。解决如下:
<a href="http://shermanblog.xyz" onclick="popUp('http://shermanblog.xyz');return false">点击链接</a>
“分离Javascript”—最好的解决方式
<script src="./test.js"></script> //调用外部JS文件
<a href="http://shermanblog.xyz" class="popup">点击连接</a>
...
//外部test.js
window.onload = preparelinks;
function preparelinks(){
let tagArrays = document.getElementByTagName("a");
for(let index= 0; index < tagArrays.length; index++){
if(tagArrays[index].getAttribute("class")==="popup"){
tagArrays[index].onclick = function(){
popUp(tagArrays.getAttribute('href'));
return false;
};
}
}
}
function popUp(URL){
window.open(URL,"新网页","width:350 height:400");
}
平稳退化:不论是失去JS,CSS文件不会影响网页的内容生成。
对象检测
检测一个浏览器是否支持DOM语句,比如getElementsByTagName
function preparelinks(){
//执行下面语句之前,增加一个判断
if(!document.getElementsByTagName) return false;
//若是不支持这个判断,浏览器会跳过这个函数,不影响网页
let tagArrays = document.getElementsByTagName("a");
for(let index= 0; index < tagArrays.length; index++){
...
网页加载完毕触发onload事件
网页加载完成后立刻执行外部的JS脚本
function Fun(){.....}
window.onload = Fun;
多个JS脚本时:
function Fun1(){...}
function Fun2(){...}
window.onload = function(){
Fun1();
Fun2();
}
编写一个addLoadEvent函数,简化window.onload()(*important)
function addLoadEvent(fun){
let oldonload = window.onload;
if(typeof window.onload != 'function'){
window.onload = fun;
}else{
window.onload = function(){
oldonload();
fun();
}
}
}
之后调用Fun1,Fun2只需要
addLoadEvent(Fun1);
addLoadEvent(Fun2);
Return的难点
return true; //函数返回正确的处理结果,等于 执行符
return false; //函数取消作用,终止处理,等于 终止符
return 表达式; //表达式的结果作为返回结果
没有特殊情况,一般不加return
检查再优化代码
动态创建标记
传统方法
1.document.write(“语句”);
快捷的将字符串添加到文档body中
<body>
<script>document.write("This is a new message.")</script>
</body>
2.inner.html
可以读,也可以写,比doucmenr.write更加快速,但是会替换掉所有的内容,比较霸道。
DOM方法
一个文档可以看作是一个DOM树,如果想要增加内容,就要在某个节点后增加文本节点。用到的方法以下:
document.createElement(‘元素名’) //创建一个元素节点
document.createTextNode(‘内容’) //创建一个文本节点
document.appendChild(‘节点名’) //将节点作为子节点接上去
document.insertBefore(‘新节点名’,’目标节点名’) //将元素节点作为兄弟节点插入到目标节点前面
parentNode //父节点
lastChild //该节点下的最后一个子节点
firstChild //该节点下的第一个子节点 相当 于childNode[0]
nextSibling //该节点的下一个兄弟节点
⚠️不存在document.insertAfter(‘新节点名’,’目标节点名’)**这个方法⚠️
但是可以写一个方便使用的脚本并且收录到JS中随时调用
function insertAfter(newElement,targetElement){
let parentNode = targetElement.parentNode;
if(targetElement == parentNode.lastChild){
parentNode.appendChild(newElement);
}else{
parentNode.insertBefore(newElement,targetElement.nextSibling);
}
}
Dom获得Style属性
<p id="p1" style="color:grey; font-family:'Arial' ; font-weight:bold">This is a test.</p>
...
let para = document.getElmentById('p1');
alert(typeof para.style); //结果为一个对象
alert(para.style.color); //结果等于grey
alert(para.style.fontWeight); //结果为bold
注意⚠️的是:font-weight在DOM中用驼峰命名法表示fontWeight,因为“-”在语句中会被认为是减号,会报错
DOM属性的特殊用法
当函数发生这么一种情况:
“既不能使用全局变量,也不能使用局部变量,并且还是需要这么一种东西能够介于他们两者之间的变量。”
只与某个特定元素有关的变量是存在的,而且我们经常会使用就是“属性”。Javascript允许我们为元素创建属性:
element.property = "value";
//只要你愿意,可以任意定一个名为myName的属性,并且值为Sherman
element.myName = "Sherman";
这很像是在创建一个变量,但区别是这个变量专属于某个特定的元素。我们创建一个元素属性的变量,它已经存在,并且可以在函数内使用任何方法,避免了全局变量和局部变量的BUG