创建可重用的对象

简而言之,对象就是包含一组变量(称为属性)和函数(称为方法)的集合的实例。对象通常由类派生而来,而类中定义了对象拥有的属性和方法。如果你的脚本中都是对象之间的交互操作,那么就可以称之为OO(Object Oriented,面向对象)的脚本。特别要说明的是,JavaScript 是一种原型式(prototype-style)的OO语言,没有类的概念,所有一切都派生自现有对象的一个副本。JavaScript 的主要内置对象有:Object, Function, Array, String, Boolean, Number, Math, Date, RegExp 等等。所有内置对象都可以通过 new 关键字或者其他特殊的语法来创建,例如 function 关键字用于创建 Function 对象,花括号({})是 Object 的简写形式,而方括号([])则是 Array 的简写形式。

创建一个构造函数

function myConstructor(message) {
this.myMessage = message; //私有属性
var separator = '-';
var myOwner = this; //私有方法
function alertMessage() {
alert(myOwner.myMessage);
}
//特权方法(也是公有方法)
this.appendToMessgae = function(string) {
this.myMessage += separator + string;
alertMessage();
}
}
//公有方法
myConstructor.prototype.clearMessage = function(string) {
this.myMessage = '';
}
//静态属性
myConstructor.name = 'jeff';
//静态方法
myConstructor.alertName = function() {
alert(this.name);
}

this

this 在 JavaScript 中是一个依赖于使用它的执行环境被解析的关键字。嗯...,有点难懂,其实就是 this 引用的是包含它的函数作为某个对象的方法被调用时的那个对象。可以通过 call() 和 apply() 重新定义执行环境。

实例:实现一个调试日志

function myLogger(id) {
id = id || 'logWindow';
var logWindow = null;
//用受保护的方法创建日志窗口
var createWindow = function() {
var browserWindowSize = getBrowserWindowSize();
var top = ((browserWindowSize.height - 200) / 2) || 0;
var left = ((browserWindowSize.width - 200) / 2) || 0;
//使用受保护的 logWindow 属性维护引用
logWindow = document.createElement('ul');
//指定 ID 值,以便必要时在DOM树中能够识别它
logWindow.setAttribute('id', id);
//定位日志窗口既设置大小
logWindow.style.position = 'absolute';
logWindow.style.top = top + 'px';
logWindow.style.left = left + 'px';
logWindow.style.width = '200px';
logWindow.style.height = '200px';
logWindow.style.overflow = 'scroll';
//美化外观
logWindow.style.padding = '0';
logWindow.style.margin = '0';
logWindow.style.border = '1px solid black';
logWindow.style.backgroundColor = 'palegoldenrod';
logWindow.style.listStyle = 'none';
//添加到文档主体
document.body.appendChild(logWindow);
};
//向日志窗口中添加新条目
this.writeRaw = function(message) {
if(!logWindow) createWindow();
var li = document.createElement('li');
li.style.padding = '2px';
li.style.borderBottom = '1px solid #000';
li.style.color = 'orangered';
if(typeof message == 'undefined') {
li.appendChild(document.createTextNode('Message was undefined.'));
} else {
li.innerHTML = message;
}
logWindow.appendChild(li); return true;
};
} myLogger.prototype.write = function(message) {
//警告 message 为空值
if(typeof message == 'string' && message.length == 0 || typeof message == 'undefined') {
return this.writeRaw('null message');
}
//如果 message 不是字符串,则尝试调用 toString() 方法,如果不存在则记录对象类型。
if(typeof message != 'string') {
if(message.toString) return this.writeRaw(message.toString());
else return this.writeRaw(typeof message);
}
//转换 <, > ,以便 .innerHTML 不会将 message 作为 HTML 进行解析。
message = message.replace(/</g, '&lt;').replace(/>/g, '&gt;');
return this.writeRaw(message);
}

获取浏览器窗口大小的兼容写法

