第一次看了《JavaScript高级程序设计》第二版,那时见到手上的书,第一感觉真是好厚的一本书啊。现在再次回顾一下,看的是《JavaScript高级程序设计》第三版,并记录一些了内容。
第1章:JavaScript简介
JavaScript的历史、版本,可以看到一个有趣的故事。
JavaScript是什么? 一个完整的JavaScript应该有3个不同的部分组成:
1. ECMAScript(核心)
ECMAScript规定了语言的:语法、类型、语句、关键字、保留字、操作符、对象
2. 文档对象模型(DOM)
文档对象模型(DOM, Document Object Model)是针对XML但经过扩展用于HTML的应用程序接口(API, Application Programming Interface)。(通过DOM创建的表示文档的树形图,开发人员获得了控制页面内容和结构的主动权,借助API,可以轻松的处理节点)
DOM1级主要是影射文档的结构。
DOM2级引入了新模块,DOM视图、DOM事件、DOM样式、DOM遍历和范围
DOM3级引入了以统一方式加载和保存文档的方法
3. 浏览器对象模型(BOM)
BOM只处理浏览器窗口和框架,习惯把针对浏览器的JavaScript扩展算作BOM的一部分。
弹出新浏览器窗口
移动、缩放和关闭浏览器窗口
浏览器详细信息的 navigator 对象
浏览器加载页面的详细信息的 location 对象
显示器分辨率详细信息的 screen 对象
对 cookies 的支持
XMLHttpRequest / ActiveXObject
第2章:在HTML中使用JavaScript
<script>元素定义的属性:async、charset、defer、src、type
1. 在页面中嵌入javascript代码
2. 在页面中引入javascript文件
推荐把javascript放在页面</body>标签的前面
推荐尽可能使用外部javascript文件来包含javascript代码
可维护、可缓存、适应未来
文档模式: document.compatMode用来判断当前浏览器采用的渲染方式
if(document.compatMode == "CSS1Compat"){ //标准模式 Standards Mode } if(document.compatMode == "BackCompat"){ //怪异模式 Quirks Mode }
第3章:基本概念
1. 语法
区分大小写
标识符:就是变量、函数、属性的名字,或者函数的参数。
第一个字符是字母、下划线_ 、美元符号$,其他字符可以是字母、下划线、美元符号、数字
私有的属性、方法多用_下划线定义第一个字符
非JS原生对象的变量、属性用美元符号定义第一个字符
注释
//单行注释
/* (多行)块级注释 */
严格模式
"use strict";
语句:javascript中语句以一个分号结尾,如果省略分号,有解析器确定语句结尾。
2. 关键字和保留字
关键字
保留字
保留字建议加上: let yield
3. 变量
ECMAScript的变量是松散类型的,可以用来保存任何类型的数据。
定义变量使用 var 操作符 (多用局部变量、少用全局变量)
4. 数据类型
基本数据类型:undefined null boolean number string
复杂数据类型:object
使用 typeof 操作符来检测变量数据类型
"undefined" —— 如果值未定义
"boolean" —— 如果值是布尔值
"string" —— 如果值是字符串
"number" —— 如果值是数值
"object" —— 如果值是对象或者null
"function" —— 如果值是函数
5. 操作符
一元操作符
递增、递减(++ 、--)
加、减 (+、-)
位操作符
按位非(~)
按位与(&)
按位或(|)
按位异或(^)
左移(<<)
有符号右移(>>)
无符号右移(>>>)
布尔操作符
逻辑非(!) 逻辑与(&&) 逻辑或(||)
乘性操作符
乘法(*) 除法(/) 求模(%)
加性操作符
加法(+) 减法(-)
关系操作符
小于(<) 大于(>) 小于等于(<=) 大于等于(>=)
等性操作符
相等(==) 不相等(!=) 全等(===) 不全等(!==)
赋值操作符
*= /= %= += -= <<= >>= >>>=
条件操作符
variable = boolean_expression ? true : false;
逗号操作符(,)多用于声明多个变量
6. 语句
if / do while / while / for / for in / switch / break continue / (label / with)
if(expression){ //code... } do{ //code... }while(expression); while(expression){ //code... } for(var i = 0; i < count; i++){ //code... } for(property in expression){ //code... } switch(expression){ case value1: //code... break; case value2: //code... break; default: //code... } //break 立即退出循环 执行循环后的语句(结束整个循环体) //continue 退出当前循环 回到循环顶部执行下一个循环(结束单次循环)
7. 函数 参数
function functionName(arg0,arg1,...){ //code... //arguments //arguments.length //arguments.callee }
第4章:变量、作用域和内存问题
1. 基本类型和引用类型的值
动态的属性 复制变量值 传递参数 检测类型
定义基本类型值和引用类型值:创建一个变量并为变量赋值。
引用类型的值可以添加属性和方法,也可以改变和删除其属性和方法
基本类型的值不可添加属性或者方法
2. 执行环境和作用域
执行环境定义了变量或函数有权访问的其他数据,决定了它们各自行为。
在web浏览器中,全局环境是window对象。
某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在环境中的所有变量和函数也会被销毁。
当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。
延长作用域链 没有块级作用域
3. 垃圾收集
标记清除 引用计数 性能问题 管理内存
第5章:引用类型
object 类型
创建object实例: new操作符 object构造函数 对象字面量表示法
array 类型
创建数组:Array构造函数 数组字面量表示法
var colors = new Array('red','green','blue'); var colors = ['red','green','blue'];//推荐使用字面量表示法
检测数组
对于一个网页或一个全局作用域,使用 instanceof 操作符
if(value instanceof Array){ //code... }
ECMAScript 5新增了 Array.isArray() 方法 (支持的浏览器 IE9+ / Firefox 4+ / Safari 5+ Opera 10.5+ / Chrome)
可以自定义一个检测方法
if(!Array.isArray){ Array.isArray = function(value){ return Object.prototype.toString.call(value) === "[object Array]"; } }
所有对象都有 toString() / valueOf()方法。
数组的 toString() 方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。valueOf()返回的还是数组。
var colors = ['red','green','blue']; console.log( colors.toString() ) //red,green,blue console.log( colors.valueOf() ) //["red", "green", "blue"]
数组 栈、 队列方法
栈数据结构(后进先出)
队列数据结构(先进先出)
push() 接收任意个参数,并把它们逐个添加到数组末尾 返回数组修改后的长度length
pop() 从数组末尾移除最后一项 减少length的值 返回移除的项
shift() 移除数组第一项 length减1 返回移除的项
unshift() 在数组前端添加任意个项 返回数组修改后的长度length
数组 排序方法
reverse() 用于颠倒数组中元素的顺序
sort() 对数组的元素进行排序
数组 操作方法
concat() 基于当前数组创建一个新数组 如果有参数则把参数加在新数组后面
slice() 基于当前数组的一或者多项创建一个新数组 接受一个或者两个参数 就是开始位置和结束位置
splice() 用于插入、删除或替换数组的元素 返回从原始数组删除的项组成的一个数组 如果没有删除项返回空数组
//删除 var arr=['a','b','c','d']; arr.splice(1,2) //删除了'b','c' 返回['b','c'] 此时arr为['a','d'] //插入 var arr=['a','b','c','d']; arr.splice(1,0,'e','f') //没有删除任何项 返回[] 插入了'e','f' 此时arr为['a','e','f','b','c','d'] //替换 var arr=['a','b','c','d']; arr.splice(1,2,'e','f') //删除了'b','c' 返回['b','c'] 插入了'e','f' 此时arr为['a','e','f','d']
数组 位置方法
ECMAScript 5为数组新增了两个位置方法 indexOf() lastIndexOf() (支持的浏览器 IE9+ / Firefox 2+ / Safari 3+ Opera 9.5+ / Chrome)
可以这样扩展:if(typeof Array.prototype.indexOf != "function"){
if(typeof Array.prototype.indexOf != "function"){ Array.prototype.indexOf = function(searchElement, fromIndex){ var index = -1, i = 0, n = this.length; fromIndex = fromIndex * 1 || 0; for(; i < n; i++){ if(i >= fromIndex && this[i] === searchElement){ index = i; break; } } return index; } } if(typeof Array.prototype.lastIndexOf != "function"){ Array.prototype.lastIndexOf = function(searchElement, fromIndex){ var index = -1, i, n = this.length, l = n - 1; fromIndex = fromIndex * 1 || l; for(i = l; i > -1; i--){ if(i <= fromIndex && this[i] === searchElement){ index = i; break; } } return index; } }
数组 迭代方法
ECMAScript 5为数组新增了5个迭代方法: forEach() map() filter() every() some() 每个方法都接收两个参数,要在每一项运行的函数、运行该函数的作用域对象;传入每一项运行函数会接收三个参数:数组项的值、该项在数组中的位置、数组对象本身。(支持的浏览器 IE9+ / Firefox 2+ / Safari 3+ Opera 9.5+ / Chrome)
forEach: 对数组每一项运行给定函数,没有返回值
map: 对数组中每一项运行给定函数,返回 函数调用后的项 组成的数组
filter: 对数组中每一项运行给定函数,返回 函数调用后结果为true的项 组成的数组
every: 对数组中每一项运行给定函数,如果 函数调用后每一项结果都为true 就返回true
some: 对数组中每一项运行给定函数,如果 函数调用后只要任何一项结果为true 就返回true
可以这样扩展:
if(typeof Array.prototype.forEach != "function"){ Array.prototype.forEach = function(fn, context){ var i = 0, n = this.length; if(typeof fn === "function"){ for(; i < n; i++){ fn.call(context, this[i], i, this); } } } } if(typeof Array.prototype.map != "function"){ Array.prototype.map = function(fn, context){ var arr = [], i = 0, n = this.length; if(typeof fn === "function"){ for(; i < n; i++){ arr.push(fn.call(context, this[i], i, this)); } } return arr; } } if(typeof Array.prototype.filter != "function"){ Array.prototype.filter = function(fn, context){ var arr = [], i = 0, n = this.length; if(typeof fn === "function"){ for(; i < n; i++){ !!fn.call(context, this[i], i, this) && arr.push(this[i]); } } return arr; } } if(typeof Array.prototype.every != "function"){ Array.prototype.every = function(fn, context){ var passed = true, i = 0, n = this.length; if(typeof fn === "function"){ for(; i < n; i++){ if(passed === false) break; passed = !!fn.call(context, this[i], i, this); } } return passed; } } if(typeof Array.prototype.some != "function"){ Array.prototype.some = function(fn, context){ var passed = false, i = 0, n = this.length; if(typeof fn === "function"){ for(; i < n; i++){ if(passed === true) break; passed = !!fn.call(context, this[i], i, this); } } return passed; } }
数组 缩小方法
ECMAScript 5为数组新增了2个缩小方法:reduce() reduceRight() 这两个方法都会迭代数组的项,然后构建一个最终返回的值。两个方法都接收两个参数,在每一项调用的函数、作为缩小基础的初始值。传入的函数接收4个参数,前一个值、当前值、项的索引、数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参是数组的第一项,第二个参数是数组的第二项。(支持的浏览器 IE9+ / Firefox 3+ / Safari 4+ Opera 10.5+ / Chrome)
可以这样扩展:
if(typeof Array.prototype.reduce != "function"){ Array.prototype.reduce = function(fn, initialValue){ var previous = initialValue, i = 0, n = this.length; if(typeof initialValue === "undefined"){ previous = this[0]; i = 1; } if(typeof fn === "function"){ for(; i < n; i++){ this.hasOwnProperty(i) && (previous = fn(previous, this[i], i, this)); } } return previous; } } if(typeof Array.prototype.reduceRight != "function"){ Array.prototype.reduceRight = function(fn, initialValue){ var previous = initialValue, n = this.length, i = n - 1; if(typeof initialValue === "undefined"){ previous = this[n - 1]; i--; } if(typeof fn === "function"){ for(; i > -1; i--){ this.hasOwnProperty(i) && (previous = fn(previous, this[i], i, this)); } } return previous; } }
Date 类型
Date类型使用自UTC(Coordinated Universal Time, 国际协调时间) 1970年1月1日午夜(0时)开始经过的毫秒数保存日期。Date类型保存的日期能够精确到1970年1月1日之前或之后的285 616年。
ECMAScript 5新增了1个 Date.now() 方法,这个方法返回一个日期时间的毫秒数。(支持的浏览器 IE9+ / Firefox 3+ / Safari 3+ Opera 10.5+ / Chrome)
可以这样扩展:
if(!Date.now){ Date.now = function(){ return (new Date()).valueOf(); } } //一个实例 var start = Date.now(); //run some code... var stop = Date.now(), result = stop - start; console.log(result); //等同于 var start = +new Date(); //run some code... var stop = +new Date(), result = stop - start; console.log(result);
一些处理日期、时间常用方法:
getTime() //返回日期的毫秒数 与valueOf()相同 getFullYear() //取得日期4位数的年份 getMonth() //取得日期的月份(0--11) getDate() //取得日期的天数(1--31) getDay() //取得日期的星期 (0--6)0是星期日 getHours() //取得日期的小时数(0--23) getMinutes() //取得日期的分钟数(0--59) getSeconds() //取得日期的秒数(0--59) getMilliseconds() //取得日期的毫秒数
RegExp 类型
创建一个正则表达式:
var expression = / pattern / flags;
其中模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、向前查找以及方向引用。每个表达式可以带有一个或者多个标志(flags),用以标明表达式的行为。
一些常用正则表达式规则:
g //全局 i //不分大小写 m //多行 ^ //匹配字符的开始 $ //匹配字符的结束 [...] //方括号内任意字符 [^...] //不在方括号内任意字符 . //除换行符和其他行终止符以外的字符 w //字母和数字 相当于[a-zA-Z_0-9] 注意下划线 W //不是字母和数字 相当于[^a-zA-Z_0-9] s //空白符 S //非空白符 d //数字 相当于[0-9] D //非数字 相当于[^0-9] {n,m} //匹配前一项至少n次 不超过m次 {n,} //匹配前一项n次 或更多次 {n} //匹配前一项n次 ? //0次或1次 等价{0,1} + //1次或者多次 等价 {1,} * //0次或者多次 等价 {0,} | //分隔 选择 匹配左边或右边 () //合成 定义 组合
RegExp 实例方法
exec() 这个方法接收一个参数,要应用模式的字符串,返回包含第一个匹配项信息的数组,或者在没有匹配下返回null。
test() 这个方法接收一个字符串参数,在与模式匹配返回true,否则返回false。
Function 类型
函数实际上是对象,每个函数都是 Function 类型的实例。
函数声明 函数表达式
//函数声明 function add(a,b){ return a + b; } //函数表达式 注意末尾分号,就像声明一个变量一样 var add = function(a,b){ return a + b; };
没有重载(深入理解) 作为值的函数 函数内部属性 函数的属性和方法
prototype属性: 在引用类型中,prototype是保存它们所有实例方法的真正所在。
call() apply() 这个两个方法都是在特定的作用域调用函数,实际上是设置函数内this对象的值。 apply方法接收两个参数:一个运行函数的作用域,一个参数数组,第二个参数可以是Array实例,也可以是arguments对象。call方法类似apply:第一个参数是运行函数作用域,后面是每个参数,就是参数要逐个列举出来。
ECMAScript 5新增了1个 bind() 方法,这个方法创建一个函数实例,其this值会被绑定到函数的参数的值(参数为一个对象)。(支持的浏览器 IE9+ / Firefox 4+ / Safari 5.1+ Opera 12+ / Chrome)
可以这样实现:
if(!Function.prototype.bind){ Function.prototype.bind = function(oThis){ var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function(){}, fBound = function(){ return fToBind.apply(this instanceof fNOP && oThis ? this : oThis || window, aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }; } //一个使用实例 this.x = 9; var bb = { x: 88, getX: function(){ return this.x; } } alert( bb.getX() ) //88 var getX = bb.getX; alert( getX() ) //9 var bindGetX = getX.bind(bb); alert( bindGetX() ) //88
基本包装类型
boolean类型 number类型 string类型
toFixed() //按指定小数位返回数值字符串的表示 var num = 10; alert( num.toFixed(2) ) // "10.00" //访问字符串中特定字符的方法 charAt() //取得字符串中特定字符 接收一个参数 基于0的字符位置 var str = "abc"; alert(str.charAt(2)) //c charCodeAt() 和charAt()一样 不过返回的是特定字符的编码 //基于字符串创建新字符串的方法 substring(start,end) //提取字符串从 start 下标开始到 end 结束之间的字符 返回一个新的字符串,是从 start 处到 end-1 处的所有字符, 不包括 end 处的字符 //start/end不能为负数 会把负值参数转为0 var str = 'abcd'; str.substring(0) //abcd str.substring(0,3) //abc str.substring(-1,-2) //'' substr(start,length) //提取字符串中从 start 下标开始的指定数目 length 的字符 返回一个新的字符串,包含 start 处开始的 length 个字符 //参数为负数时 第一个参数为 字符串长度加负值参数 第二个参数被转为0 var str = 'abcd'; str.substr(0) //abcd str.substr(0,3) //abc str.substr(-2,-1) //'' slice(start,end) //提取字符串从 start 下标开始到 end 结束之间的字符 返回一个新的字符串,是从 start 处到 end-1 处的所有字符, 不包括 end 处的字符 //参数为负数时 两个参数都为 字符串长度加负值参数 var str = 'abcd'; str.slice(0) //abcd str.slice(0,3) //abc str.slice(-2,-1) = str.slice(2,3) //c //字符串位置方法 indexOf(index) //返回给定子字符串在字符串中首次出现的位置 如果要检索的字符串值没有出现,则该方法返回-1 var str = 'abc'; str.indexOf('c') //2 lastIndexOf(index) //与indexOf相反 从字符串末尾开始向前检索 //字符串大小写转换方法 toLowerCase() //把字符串转换为小写 toUpperCase() //把字符串转换为大写 var str = 'aBc'; str.toLowerCase() //'abc' str.toUpperCase() //'ABC' //字符串模式匹配方法 match() //接收一个参数 一个正则表达式或者一个RegExp对象 var str = 'cat, bat, sat, fat', pattern = /.at/; var arr1 = str.match(pattern); console.log(arr1) // ["cat", index: 0, input: "cat, bat, sat, fat"] //相当于 var arr2 = pattern.exec(str) console.log(arr2) // ["cat", index: 0, input: "cat, bat, sat, fat"] search() //接收一个参数 一个字符串或者一个RegExp对象指定正则表达式 返回字符串中第一个匹配项的索引 没有返回-1 var str = 'cat, bat, sat, fat'; var index = str.search(/at/); console.log( index ) //1 replace() //替换子字符串操作 接收两个参数 第一个参数为一个字符串或者RegExp对象 第二个参数为一个字符串或者一个函数 var str = 'cat, bat, sat, fat'; var str2 = str.replace('at','AT'); console.log(str2) //cAT, bat, sat, fat var str3 = str.replace(/at/g,'AT'); console.log(str3) //cAT, bAT, sAT, fAT var str4 = str.replace(/(.at)/g,'AT($1)') console.log(str4) //AT(cat), AT(bat), AT(sat), AT(fat) function htmlEscape(str){ return str.replace(/[<>"&]/g, function(match, pos, originalText){ switch(match){ case "<": return "<"; case ">": return ">"; case "&": return "&"; case """: return """; } }); } split() //基于指定的分隔符把一个字符串分割成多个子字符串,并返回一个由这些子字符串组成的数组 var str = 'a-b-c'; str.split('-') //[a,b,c]
ECMAScript 5新增了 trim() 方法,这个方法删除字符串首尾的空格(支持的浏览器 IE9+ / Firefox 3.5+ / Safari 5+ Opera 10.5+ / Chrome)
可以这样实现:
if(!String.prototype.trim){ String.prototype.trim = function(){ return this.replace(/^s+|s+$/g,''); } }
单体内置对象
Global对象 Math对象
Global对象方法:
isNaN() 检查其参数是否是非数字值 不是数字值返回true
isFinite(x) 检查其参数是否是无穷大 如果 x 是有限数字(或可转换为有限数字),那么返回 true。否则,如果 x 是 NaN(非数字),或者是正、负无穷大的数,则返回 false
parseFloat() 解析一个字符串,并返回一个浮点数。 指定字符串中的首个字符是否是数字。如果是,则对字符串进行解析,直到到达数字的末端为止,然后以数字返回该数字; 如果参数字符串的第一个字符不能被解析成为数字,则 parseFloat 返回 NaN
parseInt() 函数可解析一个字符串,并返回一个整数
encodeURI() 函数可把字符串作为 URI 进行编码。该方法的目的是对 URI 进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI() 函数是不会进行转义的:;/?:@&=+$,#。如果 URI 组件中含有分隔符,比如 ? 和 #,则应当使用 encodeURIComponent() 方法分别对各组件进行编码
encodeURIComponent() 函数可把字符串作为 URI 组件进行编码
decodeURI() 函数可对 encodeURI() 函数编码过的 URI 进行解码
decodeURIComponent() 函数可对 encodeURIComponent() 函数编码的 URI 进行解码
eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码
Math对象方法:
Math.max() Math.min() 确定一组值中最大值 最小值 这两个方法接收任意多个参数
Math.ceil() 向上舍入为最接近的整数
Math.floor() 向下舍入为最接近的整数
Math.round() 标准四舍五入为最接近的整数
Math.random() 返回0-1之间的一个随机数 不包括0和1
值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值) 如 1-10 之间的值 包括1 10, 10个值:Math.floor(Math.random()*10 + 1) 如 2-9 之间的值 包括2 9, 8个值:Math.floor(Math.random()*8 + 2) function random(min, max){ return Math.floor(Math.random() * (max-min+1) + min); }
到这里看了前面5章。第1章中介绍什么是JavaScript, ECMAScript(核心)、文档对象模型(DOM)、浏览器对象模型(BOM)。第2章介绍怎样在HTML页面中使用JavaScript。第3章介绍JavaScript的基本概念:语法、关键字和保留字、变量、数据类型、操作符、语句、函数和参数。第4章中介绍变量、作用域和内存问题等。第5章中介绍数组、字符串、日期、正则表达式等,并介绍了各种类型一些方法和属性。其中还有许多细节,需要花更多的时间去理解。前面5章算是javascript语言的基础,需要多多去理解、实践。