javascript书籍中的经典,里面非常多细节解释的十分详细,而且有些晦涩难懂的概念,比如js面向对象、原型链、继承等,也能层层递进,深入浅出。忍不住赞叹:写的太棒了!
浏览器宿主中的JavaScript = ECMAScript + DOM + BOM。
Web浏览器只是ECMAScript实现的宿主环境之一。宿主环境不仅提供基本的ECMAScript实现,也会提供该语言的扩展(比如DOM/BOM),以便语言与环境之间对接交互。
DOM(文档对象模型)是针对XML但经过扩展用于HTML的应用程序编程接口。DOM把整个页面映射为一个多层节点结构。HTML的每个组成部分都是某种类型的节点,这些节点又包含着不同类型的数据。
提供访问和操作网页内容的方法与接口
js 是ECMAScript的具体实现。其定义了包含语法、关键字等,但不包括与浏览器相关的API。 js引擎不是独立运行的,它运行在宿主环境中。web宿主环境就是浏览器。
<script>
会暂停解析html + 浏览器遇到<body>
标签才开始呈现内容,所以script应该放在body的最后从属于ECMAScript规范定义。从技术角度讲,函数在ECMAScript中是对象,不是一种数据结构
。(笔者注:所以js语言可以很好的实践函数式编程思想。关于函数式编程思想可以看笔者另外一篇笔记:函数式编程)
JS变量松散,只是在特定时间用于保存特定值的一个名字。即不存在定义某个变量时必须保存何种数据类型
复制的是指针,指针指向真实的内存
(js是无法获取以及操作内存,只能通过指针代理)// 以上解释了这个赋值问题
var a = { name: 1 }
var b = a // b和a指向同一个内存地址
b = { aget: 1 } // b被指向新的内存地址,断开了与a的联系
函数是对象,函数名是指针(函数名代理着内存)
// 以下都是等价的
function add(a, b) {
return a + b
}
var add = function(a, b) {
return a + b
}
// 这种方式较为明显的诠释了实质:函数是对象,函数名是指针
var add = new Function('a', 'b', 'a + b')
指有权访问另一个函数作用域中的变量的函数。原理:
function addThird(c) {
var d = 10
return function (a, b) {
return a + b + c + d // 该函数能访问另外一个函数作用域的变量:c、d
}
}
addThird(3)(1, 2) // 16
最典型需要闭包案例:
// 连续打印5,而不是从1~4
for (var i = 1; i < 5; i++) {
setTimeout(function() { console.log(i) }, i * 1000)
}
以上代码我们试图假设循环中的每个迭代在运行时都会给自己“捕获”一个i副本,但根据作用域的工作原理,实际情况是尽管循环中的五个函数是在各个迭代中分布定义的,但是这些函数都是被封闭在一个共享的全局作用域中
,因此实际上只有一个i。
所以所有函数共享一个i的引用。
for (var i = 1; i < 5; i++) {
(function() {
var j = i // 存储i副本,使得settimeout函数可以访问到外部作用域
setTimeout(function() { console.log(j) }, j * 1000)
})()
}
// 一般编码更常用这种方式
for (var i = 1; i < 5; i++) {
(function(j) {
setTimeout(function() { console.log(j) }, j * 1000)
})(i)
}
块作用域本质上是将块变成一个可以被关闭的作用域。
for (var i = 1; i < 5; i++) {
let j = i // 块作用域
setTimeout(function() { console.log(j) }, j * 1000)
}
for循环头部的let声明
还有一个特殊行为。这个行为指出变量在循环过程中不止被声明一次,每次迭代都会声明
。随后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量。
for (let i = 1; i < 5; i++) {
setTimeout(function() { console.log(i) }, i * 1000)
}
DOM(文档对象模型),提供访问和操作网页内容的方法和接口
,是针对HTML和XML文档的一个API(扩展XML)。DOM描绘了一个层次化的节点树
。
借助DOM提供的API,开发人员可轻松自如的增删改查任何节点,即获得控制页面内容和结构的主动权。
1998年成为W3C标准,由两个模块组成:DOM Core 和DOM HTML。DOM Core规定如何映射基于XML的文档结构;DOM HTML模块则在DOM Core的基础上扩展,添加了对HTML的对象和方法(比如在对象上直接绑定事件el.onclick=function)。
DOM2目标宽泛了很多。主要有DOM2使得DOM1的DOM Core模块经过扩展支持XML命名空间。 同时引入了新的模块:
目的同样是扩展DOM API,以满足操作XML的所有需求。
除了DOM Core和DOM HTML接口之外,SVG语言(也是基于XML的)也发布了针对自己的DOM标准,使得SVG对象上可操作相对应的新的API。其他语言还包括MathML、SMIL
HTML不支持XML命名空间,但XHTML支持XML命名空间
。命名空间使用xmlns
特性来指定。在混合使用两种语言的情况下,命名空间用处非常大。比如混合了XHTML和SVG语言的文档:
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect x="0" y="0" widht="100" height="100"></rect>
</svg>
</body>
</html>
通过设置命名空间,svg元素的所有子元素,以及这些元素的所有特性,都被认为属于http://www.w3.org/2000/svg命名空间。
由于引入了命名空间,所以DOM2级的Document类型新增了关于命名空间的方法。比如document.createElementNS(namespaceURI, tagName)
var myDiv = document.getElementByClassName('myDiv')
myDiv.classList.add('current')
myDiv.style.width = '100px'
// DOM0事件处理
var btn = document.getElementById('myBtn')
btn.onclick = function() { ... }
// DOM2事件处理,好处:可以添加多个事件处理程序
var btn = document.getElementById('myBtn')
btn.addEventListener('click', function() { ... }, false) // 最后为false,代表冒泡阶段捕获
元素的可见大小由高度、宽度决定,包括所有内边距、滚动条和边框大小(注意,不包括外边距)。
元素的偏移量。
注意offsetLef和offsetTop是相对于offsetParent元素
。
// 案例:知道某个el元素在页面上的偏移量
// 等同于el.getBoundingClientRect().top
function getElementTop(el) {
var actualTop = el.offsetTop
var current = el.offsetParent
while(current) {
actualTop += current.offsetTop
current = current.offsetParent
}
return actualTop
}
指的是元素内容及内边距所占的空间大小
(不包括边框和外边距)。
// 案例:获取视口大小
function getViewport(el) {
if (document.compatMode == 'BackCompat') {
// ie 7 以下版本
return {
width: document.body.clientWidth,
height: document.body.clientHeight
}
} else {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
}
}
}
指的是包含滚动内容的的元素大小。
有些元素(如html),即使没有执行任何代码也能自动的添加滚动条,但另外一些元素(如div),则需要通过css的overflow属性设置才能滚动
。
scrollHeight/scrollWidth主要用于确定元素内容的实际大小。例如带有垂直滚动条的页面总高度是document.documentElement.scrollHeight
浏览器为每个元素都提供了getBoundingClientRect()
方法(注意该方法的兼容性)。这个方法会返回一个矩形对象,包含4个属性: left、top、bottom、right。
这些属性给出了元素在页面中相对于视口(页面坐标原点)的位置。