function getBrowserWindowSize() {
var de = document.documentElement;
return {
'width': (
window.innerWidth
|| (de && de.clientWidth)
|| document.body.clientWidth),
'height': (
window.innerHeight
|| (de && de.clientHeight)
|| document.body.clientHeight)
}
};

DOM2 核心和 DOM2 HTML

DOM 是什么

DOM 是一组用来描述脚本怎样与结构化文档进行交互和访问的web标准。DOM定义了一系列对象,方法和属性,用于访问,操纵和创建文档中的内容,结构,样式以及行为。需要清楚的是 DOM 不是 JavaScript,DOM 是 W3C 开发的一组规范,这些规范规定了 JavaScript 这样的语言为符合标准需要实现的对象,方法和属性。通过建立和遵守规范,可以保证你编写的JavaScript代码在不同的操作环境(例如不同的浏览器)中具有一致的行为和相同的预期效果。

DOM 级别

W3C DOM 并不是只有一份大而全的规范,它分成不同的级别,每个级别包含不同的子规范和模块。DOM 级别有 DOM 1级,DOM 2级,DOM 3级。要知道你选择的浏览器支持何种W3C DOM特性,可以使用 DOMImplementation 对象。在 Web 浏览器中,DOMImplementation 对象被实例化为 document.implementation 。如果浏览器的官方声称支持某种特性,那么可以通过 document.implementation.hasFeature() 方法进行验证。该方法接受两个参数:第一个参数(Core, XML, HTML, Views, StyleSheets, CSS, CSS2, Events等等),第二个参数是DOM级别(1.0,2.0,3.0)。

if(document.implementation) {
if(document.implementation.hasFeature('Core', '2.0')) {
alert('DOM2 Core Supported');
} else {
alert('DOM2 Core Not Supported');
}
} else {
alert('No DOMImplementation Supported');
}

当然也可以打开https://www.w3.org/2003/02/06-dom-support.html页面测试查看该页面的浏览器所有的报告特性。

DOM 核心

当浏览器解析一个 html 文件时,它会根据自身支持的W3C DOM模块把标记转换为对象,树形结构中项的主体部分是Element节点,唯一的特例是表示整个文档的Document和表示标记中根元素<html>的documentElement,需要注意的是标记中每个标签之间的空白符都被转换成了Text节点。然而,在使用IE时,只有当除了空白符之外还夹杂着其他的文本字符时文本节点才会存在。

核心 Node 对象

每个Element都扩展自Node对象,即使是document和documentElement也是如此,只不过它们也有自己独特的属性和方法。

1. 节点名称,值和类型

nodeName 属性取得用于区分节点的标签名称,为了保持一致性,nodeName的值会被转化为大写形式。

对于不基于文档中标签的其他对象来说,nodeName 的值取决于引用对象的类型。

对象 返回值
Element.nodeName 元素的名称,大写
Attr.nodeName 属性的名称,小写
Text.nodeName #text
Comment.nodeName #comment
Document.nodeName #document
DocumentType.nodeName 文档类型的名称,如HTML
DocumentFragment.nodeName #document fragment

与 nodeName 类似,nodeValue 属性对于不同的对象类型也具有不同的含义。

对象 返回值
Element.nodeValue null
Attr.nodeValue 字符串形式的属性值
Text.nodeValue 字符串形式的节点内容
Comment.nodeValue 字符串形式的注释文本
Document.nodeValue null
DocumentType.nodeValue null
DocumentFragment.nodeValue null

DOM 核心对象的 nodeType 常量

nodeType值 等价命名常量
1 Node.ELEMENT_NODE
2 Node.ATTRIBUTE_NODE
3 Node.TEXT_NODE
8 Node.COMMENT_NODE
9 Node.DOCUMENT_NODE
10 Node.DOCUMENT_TYPE_NODE
11 Node.DOCUMENT_FRAGMENT_NODE

