乐趣区

关于前端:javascript高级程序设计读书笔记七

上班曾经很晚了,还是决定啃会儿,回顾回顾根底的常识点儿~
进入正题咯~

第 9 章 客户端检测

检测 web 客户端的伎俩很多,而且各有利弊。但最重要的还是要晓得,不到万不得已,就不要应用客户端检测,只有能找到更通用的办法,就应该优先采纳更通用的办法。
一言以蔽之,先设计最通用的计划,而后再应用特定于浏览器的技术加强该计划。

能力检测

function getElement(id){if(document.getElementById){return document.getElementById(id);
    }else if (document.all){return document.all[id];
    }else {throw new Error("No way to retrieve element!");
    }
}

要理解能力检测,首先必须了解两个重要概念:
第一个就是先检测达成目标的最罕用的个性 ,能够保障代码最优化,因为在少数状况下都能够防止测试多个条件。
第二个重要的概念就是必须测试理论要用到的个性。一个个性存在,不肯定意味着另一个个性也存在。

在浏览器环境下测试任何对象的某个个性是否存在,能够应用上面函数。

function isHostMethod(object,property){var t = typeof object[property];
    return t == 'function' || (!!(t == 'object' && object[property])) || t == 'unknow';
}
result = isHostMethod(xhr, "open");   //true
result = isHostMethod(xhr, "foo");   //false

第 10 章 DOM

1、节点档次—Node 类型
Javascript 中的所有节点类型都继承自 Node 类型,因而所有节点类型都共享着雷同的根本属性和办法。
每个节点都有一个 nodeType 属性,敢于表明节点的类型。
想要确定一个节点是不是 element 类型,上面办法:

if(someNode.nodeType == 1){     // 实用于所有浏览器
 alert(“Node is an element .”);
}

要理解节点的具体信息,能够用 nodeName 和 nodeValue 这两个属性。nodeName 中保留的始终都是元素的标签名,而 nodeValue 的值始终是 null。
每个节点都有一个 childNodes 属性,其中保留着一个 NodeList 对象。
上面栗子小姐姐为大家展现如何拜访保留在 NodeList 中的节点

var firstChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var count = someNode.childNodes.length;

上面办法能够将 NodeList 对象转换为数组。来栗子小姐姐吧

function convertToArray(nodes){
 var array = null;
 try{array = Array.prototype.slice.call(nodes,0);     // 针对非 IE 浏览器
 }catch (ex){array = new Array();
  for(var i = 0,len=nodes.length; i<len;i++){array.push(nodes[i]);
  }
 }
 return array;
}

parentNode 属性 :指向文档数的父节点;蕴含在 childNodes 列表中的所有节点都具备雷同的父节点,它们的 parentNode 指向同一个节点。
previousSibling 和 nextSibling 属性,能够拜访同一个列表中的其余节点。
firstChild 和 lastChild 属性,别离指向 childNodes 列表中的第一个和最初一个节点。
下图形象地展现了上述关系:

hasChildNodes()办法 在蕴含一个或多个字节点的状况下返回 true。
ownerDocument 属性,指向示意整个文档的文档节点。文档节点是每个文档的根节点。每个文档智能由一个文档元素。在 HTML 页面中,文档元素适中都是 <html> 元素。

操作节点的罕用办法:appendChild()办法 ,用于向 childNodes 列表的开端增加一个节点。更新实现后,appendChild() 返回新增的节点。

var returnedNode = someNode.appendChild(newNode);
alert(returnedNode == newNode);      //true
alert(someNode.lastChild == newNode);  //true

insertBefore()办法 ,把节点放在 childNodes 列表中特定的地位上,而不是放在开端。
承受两个参数:要插入的节点和作为参照的节点。插入节点后,被插入的节点会变成参照节点的前一个同胞节点,同时被办法返回。

// 插入后成为最初一个子节点
returnedNode = someNode.insertBefore(newNode, null);
alert(newNode == someNode.lastChild);    //true

// 插入后成为第一个子节点
var returnedNode = someNode.insertBefore(newNode, someNode.firstChild);
alert(returnedNode == newNode);    //true
alert(newNode == someNode.firstChild);   //true

// 插入到最初一个子节点后面
returnedNode = someNode.insertBefore(newNode, someNode.lastChild);
alert(newNode == someNode.childNodes[someNode.childNodes.length-2]};   //true

replaceChild()办法,要替换的节点将由这个办法返回并从文档树中移除,同时由要插入的节点占据其地位。
承受两个参数:要插入的节点和要替换的节点。

// 替换第一个子节点
var returnedNode = someNode.replaceChild(newNode, someNode.firstChild);

如果只想移除而非替换节点,就能够应用 removeChild() 办法。这个办法承受一个参数,即要移除的节点,被移除的节点将成为办法的返回值。

// 移除第一个子节点
var formerFirstChild = someNode.removeChild(someNode.firstChild);

replaceChild()办法和 removeChild()办法一样,移除的节点依然为文档所有,只不过在文档中没有了本人的地位。

有两个办法,是所有类型的节点都有的,第一个是 cloneNode(),用于创立调用这个办法的节点的一个完全相同的正本。
cloneNode() 承受一个布尔值参数,示意是否执行深复制。
参数为 true,执行深复制,也就是复制节点及其整个子节点树。
参数为 false, 执行浅复制,即只复制节点自身。
复制后返回的节点正本属于文档所有,但并没有为它指定父节点。

cloneNode()办法不会复制增加到 DOM 节点中的 JavaScript 属性,例如事件处理程序。这个办法只复制个性、子节点,其余所有都不会复制。
normallize()办法,惟一的作用就是解决文档树中的文档节点。

