变量
变量对象(缩写为VO)
一个与执行上下文相关的特殊对象,它存储着在上下文中声明的以下内容:
- 变量 (var, 变量声明);
- 函数声明 (FunctionDeclaration, 缩写为FD);
- 函数的形参
1 | var x=30; |
数据类型
undefined
使用var声明变量但未初始化:
1 | var a; |
null
逻辑上来看相当于空对象指针。
1 | var a = null; |
boolean
该类型只有两个字面值:true/false。
可以通过转型函数Boolean()将其他类型的值转换为boolean类型。其中转为false的值如下:
- String : ‘’(空字符串)
- Number : 0和NaN
- Object : null
- Undefined : undefined
Number
- 数值范围
在ECMAScript中超出了最小值Number.MIN_VALUE或者最大值Number.MAX_VALUE会被转换为Infinity(正无穷),如果是负数就是-Infinity(负无穷)。
可以通过isFinite()判断数值是否有穷。
2. NaN
非数值,表示本来要返回数值的操作数未返回数值的情况。NaN进行任何操作结果都是NaN;NaN和任何值都不相等,包括NaN本身。使用isNaN判断是否是非数值。
1 | //测试isNaN() |
- 数值转化
非数值转换为数值:
Number()
1
2
3
4Number('blue'); //NaN
Number(''); //0
Number('00011'); //11
Number(true); // 1parseInt()
1
2
3
4
5
6
7
8parseInt('1234blue'); //1234
parseInt(''); //NaN
parseInt('0xA'); //十六进制的10
parseInt(22.5); //22
parseInt('070'); //八进制的56
parseInt('0xAF',16); //175(十六进制)
parseInt('AF',16); //175(十六进制)
parseInt('AF'); //NaNparseFloat()
1
2
3
4parseFloat('1234blue'); //1234
parseFloat(22.34.5); //22.34
parseFloat(3.125e7); //31250000
parseFloat('0xA'); //0
String
转化为字符串:
toString()
ps: null和undefined没有这个方法。
默认不传参以十进制输出。也可以传参输出二进制,八进制,十六进制等。转型函数String()
能够将任何类型的值转化为字符串。
Object
数据和功能的集合。Object的每个实例都具有以下属性和方法:
- constructor : 保存着用于创建当前对象的函数
- hasOwnProperty(pro) : 检测属性是否存在,
({a:1}).hasOwnProperty('a') - isPrototypeOf(obj) : 检测传入的对象是否是当前对象的原型,
Object.prototype.isPrototypeOf({}) - propertyIsEnumerable(pro) : 检测属性是否可以用for-in枚举
- toLocaleString() : 返回对象的字符串表示
- toString() : 返回对象的字符串表示
- valueOf() : 返回对象的字符串、数值、布尔值表示
变量类型
- 基本类型值指的是简单的数据,按值访问,可以操作保存在变量中的实际值
- 引用类型值指的是保存在内存中的对象,按引用访问
复制引用类型值时,除了会复制变量中的值,而且两个变量引用的是同一对象,改变其中一个变量也会影响另一个变量。
数组方法
引用类型的值是引用类型的实例。
栈方法
- push():接收任意数量的参数,并逐个添加到数组末尾,并返回修改后的
数组长度 - pop():从数组末尾移除最后一项,减少数组长度并返回
移除的项
队列方法
- shift():移除数组第一项并
返回该项,数组长度减一 - unshift():在数组前端添加任意个数并返回
新数组长度
归并方法
- reduce():从数组的第一项开始,逐个遍历到最后
- reduceRight():从数组的最后一项开始,向前遍历到第一项
接收一个参数:在每一项调用的函数和作为归并基础的初始值
1 | var arr = [1,2,3,4]; |
Date类型
创建一个日期对象:
1 | var now = new Date(); |
不传递参数时,新建对象自动获得当前时间日期。
Date.parse(date):接收一个表日期的字符串参数,返回相应毫秒数或者NaN。
1
2
3var date1 = new Date(Date.parse("May 25,2004"));
//等价于
var date1 = new Date("May 25,2004");Date.UTC():返回毫秒数,参数是(年份,基于0的月份,日期,小时,分钟,秒),年份和月份是必须的。
1
2
3
4
5
6
7//GMT时间2000-1-1 00:00:00
var date2 = new Date(Date.UTC(2000,0));
//GMT时间2001-2-5 17:55:55
var date2 = new Date(Date.UTC(2001,1,5,17,55,55));
//等价于
var date2 = new Date(2001,1,5,17,55,55);Date.now():返回调用这个方法的时间毫秒数。
1
2
3var start = Date.now();
//等价于
var start = +new Date();
日期格式化方法
将日期格式化为字符串的方法:
- toDateString():显示日期
- toTimeString(): 显示时间
- toLocaleDateString(): 显示地区日期
- toLocaleTimeString(): 显示地区时间
- toUTCString(): 显示UTC日期
RegExp
正则式的元字符:( [ { \ ^ $ | ) ? * + . ] }
1 | var reg = /.at/g; //返回以at结尾的字符串 |
- . : 匹配除换行符之外的所有字符
- \d : 匹配数字,相当于[0-9]
- \w : 字母或数字或下划线或汉字等
- * : 表示前边的内容可以连续重复使用任意次数(包括0次)
- \s : 匹配任意空格符,包括换行符和tab
- \b : 表示单词的开头或结尾,也就是单词的分界处
- + :表示出现至少一次或多次
- \r :回车
- \t :制表符,tab
- ^ :匹配字符串的开始
- $ :匹配字符串结束
- ? :表示出现0次或一次
- {n} :重复n次
- {n,} :重复n次或更多次
- {n,m} :重复n到m次
- \W :匹配任意不是字母,数字,下划线,汉字的字符
- \S :匹配任意不是空白符的字符
- \D :匹配任意非数字的字符
- \B : 匹配不是单词开头或结束的位置
- [^xy] :匹配除了xy以外的任意字符
- [\s\S] :匹配任意字符,[^] 与 [\s\S] 等价
- (?=exp) :零宽度正预测先行断言,断言自身出现的位置的后面能匹配表达式exp
- (?!exp) :零宽度负预测先行断言,断言此位置的后面不能匹配表达式exp
- (?#comment) :注释
- .* :贪婪匹配,匹配尽可能多的字符
- *? :懒惰匹配,也就是匹配尽可能少的字符,重复任意次
- +? :重复1次或更多次,但尽可能少重复
- ?? :重复0次或1次,但尽可能少重复
- {n,m}? :重复n到m次,但尽可能少重复
1
var reg = \<(\w+)>\g; // 查找尖括号括起来的字母或数字(即HTML/XML标签)
toLocaleString()和toString()都发挥正则表达式的字面量,与创建表达式的方式无关。
1 | var reg = new RegExp("\\[bc\\]at","gi"); |
实例方法
exec(str): 返回包含第一个匹配性信息的数组或null。在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的补货组匹配的字符串。返回的数组有两个额外的属性:
index:匹配项在字符串的位置;
input:应用正则的字符串;1
2
3
4
5
6
7
8
9var text = "mon and dad and baby";
var pattern = /mon( and dad( and baby)?)?/gi;
var matches = pattern.exec(text);
console.log(matches.index); //0
console.log(matches.input); //"mon and dad and baby"
console.log(matches[0]); //"mon and dad and baby"
console.log(matches[1]); //"and dad and baby"
console.log(matches[2]); //"and baby"test(str): 测试是否匹配
compile(): 对正则表达式进行编译,被编译过的正则在使用的时候效率会更高,适合于对一个正则多次调用的情况
str.match(reg): 输出结果在不是全局匹配的情况下和exec方法的结果一致即一个数组并带有额外的属性,如果采用全局匹配,则不返回任何和其被匹配字符串相关的信息,只返回匹配的结果。
Function
函数是对象。定义函数:函数声明和函数表达式。
函数的内部属性
arguments: 保存函数参数,类数组对象。属性callee: 指针,指向拥有这个arguments的函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//阶乘函数
function factorial(num){
if(num < 2){
return 1;
}else{
return num * factorial(num-1);
}
}
//等价于(严格模式下不支持)
function factorial(num){
if(num < 2){
return 1;
}else{
return num * arguments.callee(num-1);
}
}this: 引用的是函数执行的环境对象,当全局调用时,指向的是window
1
2
3
4
5
6
7
8
9window.color = 'red';
var o = {color:'blue'};
function sayColor(){
console.log(this.color);
}
sayColor(); //red
o.sayColor = sayColor;
o.sayColor(); //bluecaller(ES5): 保存着调用当前函数的函数的引用
1
2
3
4
5
6
7
8
9function outer(){
inner();
}
funtion inner(){
console.log(inner.caller);
//指向outer()
//console.log(arguments.callee.caller);
}
outer();
函数的属性和方法
属性:
- length: 表示函数希望接收的参数个数
- prototype:保存所有的实例方法
方法:
以下两个方法都是在特定的作用域调用函数,实际上等于设置函数体内this对象的值。
apply()
1
2
3
4
5
6
7
8
9
10//作用1:传递参数
function sum(a,b){
return a + b;
}
function callSum(a,b){
return sum.apply(this,arguments);//this指向window
//相当于
// return sum.apply(this,[a,b]);
}
callSum(10,20); //30call()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19//作用1:传递参数
function sum(a,b){
return a + b;
}
function callSum(a,b){
return sum.call(this,a,b);
}
callSum(10,20); //30
//作用2:扩充函数运行的作用域
window.color = 'red';
var o = {color:'blue'};
function sayColor(){
console.log(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //bluebind(): 创建一个函数的实例,this值被绑定到传给bind()函数的值。
1
2
3
4
5
6
7
8window.color = 'red';
var o = {color:'blue'};
function sayColor(){
console.log(this.color);
}
var sayColorFun = sayColor.bind(o);
sayColorFun(); //blue
基本包装类型
用于操作基本类型值的特殊的引用类型:Boolean,Nymber,String
引用类型和基本包装类型的主要区别就是对象的生存周期。使用new创建的引用类型实例在执行流离开作用域之前一直保存在内存中。自动创建的基本包装类型的对象值存在于一行代码执行的瞬间,然后立即销毁。
对基本包装类型的实例调用typeof返回object,并且转化为布尔类型时都是true。
1 | //根据传入的值的类型返回相应的基本包装类型实例 |
使用new调用基本包装类型的构造函数和直接调用转型函数不一样。
1 | var value = "25"; |
Boolean类型
Number类型
- toFixed(): 按指定的小数位返回数值的字符串表示。
- toExponential(): 以指数表示法当数值的字符串形式。参数指定输出结果中的小数位数。
- toPrecision(): 返回最合适的数值格式
1
2
3
4var num = 99;
num.toPrecision(1); //"1e+2"
num.toPrecision(2); //"99"
num.toPrecision(3); //"99.0"
不建议实例化:
1 | var numobj = new Number(10); |
String类型
单体内置对象
Global对象
全局对象
Math对象
min()和max()
1
2
3var max = Math.max(1,55,22); //55
var arr = [1,3,5,7];
var min = Math.apply(Math,arr); //1舍入方法
- ceil(num):向上取整
- floor(num):向下取整
- round(num):四舍五入
- 其他方法
- random():返回0到1之间的随机数
- abs(num):绝对值
- exp(num):返回Math.E(自然对数的底数,常量e)的num次幂
- log(num):自然对数
- pow(num,power):返回num的power次幂
- sqrt(num):平方根
- acos(num):反余弦值
属性类型
数据属性:
要修改属性默认特性需使用Object.defineProperty()。接收三个参数,属性所在对象、属性名、描述符对象。
描述符对象的属性:configurable(能否delete或修改属性特性)、enumerable(for-in能否返回属性)、writable(能否修改属性值)、value(属性的数据值)
1 | var person = {}; |
PS:configurable设置为false表示不可配置之后,就不能再变回可配置了,此时修改除writable之外的特性都会报错。
访问器属性
包含getter()和setter()。访问器属性必须用Object.defineProperty()定义。
1 | var book = {_year:2004,edition:1}; |
定义多个属性和读取属性
1 | var book = {}; |
创建对象
为了解决构造函数和字面量创建对象的缺点:创建多个对象时代码重复
工厂模式
用函数来封装以特定接口创建对象的细节。缺点:无法识别对象
1 | function createPerson(name,age){ |
构造函数模式
与工厂模式的不同:没有显示的创建对象;直接将属性和方法赋予了this;没有return;函数名首字母大写;创建实例必须使用new操作符(构造函数与普通函数的调用方式不同);
1 | function Person(name,age){ |
缺点:每个方法都要在实例上重新创建一遍(不同实例的同名方法是不同的)
1 | console.log(person1.sayName == person2.sayName); //false |
原型模式
prototype属性是一个指针,指向原型对象,通过调用构造函数创建的对象实例的原型对象。原型对象的优点:所有的实例都共享了包含的属性和方法。将对象实例的信息都添加到原型对象中。
1 | function Person(){ |
for-in循环时返回的是所有对象能够访问的属性(包括原型中的属性)。如果要获取所有可枚举属性,可以使用Object.keys(),返回数组。如果要获取所有实例属性,不论是否可枚举,使用Object.getOwnPropertyNames()。
缺点:原型的共享性会导致实例的引用类型值相同
1 | function Person(){ |
组合使用构造函数模式和原型模式
构造模式用于实例属性,原型模式用于定义方法和共享的属性。可以用来定义引用类型的一种默认模式。(推荐)
1 | function Person(name,age){ |
动态原型模式
信息封装在构造函数中,通过构造函数初始化原型。不能使用字面量重写原型。
1 | function Person(name,age){ |
寄生构造函数模式
这个模式可以在特殊情况下用来为对象创建构造函数。不能依赖instanceof确定对象类型。
1 | function Person(name,age){//封装创建对象并返回新对象 |
稳妥构造函数模式
和寄生构造函数类似,不同点:新创建对象的实例方法不引用this,不使用new操作符调用构造函数。(在安全的环境中使用)
1 | function Person(name,age){ |
继承
原型链
原型链是实现继承的主要方法。在继承时不能使用字面量创建原型。原型链的基本模式:
1 | function Super(){ |
缺点:引用类型值会被所有实例共享;在创建子类型时不能给超类型的构造函数传递参数。
借用构造函数
在子类型构造函数内部调用超类型构造函数。
1 | function Super(){ |
子类型构造函数像超类型构造函数传递参数:
1 | function Super(name){ |
缺点:不支持函数复用;超类型的原型中定义的方法对子类型不可见;
组合继承
使用原型链实现对原型属性和方法的继承,使用借用构造函数实现对实例属性的继承。(推荐)
1 | function Super(name){ |
缺点:无论怎样都会调用两次超类型构造函数
原型式继承
借助原型基于已有对象创建新对象。可以用方法Object.create()实现。参数:用作新对象原型的对象、为新对象定义额外属性的对象。
1 | var person = { |
寄生式继承
和寄生构造函数类似。
寄生组合式继承
通过借用构造函数继承属性,通过原型链的混合形式来继承方法。
1 | function inheritPrototype(sub,super){ |
函数表达式
函数声明,函数表达式。函数表达式创建的函数是匿名函数。
递归
闭包
有权访问另一个函数作用域中的变量的函数。
作用域链是一个指向变量对象的指针列表,只引用但不包含变量对象。闭包保存的是包含函数的整个活动变量,所以闭包只能取得包含函数中任何变量是最后一个值。
闭包中的this对象:this对象指向函数的执行环境。匿名对象的执行环境具有全局性,所以this对象指向window。
1 | var name = 'window'; |
把外部作用域的this保存在闭包能访问到的变量中:
1 | var name = 'window'; |
模仿块级作用域和私有变量
1 | (function(){ |
任何在函数内部定义的变量都是私有变量。特权方法:有权访问私有变量和私有函数的方法。
创建特权方法:
- 在构造函数中定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14function MyObj(){
var val = 0;
function privateFun(){
return false;
}
//特权方法(闭包)
this.publicFun = function(){
val++;
return privateFun();
}
}
var obj = new MyObj();
console.log(obj.publicFun());
缺点:每个实例都会创建同样的方法
2. 静态私有变量:在私有作用域中定义私有变量
1 | (function(){ |
缺点:每个实例都共享了方法,但没有自己的私有变量
3. 模块模式:为单例创建私有变量和特权方法,单例是只有一个实例的对象
1 | //创建一个对象并对其初始化,并公开一些访问私有数据的方法 |
浏览器对象模型(BOM)
BOM的核心是window。
全局对象和window对象
全局变量是window对象的属性。全局变量不能通过delete删除,但直接在window上定义的属性可以删除。
1 | var age = 10; |
location对象
保存当前窗口的文档信息。
1 | //解析查询url |
使用location对象可以改变浏览器的位置。
1 | location.assign(url); |
navigator对象
保存浏览器信息。
检测插件
1 | //在ie中无效 |
其他对象
- screen对象:显示器信息
- history对象:历史记录
1
2
3
4
5
6
7
8
9history.go(-1); //后退一页
history.back();
history.go(1); //前进一页
history.forward();
history.go(2); //前进两页
history.go("baidu.com"); //跳到最近的baidu.com
客户端检测
能力检测
检测浏览器是否支持某功能。
1 | var hasNSPlugins = !!( navigator.plugins&& navigator.plugins.length); |
怪癖检测
针对浏览器的特殊行为进行检测。
用户代理检测
文档对象模型(DOM)
针对XML扩展后用于HTML的应用程序编程接口(API)。DOM把页面映射为一个多层节点结构,或者说它将网页中的HTML文档抽象为内存中的节点对象树(DOM Tree)。树中的每一个节点对象对应HTML文档中的一个元素。
Node类型
有12种节点类型。
1 | if(someNode.nodeType == 1){//元素节点 |
- 节点关系
每个节点都有childNodes属性,保存着NodeList对象(类数组对象,保存一组有序的节点)。
1 | var firstChild = someNode.childNodes[0]; |
- 操作节点
appendChild():向childNodes末尾添加节点,返回新增节点。如果节点已经存在,就把它移动到末尾。
1 | var node = someNode.appendChild(someNode.firstChild); |
insertBefore():向指定位置插入节点,返回新增节点。
1 | //插入最后一个子节点 |
replaceChild():替换节点。
1 | //替换第一个子节点 |
removeChild():移除节点。
1 | //移除第一个子节点 |
cloneNode():复制节点,接收一个布尔参数,表示是否深复制。深复制:复制节点及其子节点;浅复制:仅复制节点。
normalize():处理文本节点(删除空文本节点,合并相邻文本节点)
document类型
表示文档,表示html页面。nodeType值为9,nodeName为#document。
1 | var html = document.documentElement; |
- 查找元素
getElementById():返回第一次匹配的元素。在ie7中可能返回name特性的元素。
getElementByTagName():根据标签名查找元素,返回包含零或多个元素的NodeList。
1 | var imgs = document.getElementByTagName("img"); |
getElementByName():根据name特性返回所有元素
2. 特殊集合
document.anchors:所有带name特性的<a>元素。
document.forms:所有<form>。
document.images:所有<img>。
document.links:所有带href特性的<a>元素。
3. DOM一致性检测
1 | var hasXmlDom = document.implementation.hasFeature("XML","1.0"); |
- 文档写入
document.write():写入s输出流。
document.writeln():写入时加换行符。
document.open():打开输出流。
document.close():关闭输出流。
Element类型
nodeType值为1。可以用nodeName或者tagName获取元素标签名,在html中标签名以大写返回。
- HTML元素
特性:id,title,lang(语言),dir(方向),className
2. 操作特性
特性的名称不区分大小写。
getAttribute(attrname):获取某特性,返回字符串
setAttribute(attrname,attrvalue):设置特性
removeAttribute(attrname):移除特性
3. attributes属性
Element类型有attributes属性。包含元素所有的属性Attr节点,可以用nodeName获取特性的名称,nodeValue获取特性值。一般用于遍历元素的特性。
1 | var id = element.attributes.getNamedItem("id").nodeValue; |
- 创建元素
1
var div = document.createElement('div');