如果你在代码中需要检测 nodeType ,尽量使用 DOM 常量(更容易被人看懂,维护和调试)。比如:

if(node.nodeType == Node.COMMENT_NODE) {
//针对注释节点的代码
}

2. 父节点,子节点和同辈节点

  • parentNode属性 引用指定节点的直接父节点;
  • childNodes属性引用的是指定节点的所有子元素,也是包含DOM对象的一个类数组的NodeList对象;
  • firstChild属性引用的是第一个子节点;
  • lastChild属性引用的是最后一个子节点;
  • previousSibling属性引用的是与当前节点前紧邻的同辈节点,如果没有则为 null ;
  • nextSibling属性引用的是与当前节点后紧邻的同辈节点,如果没有则为 null ;

3. 节点的属性

作为核心Attr对象的实例,节点的属性被包含在相应节点的attributes成员的一个NamedNodeMap对象中。包括html预定义属性和自定义属性。

4. 节点的ownerDocument属性

一个节点的ownerDocument属性类似于指向节点所属根文档的引用。可以通过它引用 document, 或者window.document。假如你在某个自定义对象的内部覆盖了 document 对象,可以通过这个属性访问到原始的 document 。

function example(node) {
//在作用域中覆盖document
var document = 'something else';
//使用ownerDocument引用原始DOM文档
var anotherNode = node.ownerDocument.getElementById('id');
//下面这行代码会出错,因为document现在是一个字符串,而非DOM文档
var anotherNode = document.getElementById('id');
}

5. 检测子节点和属性

如果你需要简单的检测一下某个节点是否具有子节点或属性,那么可以使用hasChildNodes()和hasAttributes()方法。

var h2 = document.getElementsByTagName('H2')[0];
console.log(h2.nodeName + ' hasChildNodes: ' + h2.hasChildNodes());
console.log(h2.nodeName + ' childNodes: ' + h2.childNodes);
console.log(h2.nodeName + ' number of childNodes: ' + h2.childNodes.length);
console.log(h2.nodeName + ' hasAttributes: ' + h2.hasAttributes());
console.log(h2.nodeName + ' attributes: ' + h2.attributes);
console.log(h2.nodeName + ' number of attributes: ' + h2.attributes.length);

输出结果为:

H2 hasChildNodes: true
H2 childNodes: [object NodeList]
H2 number of childNodes: 1
H2 hasAttributes: false
H2 attributes: [object NamedNodeMap]
H2 number of attributes: 0

6. 操纵DOM节点树

  • ParentNode.appendChild(newChild) 用于把新节点插入到当前节点末尾;
  • ParentNode.append((节点或字符串)... 更多节点) 用于在当前节点的最后面插入其它节点内容(作为子节点);
  • ParentNode.prepend((节点或字符串)... 更多节点) 用于在当前节点的最前面插入其它节点内容(作为子节点);
  • ParentNode.insertBefore(newNode, referenceNode) 用于在当前的子节点之前插入一个新节点;
  • ParentNode.removeChild(oldChild) 用于删除当前节点的子节点;
  • ParentNode.replaceChild(newChild, oldChild) 用于替换当前节点的子节点为其他节点;
  • ChildNode.before((节点或字符串)... 其它更多节点) 用于在一个子节点之前插入一个或多个节点;
  • ChildNode.after((节点或字符串)... 其它更多节点) 用于在一个子节点之后插入一个或多个节点;
  • ChildNode.replaceWith((节点或字符串)... 更多节点) 用于替换当前节点为其他节点内容;

注意:append(),prepend(),before(),after(),replaceWith()方法的参数既可以是DOM元素,也可以是DOM节点,甚至可以是直接字符内容,这些都是新增的DOM API。

7. 复制和移动节点

首先需要明白的是 document.getElementById('id') 返回的是 Node 对象的引用。

核心Element对象

所有Element对象都拥有Node对象的属性和方法,同时还有其他一些便于操纵节点属性和查找子Element对象的方法。