2、Document 类型

3、Element 类型。
要拜访元素的标签名,能够应用 nodeName 属性,也能够应用 tagName 属性;这两属性会返回雷同的值。

var div = document.getElementById("myDiv");
alert(div.tagName);          //"DIV"  在 HTML 中,标签名始终都以全副大写示意
alert(div.tagName == div.nodeName);      //true

HTMLElement 类型间接继承自 Element 并增加了一些属性。增加的这些属性别离对应于每个 HTML 元素中都存在的下列规范个性。

<div id="myDiv" class="bd" title="body text" lang="en" dir="ltr"></div>
var div = document.getElementById("myDiv");
alert(div.id);               //"myDiv"
alert(div.className);               //"bd"  留神这里是 className, 不是 class, 是因为 class 是 ECMAScript 的保留字
alert(div.title);               //"body text"
alert(div.lang);               //"en"
alert(div.dir);               //"ltr"

操作个性的 DOM 办法次要有三个,别离是 getAttribute()、setAttribute()和 removeAttribute()。

<div id="myDiv" my_special_attribute="hello"></div>
var div= document.getElementById("myDiv");
alert(div.getAttribute("id"));       //"myDiv"
alert(div.getAttribute("class"));    //"bd"
// 想要失去 class 个性值,应该传入 "class" 而不是 "className", 后者只有通过对象属性拜访个性时才用。var value = div.getAttribute("my_special_attribute");  //hello
// 通过 getAttribute()办法也能够获得自定义个性的值。

有两类非凡的个性,它们尽管有对应的属性名,但属性的值与通过 getAttribute()返回的值并不相同。
第一类个性时 style, 用于通过 CSS 为元素指定款式。通过 getAttribute()拜访时,返回的 style 个性值中蕴含的是 css 文本,而通过属性来拜访它则返回一个对象。
第二类不同凡响的个性时 onclick 这样的事件处理程序。当在元素上应用时,onclick 个性中蕴含的是 Javascript 代码,则会返回一个 Javascript 函数。
因为存在这些差异,在通过 Javascript 以编程形式操作 DOM 时,开发人员常常不实用 getAttribute(), 而是只应用对象的属性。只有在获得自定义个性值得状况下,才会应用 getAttribute()办法。

与 getAttribute()对应的办法是setAttribute()。承受两个参数,要设置的个性名和值。

div.setAttribute("id", "someOtherId");
div.setAttribute("class", "ft");
div.id = "someOtherId";  // 因为所有个性都是属性,所以间接给属性赋值能够设置个性的值。div.align = "left";

removeAttribute()办法,用于彻底删除元素的个性,调用这个办法不仅会革除个性的值,而且也会从元素中齐全删除个性。
div.removeAttribute("class");

document.createElement()办法能够创立新元素。这个办法只承受一个参数,即要创立元素的标签名。
var div = document.createElement("div");
因为新元素尚未被增加到文档树中,因而设置这些个性不会影响浏览器的显示,要把新元素增加到文档树,能够应用 appendChild()、insertBefore()或 replaceChild()办法。
document.body.appendChild(div); // 把新创建的元素增加到文档的 <body> 元素中。

4、Text 类型
应用 document.createTextNode()创立新文本节点。

var element = document.createElement("div");
element.className = "message";

var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);

document.body.appendChild(element);

DOM 操作技术
动静脚本:创立动静脚本有两种办法,插入内部文件和直接插入 JavaScript 代码。别离是以下两种封装好的办法。

function loadScript(url){var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = url;
    document.body.appendChild(script);
}
loadScript("client.js");
function loadScriptString(code){var script = document.createElement("script");
    script.type = "text/javascript";
    try{script.appendChild(document.createTextNode(code));
    }catch (ex){script.text = code;}
    document.body.appendChild(script);
}
loadScriptString("function sayHi(){alert('hi');}");

动静款式

function loadStyle(url){var link = document.createElement("link");
    link.rel = "stylesheet";
    link.type = "text/css";
    link.href = url;
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(link);
}
loadStyle("styles.css");
function loadStyleString(css){var style = document.createElement("style");
    style.type = "text/css";
    try{style.appendChild(document.createTextNode(css));
    }catch (ex){style.styleSheet.cssText = css;}
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(style);
}
loadScriptString("body{background-color:red}");

小结:
DOM 是语言中立的 API,用于拜访和操作 HTML 和 XML 文档。
DOM 由各种节点形成,简要总结如下。

  • 最根本的节点类型是 Node, 用于抽象地示意文档中一个独立的局部;所有其余类型都继承自 Node。
  • Document 类型示意整个文档,是一组分层节点的根节点。在 javascript 中,document 对象是 document 的一个实例,应用 document 对象,有很多种形式能够查问和获得节点。
  • Element 节点示意文档中的所有 HTML 或 XML 元素,能够用来操作这些元素的内容和个性。
  • 另外还有一些节点类型,别离示意文本内容、正文、文档类型、CDATA 区域和文档片段。

拜访 DOM 的操作在少数状况下都很直观,不过在解决 <script> 和 <style> 元素时还是存在一些复杂性。因为这两个元素别离蕴含脚本和款式信息,因而浏览器通常会将它们与其余元素区别对待。
了解的 DOM 的要害,就是了解 DOM 对性能的影响。DOM 操作往往是对 Javascript 程序中开销最大的局部,因此拜访 NodeList 导致的问题为最多。NodeList 对象都是 ” 动静的 ”,这就意味着每次拜访 NodeList 对象,都会运行一次查问。有鉴于此,最好的方法就是尽量减少 DOM 操作。

明天就先更新到这里吧,未完待续,宝宝们

退出移动版