Javascript 高级程序设计--总结【三】
******************** Chapter 8 BOM ********************
BOM由浏览器提供商扩展
window:
既是js访问浏览器窗口的接口,又是Global对象
全局变量会成为window 的属性,但是定义全局变量和window属性还是有差别,在于能否通过delete删除
var age = 10;//本质上来说,configurable 属性设置为false, 所以不能delete 删除
window.name = 'test';
delete window.age;//false, IE<9 抛出错误
delete window.name;//true, IE<9 抛出错误
console.log(window.age);//10
console.log(window.name);//undefined
var n = window.a;//undefined 这里不会抛出错误,相当于是一次属性查询
窗口关系及框架:
window.frames.length;
top.frames[''];//最好使用 top 的方式,因为top始终指向最高层的框架window
parent:
表示当前框架的父框架
除非最高层的窗口是通过window.open()打开的,否则其window对象的name属性不会包含任何值
self:
始终指向window
窗口位置:
其他: screenLeft\screenTop
Firefox: screenX\screenY
var leftPos = (typeof window.screenLeft == 'number') ? window.screenLeft : window.screenX;
var leftPos = (typeof window.screenTop == 'number') ? window.screenTop : window.screenY;
IE\Chrome: screenTop 表示的是可见区域的离屏幕顶端距离,也就是工具栏高度值
这两个方法移动窗口,但是一般会被浏览器禁用
window.moveTo(10,10);//移动到指定位置
window.moveBy(10,10);//移动指定像素距离
窗口大小:
//获取窗口视图的大小
var pageW = window.innerWidth,
pageH = window.innerHeight;//IE8及以前的版本不支持
if (typeof pageW != 'number') {
if (document.compatMode == 'CSS1Compat') {
pageW = document.documentElement.clientWidth;
pageH = document.documentElement.clientHeight;
} else {
pageW = document.body.clientWidth;
pageH = document.body.clientHeight;
}
}
//调整窗口大小,但是一般会被浏览器禁用
window.resizeTo(100,100);
window.resizeBy(10,20);
导航和打开窗口:
window.open('http://......',frameName);
window.open('http://......',_self);//_parent,_top,_blank
第三个参数: fullscreen\height\left\location\menubar\resizable\scrollbars\status\toolbar\top\width
var newWin = window.open('','','height=200,width=400,top=10,resizable=yes');
//对于新的打开窗口,可以执行以下两个方法
newWin.resizeTo(500,500);
newWin.moveTo(100,100);
newWin.close();
newWin.closed;//获取新窗口的关闭状态
newWin.opner;//调用 window.open() 的对象
setTimeout\ setInterval:
var id = setTimeout(function(){},1000);
clearTimeout(id);
setTimeout(function(){},1000);
setInterval(function(){},1000);
//一般使用 setTimeout() 来替代setInterval()
var num = 0;
var max = 10;
function increment() {
num++;
if (num < max) {
setTimeout(increment, 1000);
} else {
alert('OK');
}
}
setTimeout(increment, 1000);
系统对话框:
alert()\confirm()\prompt()
window.print()
window.find()
location对象:
window.location 和 document.location 引用的是同一个对象
属性:
hash '#contents'
host 'www,google.com:80'
hostname 'www,google.com'
href 'http://www,google.com'
pathname '/Login/'
prot '80'
protocol 'http:'
search '?name=test'
查询字符串参数:
//封装获取查询字符串的方法
function getQuery() {
var res = {};
var sear = location.search.length > 0 ? location.search.substring(1) : "";
var items = sear.length ? sear.split('&') : [];
var len = items.length, item = null, key = null,value=null;
for (var i = 0; i < len; i++) {
item = items[i].split('=');
key = decodeURIComponent(item[0]);
value = decodeURIComponent(item[1]);
if (key.length) {
res[key] = value;
}
}
return res;
}
url位置操作:
//以下的方式都是等价的
window.location.assign("http://www.baidu.com");
window.location = 'http://www.baidu.com';
location.href = 'http://www.baidu.com';
//可以动态修改地址参数
location.hash = '#section';
location.search = '?test=1';
以上方式都会在浏览器产生历史记录,可以在浏览器进行后退操作,但是如果使用replace()操作就不会产生历史记录。
location.replace("http://www.baidu.com");//没有历史记录
location.reload();//可能从缓存中加载
location.reload(true);//强制从服务器加载
navigator对象:
navigator.appCodeName; //浏览器名称:Mozilla
navigator.appName;//完整浏览器名称 :Netscape
navigator.userAgent;//浏览器的用户代理字符串
检测插件:
navigator.plugins
//只能在非IE的环境中使用
function hasPlugin(name) {
name = name.toLowerCase();
var len = navigator.plugins.length;
for (var i = 0; i < len; i++) {
if (navigator.plugins[i].name.toLowerCase().indexOf(name) > -1) {
return true;
}
}
return false;
}
//对于IE的检测方式,COM的方式实现,所以name表示插件的标识符
//Flash 标识符 ShockwaveFlash.ShockwaveFlash
function hasIEPlugin(name) {
try {
new ActiveXObject(name);
return true;
} catch (e) {
return false;
}
}
//测试
function hasFlashPlugin() {
var res = hasPlugin('Flash ');
if (!res) {
return hasIEPlugin(name);
}
return res;
}
//plugins 集合的refresh()方法更新集合,如果参数传入 true,那么会刷新所有的包含插件的页面
navigator.plugins.refresh();
注册处理程序:
//将一个站点注册为Rss源
navigator.registerContentHandler('application/rss+xml','http://www.somereader.com?feed=%s','some reader');
navigator.registerProtocolHandler('mailto','http://www.somemailclient.com?cmd=%s','some mail client');
screen 对象:
screen.availLeft;//未被系统占用的左侧像素值
screen.availTop ;//未被系统占用的上方像素值
screen.colorDepth;//颜色位数
history对象:
history.length;//历史页面数量
history.back();//后退一页
history.forward();//前进一页
history.go(1);
******************** Chapter 9 客户端检测 ********************
//这里研究过深,难度太大,并且实用性不强,后续有时间需要,可以再研究
******************** Chapter 10 DOM ********************
IE中所有的DOM对象都是以COM对象的形式实现的。这些对象与原生的JavaScript对象的行为或活动特点不一致。
节点层次
Node类型://除IE之外都可以访问的类型
Node.ELEMENT_NODE(1);
Node.ATTRIBUTE_NODE(2);
Node.TEXT_NODE(3);
Node.CDATE_SECTION_NODE(4);
Node.ENTITY_REFRENCE_NODE(5);
Node.ENTITY_NODE(6);
Node.PROCESSING_INSTRUCTION_NODE(7);
Node.COMMIT_NODE(8);
Node.DOCUMENT_NODE(9);
Node.DOCUMENT_TYPE_NODE(10);
Node.DOCUMENT_FRAGMENT_NODE(11);
Node.NOTATION_NODE(12);
var ele = document.getElementById('test');
if (ele.nodeType == Node.ELEMENT_NODE) {//IE没有公开Node类型的构造函数,这里会报错
if (window.console) {
console.log("node is an element");
}
}
//适用于所有的浏览器
if (ele.nodeType == 1) {}
NodeList:
根据实际DOM情况变化的对象
var chil = ele.childNodes[0];
chil = ele.childNodes.item(0);
//将NodeList转换为数组,但是IE8及以下的浏览器不支持,因为都是COM对象
Array.prototype.slice.call(ele.childNodes, 0);
//更加通用的方式
function toArray(nodes) {
var arr = null;
try {
arr = Array.prototype.slice.call(nodes, 0);
} catch (e) {
arr = new Array();
for (var i = 0, len = nodes.length; i < len ; i++) {
arr.push(node[i]);
}
}
}
//nextElementSibling 和 previousSibling
if (ele.nextElementSibling == null) {
console.log("this is last one");
} else if (ele.previousSibling == null) {
console.log("this is first one....");
}
//parentNode
//hasChildNodes
if (ele.hasChildNodes()) {
console.log('has children...');
}
//ownerDocument 表示整个文档的文档节点
ele.ownerDocument;
节点操作:
var ele = document.getElementById("test");
//返回新增的节点,如果node已经是文档的一部分,那么就是移动到新的节点位置的效果
var newNode = ele.appendChild(node);
//如果第二个参数为null,那么效果就是appendChild()
ele.insertBefore(node,null);
ele.insertBefore(node,ele.firstChild);//插入后成为第一个节点
//替换最后一个节点
var retNode = ele.replaceChild(newNode,ele.lastChild);
//移除最后一个节点并返回
var lNode = ele.removeChild(ele.lastChild);
//深拷贝,包括后代元素
ele.cloneNode(true);
//浅拷贝,不包括后代元素
ele.cloneNode(true);
//处理文本节点,删除后代空文本节点,合并相邻文本节点
ele.normalize();
Document类型:
document 是HTMLDocument的实例;
nodeType: 9;
nodeName: '#document';
//访问子节点
document.documentElement;//始终指向HTML元素 <html>
document.childNodes;
//获取 body 元素
document.body;
//获取文档结构
document.doctype;
不同的浏览器对document.doctype 的支持差别很大
document.title;
document.URL;
document.referrer;
document.domain;
//如果原地址是 www.baidu.com, 那么只能设置 baidu.com
document.domain = 'baidu.com';
document.domain = 'sina.com';//这样设置为出错的
//对于含有内嵌框架的页面很有用,因为不同子域的页面无法通过JavaScript通信的,但是如果把document.domain 都设置成相同的值,那么就可以通信了
同样如果一开始设置为了 松散的,就不能设置为紧绷的
document.domain = 'baidu.com';
document.domain = 'www.baidu.com';//不能再设置回紧绷的
//namedItem
var ps = document.getElementsByTagName("p");//NodeList
//寻找结果集中的 name=p1 的项
console.log(ps.namedItem('p1'));//ps['p1']
document.getElementsByName('');//
特殊集合:
document.anchors;// 带有name 的<a>
document.forms;
document.images;
document.links;//带有 href 的<a>
DOM一致性检测:
//一般不使用这种方式,并不准确,还是使用能力检测
document.implementation.hasFeature('XML','1.0');
//注意转义
document.write("<script type='' src=''><\/script>");
//多一个换行符
document.writeln("<script type='' src=''><\/script>");
//重写整个页面
window.onload = function () {
document.write("onload 之后重写整个页面");
}
open()和close() 分别用于打开的关闭网页输出流
Element 类型
nodeType: 1
tagName 等价于 nodeName
ele.id;
ele.title;
ele.className;
ele.lang;
ele.dir;//左右对齐方式
ele.getAttribute('id');
ele.getAttribute('class');
html5 规范: 自定义特性添加 data- 前缀
setAttribute('id','test');
removeAttribute('class');
DOM元素本身属性的访问:
div.id;
div.align;
var atrs = ele.attributes;
var id = atrs.getNamedItem('id');
atrs.removeNamedItem('class');
atrs.setNamedItem(newatr);
function getAttrs(ele) {
var name, val, arr = new Array();
for (var i = 0, len = ele.attributes.length; i < len; i++) {
//specified 表示是否设置了该属性,为了兼容IE7
if (ele.attributes[i].specified) {
name = ele.attributes[i].nodeName;
val = ele.attributes[i].nodeValue;
arr.push(name + "=" + val);
}
}
return arr.join(" ");
}
createElement():
//这种方式对于IE7 是有问题的
var div = document.createElement("div");
div.id = 'a';
IE7问题总结:
不能设置动态创建的 iframe 的name特性;
不能通过表单的reset() 方法重设动态创建的 input 元素
动态创建的 type='reset' 重设不了表单
动态创建的一批name 相同的单选按钮彼此毫无关系
子节点操作:
for (var i = 0, len = ele.childNodes.length; i < len; i++) {
if (ele.childNodes[i].nodeType == 1) {
//执行元素操作
}
}
Text类型:
nodeType: 3
nodeName: '#text'
nodeValue(date): 文本值
normalize:
var ele = document.getElementById("div1");
//创建文本节点
var txt = document.createTextNode('text');
ele.appendChild(txt);
//同一个元素可以添加多个文本节点
var txt1 = document.createTextNode('txt2');
ele.appendChild(txt1);
console.log(ele.childNodes.length);//3
//合并元素中所有的文本节点
ele.normalize();
console.log(ele.childNodes.length);//1
splitText:
var div = document.createElement('div');
var txt = document.createTextNode('this is good!');
div.appendChild(txt);
document.body.appendChild(div);
console.log(div.childNodes.length);//1
//分割子节点, 返回4之前的节点
var before = div.firstChild.splitText(4);
console.log(div.firstChild.nodeValue);//this
console.log(before.nodeValue);//is good
console.log(div.childNodes.length);//2
Comment 类型:
noteType:8
nodeName:'#comment'
//创建
var comment =document.createComment("this is commnet");
CDATASection 类型: 主要是针对XML文档
nodeType:4
nodeName:'#cdata-section'
//在XML文档中可以如下创建
document.createCDataSection()
DocumentType 类型: Firefox\Safari\Opera 支持
nodType:10
document.doctype.name;
IE及更早版本不支持DocumentType,会被解释为注释
DocumentFragment 类型:
nodeType;11
nodeName:'#document-fragment'
文档片段不会再文档中显示,相当于一个‘仓库’来使用,也不占用资源,把文档片段可以添加到文档中,但是只会将文档片段的子节点添加到文档中去
//通过fragment 的方式多次添加元素,可以让页面少量的渲染
var frag = document.createDocumentFragment();
var li = null;
for(var i =0;i<3;i++){
li = document.createElement("li");
li.appendChild(document.createTextNode('hello '+i));
frag.appendChild(li);
}
document.getElementById("ul").appendChild(frag);
Attr 类型:
nodeType: 11
属性:name\value\specified
var attr = document.createAttribute('align');
attr.value='left';
ele.setAttributeNode(attr);
console.log(ele.attributes['align'].value);//left
console.log(ele.getAttributeNode('align').value);//left
console.log(ele.getAttribute('align'));//left
DOM 操作技术:
动态脚本:
function loadJs(url){
var script = document.createElement('script');
script.type='text/javascript';
script.src=url;
document.body.appendChild(script);
}
//直接加载js 代码的方式,考虑IE的兼容性
function loadjsText(txt){
var script = document.createElement("script");
script.type='text/javascript';
try
{
script.appendChild(document.createTextNode(txt)
}catch(e){
//IE 是不允许 script 节点访问子节点的,所以上面进行异常捕捉
script.text=txt;
}
document.body.appendChild(script);
}
动态样式:
function loadStyle(){
var link = document.createElement('link');
link.rel='stylesheet';
link.type='text/css';
link.href='style.css';
var head = document.getElementsByTagName('head')[0];
head.appenChild(link);
}
function loadStyleText(txt){
var style = document.createElement('style');
style.type='text/css';
try{
style.appenChild(document.createTextNode(txt));
}catch(e){
//重用设置styleSheet.cssText 或者设置为空字符串,容易让IE崩溃
style.styleSheet.cssText = txt;
}
var head = document.getElementsByTagName('head')[0];
head.appenChild(style);
}
操作表格:
var tb = document.createElement('table');
var body = document.createElement('body');
tb.appenChild(body);
body.insertRow(0);
body.rows[0].insertCell(0)
body.rows[0].cells[0].appenChild(document.createTextNode('testTb'));
document.body.appendChild(tb);
使用NodeList:
这是动态改变的,应当尽量减少对NodeList 的访问
var divs = document.getElementsByTagName('div'),t;
//由于divs.length 是动态更新的,所以这里会造成无限循环
for(var i=0; i < divs.length; i++){
t = document.createElement('div');
document.body.appendChild(t);
}
//这样在使用,保存在临时变量中
for(var i=0, len = divs.length; i < len; i++){
t = document.createElement('div');
document.body.appendChild(t);
}