1. 操纵Element对象的属性

  • getAttribute(name) 方法基于一个字符串形式的属性名称取得相应属性的值
  • setAttribute(name, value) 方法基于一个字符串形式的属性名称设置相应属性的值
  • removeAttribute(name) 方法基于一个字符串形式的属性名称删除相应属性的值

2. 在Element对象中查找Element对象

在Element对象的范围内,可以用来查找其他节点的唯一有效方法是getElementsByTagName(),getElementsByTagName()方法返回的是一个NodeList对象。该方法返回的节点只包括Element节点,不包含其他类型的节点。

核心Document对象

JavaScript 的全局对象是 window 对象,所以这里讨论的就是 window 对象的 document 属性,或者是 window.document。

1. document.documentElement属性

document.documentElement属性是访问文档根元素的快捷方式。对于在浏览器呈现的HTML文档而言,所谓的根元素就是标签。

2. 使用Document对象的方法创建节点

  • createAttribute(name): 创建节点类型为Node.ATTRIBUTE_NODE的Attr节点。
  • createComment(data): 创建节点类型为Node.COMMENT_NODE的Comment节点。
  • createDocumentFragment(): 创建节点类型为Node.DOCUMENT_FRAGMENT_NODE的DocumentFragment节点。
  • createElement(tagName): 创建节点类型为Node.ELEMENT_NODE的Element节点。
  • createTextNode(data): 创建节点类型为Node.TEXT_NODE的Text节点。

3. 使用Document对象的方法查找Element对象

document.getElementById('id'), document.getElementsByTagName('tagName'), document.getElementsByClassName('className')

DOM HTML

DOM2 HTML 的 HTMLDocument 对象

当HTML文档呈现在浏览器中时,window.document 中的DOM文档对象实际上是HTMLDocument对象的一个实例,HTMLDocument 对象从核心的Document对象中继承了所有成员,而且还添加了一些属性和方法,其中增加的属性如下:

  • title: 包含位于<title>标签中的字符串;
  • referrer: 包含链接到当前页面的前一个页面的URL;
  • domain: 包含当前站点的域名;
  • URL: 包含当前页面地址栏中的URL;
  • body: 引用从节点开始的DOM树;
  • images: 是一个包含当前文档中所有标签的数组(集合);
  • links: 是一个包含与当前文档中所有标签对应的DOM节点的数组(集合);
  • forms: 是一个包含与当前文档中所有标签对应的DOM节点的数组(集合);
  • cookie: 是一个包含当前页面中所有cookie信息的字符串;

增加的方法如下:

  • open(): 打开一个文档;
  • close(): 关闭当前文档;
  • write(data): 将输入写入到文档中;
  • writeln(data): 将输入写入文档的同时写入一个换行符;
  • getElementsByName(elementName): 获取具有相同name值的元素集合;

JavaScript DOM 高级程序设计读书笔记一的更多相关文章

  1. JavaScript DOM 高级程序设计读书笔记二

    响应用户操作和事件 事件就是操作检测与脚本执行的组合,或者基于检测到的操作类型在某个对象上调用事件侦听器(事件处理程序). 事件的类型 事件可以分为几种类型:对象事件,鼠标事件,键盘事件(只适用于do ...

  2. javascript高级程序设计读书笔记-事件(一)

    读书笔记,写的很乱   事件处理程序   事件处理程序分为三种: 1.html事件2. DOM0级,3,DOM2级别  没有DOM1 同样的事件 DOM0会顶掉html事件   因为他们都是属性  而 ...

  3. AngularJS高级程序设计读书笔记 -- 大纲篇

    零. 初衷 现在 AngularJS 4 已经发布了, 楼主还停留在 1.x 的阶段, 深感自卑. 学习 AngularJS 的初衷是因为, 去年楼主开始尝试使用 Flask 开发自动化程序, 需要用 ...

  4. Javascript高级程序设计读书笔记(第10章 DOM)

    第10章 DOM 10.1  节点层次 每个节点都有一个nodeType属性,用于表明节点的类型.任何节点类型必是下面中的一个: Node.Element_NODE(1); NODE.ATTRIBUT ...

  5. javascript高级程序设计读书笔记

    第2章  在html中使用javascript 一般都会把js引用文件放在</body>前面,而不是放在<head>里, 目的是最后读取js文件以提高网页载入速度. 引用js文 ...

  6. JavaScript高级程序设计-读书笔记(7)

    第22章 高级技巧 1.高级函数 (1)安全的类型检测 在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串. ...

  7. JavaScript高级程序设计 读书笔记

    第一章 JavaScript 简介 第二章 Html中使用JavaScript 第三章 基本概念 第四章 变量,作用域,内存 第五章 引用类型 第六章 面向对象 第七章 函数表达式 第八章 BOM 第 ...

  8. Javascript高级程序设计读书笔记(第六章)

    第6章  面向对象的程序设计 6.2 创建对象 创建某个类的实例,必须使用new操作符调用构造函数会经历以下四个步骤: 创建一个新对象: 将构造函数的作用域赋给新对象: 执行构造函数中的代码: 返回新 ...

  9. JavaScript高级程序设计-读书笔记(6)

    第20章 JSON JSON是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量 JSON的语法可以表示一下三种类型的值 l        简单值:使用与JavaScript相同的语法,可以在JS ...

随机推荐

  1. vue中的tab栏切换内容变换

    <!DOCTYPE html> <html lang="cn-zh"> <head> <meta charset="UTF-8& ...

  2. Spring MVC(四)文件上传

    文件上传步骤 1.写一个文件上传的页面 2.写一个文件上传的控制器 注意: 1.method="post" 2.enctype="multipart/form-data& ...

  3. Android 字体适配方案

    开发过程中,按照UI设计尺寸做好UI页面,当用户自定义自己的手机字体大小之后UI完全没法看了,这个时候就在想让app字体大小始终一致就好了 下面看一下,出现的问题和解决方案     做个简单的例子,先 ...

  4. (爬虫)urllib库

    一.爬虫简介 什么是爬虫?通俗来讲爬虫就是爬取网页数据的程序. 要了解爬虫,还需要了解HTTP协议和HTTPS协议:HTTP协议是超文本传输协议,是一种发布和接收HTML页面的传输协议:HTTPS协议 ...

  5. 斐波那契数列(C#)

    斐波那契数,亦称之为斐波那契数列(意大利语: Successione di Fibonacci),又称黄金分割数列.费波那西数列.费波拿契数.费氏数列,指的是这样一个数列:1.1.2.3.5.8.13 ...

  6. 如何定位“Operating system error 32(failed to retrieve text for this error. Reason: 15105)”错误中被占用的文件

      之前在这篇"Operating system error 32(failed to retrieve text for this error. Reason: 15105)"博 ...

  7. Thermostat:双层存储结构的透明巨页内存管理机制

    这是一篇由密歇根大学的Neha Agarwal 和 Thomas F. Wenisch,发表在计算机系统顶会ASLOS的论文,Thermostat: Application-transparent P ...

  8. 搭建ES6开发环境

    https://github.com/IOJINDD/ES6-dev 在gulpfile最后一行加上: gulp.task('default', ['compile-es6', 'pack-js', ...

  9. Mysql 字符串指定位置插入空格

    UPDATE flow_data_243 SET data_15=CONCAT(LEFT(data_15,10),' ',RIGHT(data_15,LENGTH(data_15)-10)) WHER ...

  10. CentOS7 升级 gvim 到 8.x 版本

    因为 CentOS7 在默认情况下,通过 yum 安装的 vim-X11.x86_64 版本为 7.x 版本,对 Youcompleteme 支持不好.故需要升级到 8.x 版本. 以下记录 gvim ...