第一章: JS简介
从当初简单的语言,变成了现在能够处理复杂计算和交互,拥有闭包、匿名函数,
甚至元编程等特性。
要想全面理解和掌握JS,关键在于弄清楚它的本质、历史和局限性
1.JS简史
客户端语言--- 为了解决拨号,表单验证缓慢的问题
ECMAScript的新脚本语言的标准。
1.2 JS实现
JS由三部分组成:核心(ECMAScript)、文档对象模型(DOM)、浏览器对象模型(BOM)
1.2.1 ECMAScript
ECMAScript与Web浏览器无关。ECMAScript这门语言并不包含输入和输出定义,它只是基础。
而Web浏览器是ECMAScript实现可能的宿主环境。宿主环境不仅提供基本的ECMAScript实现,
而且也会提供该语言的扩展--如DOM,提供了更多具体的功能,以便实现各种操作。
ECMAScript只规定了下面:
1.语法
2.类型
3.语句
4.关键字
5.保留子
6操作符
7对象
1.2.2 文档对象模型(DOM)
文档对象模型是针对XML但经过扩展用于HTML的应用程序编程接口(API)。DOM把整个页面映射为
一个多层节点结构。HTML或XML页面的中的每个组成部分都是某种类型的节点。
用户可以根据需求随意控制任何节点。
1.为什么要使用DOM
由于浏览器不兼容的问题,担心成为一种趋势,制定一种标准能够都兼容,减少代码量。
2.DOM级别
DOM1:DOM核心和DOM HTML。
DOM核心规定的是如何映射基于XML的文档结构,简化对文档结构的操作。
DOM HTMl在核心加一扩展,添加了对HTML的对象和方法。
DOM2:在原来DOM基础上扩充了鼠标和用户界面事件、范围、遍历。
DOM3:进一步扩展了DOM,引入了以统一方式加在和保存文档的方法。
1.2.3 浏览器对象模型(BOM)
只处理浏览器窗口和框架。也习惯把所有针对浏览器的JS扩展放上去,
扩展: 1.弹出新浏览器窗口
2.移动、缩放和关闭
3.提供浏览器详细信息
4.提供所加载页面的详细信息
5.提供分辨率信息
6.对cookie的支持
7.XMLHttpRequest 这样的自定义对象。
小结:
JS是一种专为网页交互而设计的脚本语言,由三个不同的部分组成:
1.ECMAScript, 提供核心语言功能。
2.文档对象模型:提供访问和操作网页内容的方法和接口
3.浏览器对象模型:提供与浏览器交互的方法和接口
第二章 在HTML中使用JS
如何让JS既能与HTML页面共存,又不影响那些页面在其他浏览器中的呈现效果。
最佳的办法是:添加同意的脚本支持。
2.1元素
六个属性: async:异步加载,只对外部脚本有效。
表示应该立即下载,但不应妨碍页面其他操作,如下载资源或等待加载其他脚本
charset: 表示通过src属性指定的代码的字符集。
defer: 表示脚本可以延迟到文档完全被解析和显示之后再执行。
src: 资源文件。外部脚本文件。
type: 内容类型。常用的 text/javascript
language :废弃
两种使用方式: 直接嵌入、外部引入。
直接嵌入:
如果是一个函数定义,解释器会解释到一个函数的定义,然后将该定义保存到自己的环境中。
在解释器对元素的内部所有代码求值完毕以前,其余内容不会被加载。
外部:
1.如果外部,同时在标签中加入嵌入代码,嵌入代码会被忽略。
2.只要不存在defer和async属性,它会按照顺序解析。
2.1.1 标签位置:
惯例,放在head中。
坏处:1.必须等head中的JS全部下载,才会开始呈现内容。
为了避免,会将JS放在body元素中的内容后面。
2.1.2 延迟脚本:defer :放在底部比较好。
含义:脚本会被延迟到整个页面都解析完毕后运行。(也就是遇到再执行。)
一般但不保证一定,会先于DOMContentLoaded事件执行。
defer只支持外部脚本,因此嵌入脚本有 defer,会忽略。
2.1.3 异步脚本:async
异步加载一定会在页面的load事件前执行。 但可能会在DOMContentLoaded事件触发之前或之后进行。
2.1.4 在XHTML中的用法
可扩展超文本标记语言(XHMTL),是将HTML作为XML的应用重新定义的一个标准。
XHTML的语法规则是非常严格的。
2.2 嵌入代码与外部文件
比较强调使用外部文件
可维护性
可缓存
适应未来
2.3 文档模式
现在使用的是文档类型(doctype)实现的。
一般使用标准模式。
文档模式分为两种:混杂模式和标准模式。 如果不写上面的话,默认开启标准模式。
2.4
如何解决浏览器不支持JS时,如何让页面平稳退化:
情况 :1。不支持脚本
2.支持脚本,但脚本被禁用。
2.5 小结
第三章 基本概念
3.1 语法
3.1.1 区分大小写
变量、函数名、操作符都区分大小写。
3.1.2 标识符
其实就是变量名,命名规则
3.1.4 严格模式
严格模式是为JS定义了一种不同的解析与执行模型。对待一些不确定的行为,将会进行处理,对不安全的
操作会抛出错误。
方法: 代码顶部: "use strict"; 或者指定一个函数
function doSomething(){
“use strict”;
}
这是一个编译指示,切换到严格模式。 严格模式下,JS执行结果会有很大不同
3.1.5 语句
以;结尾。
3.2 关键字和保留子。
3.3 变量
变量时松散类型,即弱关系类型。指的是可以保存任何类型的数据。换句话说,每个变量仅仅是一个用于保存
值的占位符而已。
var message: 未经初始化的变量,会保存一个特殊的值undefined。
注意变量的作用域。
3.4 数据类型
五种简单数据类型:Undefined|Null|Boolean|Number和String.
一种复杂数据类型:Object. 本质上是由一组无序的名值对组成的。 不支持创建自定义类型的极致。
3.4.1 typeof 操作符
检测给定变量的数据类型。
使用方法: 他是一个操作符而不是函数,因此例子中的圆括号尽管可以使用,但不是必需的。
var message="some string";
alert(typeof message); //返回“string”
alert(typeof (message)); //返回...
alert(typeof 95); //返回number
alert(typeof null); //返回object. 因为把他看作是一个空的对象引用。
3.4.2 Undefined类型
var message;
alert(message); //"undefined"
alert(age); //产生错误
上面的例子,包含undefined值的变量和尚未定义的变量还是不一样的。
对于尚未声明过的变量,只能执行一项操作,即使用typeof操作符检测其数据类型。
未初始化、未声明的变量使用typeof操作符同样也会返回undefined值。
var message;
alert(typeof message); //'undefined'
alert(typeof age); //'undefined'
明智的做法:显式地初始化变量。当使用typeof时,这样就能检测出变量是没有被声明,而不是尚未初始化。
3.4.3 Null 类型
Null类型是第二个只有一个值的数据类型,这个特殊的值是null。从逻辑上看,null值表示一个空对象指针。
var car=null;
alert(typeof car);
如果定义的变量准备用来保存对象,那么最好初始化为null. 这样检测值就能知道是否已经保存了一个对象的引用
if(car!=null)
实际上,undefined值是派生自null值的,因此:
alert(null ==undefined; //true
如果是对象,记得声明成null。可以区分null和undefined.
3.4.4 Boolean类型
true和false,这两个值与数字值不是一回事。true不一定等于1,false不一定等于0。
所有类型的值都有与这两个Boolean值等价的值。可使用Boolean();
Boolean() 会自动转换在if语句中。
true false
String 任何非空 空字符
Number 任何非零数字值 0或NaN
Object 任何对象 null
Undefined n/s undefined
eg: var message="hello";
if(message) //这里使用了转化 Boolean()
3.4.5 Number类型
表示整数和浮点数。
八进制: 07;
十六进制 0xAF;
注意永远不要测试某个特定的浮点数值。
if(a+b==0.3) //不要这样做,因为会有误差。 可能 0.1+0.2的结果是=0。30000000000004
2.数值范围
Number.MIN_VALUE : 5e-324
Number.MAX_VALUE:1.7976931348623157e+308
如果超出范围会转化成特殊的Infinity值。
确定有穷:isFinite()函数。
3.NaN(not a number)
非数值是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况。(这样不会抛错。)
特点:
1.任何涉及NaN的操作都会返回NaN。
2.NaN与任何值都不相等,包括NaN本身。
alert(NaN ==NaN) //false
针对这个定义了,isNaN();(是否为数值).他会尝试这个值能否转化为数值。
alert(isNaN(NaN)); //true
alert(isNaN(10)); //false (10是一个数值)
alert(isNaN("blue")) //true (不能转化)
4.数值转换
三个函数,把非数值转化为 数值: Number()\parseInt()和parseFloat()。
Number():有点复杂。
parseInt():更常用: 从第一个非空格字符开始,如果不是数字,返回NaN.可指定进制。
parseFloat():和parseInt()类似,
3.4.6 String 类型
单双引号都可以是字符串。
1.字符字面量
String数据类型包含一些特殊的字符字面量,也叫转义序列,用于表示非打印字符。
2.字符串的特点:
ECMAScript中的字符串是不可变的。一旦创建,他们的值不可改变。如果改变值,先销毁,后用另一个包含
新值的字符串填充该变量。
3.转换为字符串
toString()方法:若使用参数,代表进制。 不适用于null\undefined
eg: var age=11;
var ageString=age.toString(); // “11” 无参数。
var ageString=age.toString(2); //“01011” 二进制
String():可使用不知道要转换的值是不是null或undefined的情况下。
var value1=null;
var value2=undefined;
alert(String(value1)); //"null"
alert(String(value2)); //"undefined"
3.4.7 Object类型
var o=new Object();
其中,在ECMAScript中,Object类型是所有它的实例的基础。
Object的每个实例都有的属性和方法:
1.Constructor
2.hasOwnProperty("name")
3.isPrototypeOf(object)。
4.propertyIsEnumerble("name"):检查给定属性能否使用for-in来枚举。
5.toLocaleString()
6.toString()
7.valueOf()
3.5 操作符
ECMAScript操作符的与众不同之处在于,他们能够适用于很多值,字符串、数字值、布尔值,甚至对象。
在使用对象时,通常会先调用对象的valueOf()和toString()
注意:一元加和减操作符
在对非数值应用一元加操作符时,该操作符会想Number()转型函数一样对这个值执行准换。
var s1="01";
var s3="z";
s1=+s1; //变为数值1
s3=+s3; //变为NaN.
3.5.4 乘性操作符
与JAVA不同的是,操作数为非数值的情况下会执行自动的类型转换。
3.5.7 相等操作符
==、!=,注意:
要比较相等性之前,不能将null和undefined转换成其他任何值。
null == 0 false
undefined ==0 false
==\ === 不一样,两个==转换类型再比较,而===直接进行比较。
“55” == 55; //true,因为转换后想等
"55" ===55; //false,因为不同的数据类型不相等
3.5.8 条件操作符
b= a?c:d;
3.5.9 赋值操作符
注意: x=y+7 等价于x=x(y+7)
3.5.10逗号操作符
用于赋值时,逗号操作符总会返回表达式中的最后一项。
var num=(5,8,9,0); //num=0
3.6 语句
3.6.4 for语句
if语句: 注意: ECMAScript中不存在块级作用域。因此在循环内部定义的变量也可以在外部访问到。
var count=10;
for(var i=0;i
}
alert(i);
3.6.5 for-in语句:建议使用前,先确认该对象是不是null或undefined.
for-in语句是一种精准的迭代语句,可以用来枚举对象的属性。
for(var propName in window){
document.write(propName);
}
ECMAScript对象的属性没有顺序。因此,for-in输出的顺序是不可预测的。
3.7 break和continue语句
独特的使用办法:label语句,可以返回到代码中特定的位置。
var num=0;
outermost:
for(var i=0;i<10;i++){
for(var j=0;j<10;j++){
if(i==5 && j==5){
break outermost;
}
num++;
}
}
alert(num); //55
添加了标签以后,会导致break语句不仅会退出内部的for语句,也会退出外部的for语句。为此,当变量i和
j都等于5时。num等于55.
var num=0;
outermost:
for(var i=0;i<10;i++){
for(var j=0;j<10;j++){
if(i==5 && j==5)
continue outermost;
}
num++;
}
alert(num); //95
在这种情况下,continue会强制继续执行循环————退出内部循环,执行外部循环。
谨慎使用label语句,如果使用,一定要使用描述性的标签,同时不要嵌套过多的循环。
3.6.8 with语句 : 大量使用会导致性能下降,调试困难。大程序不建议使用
with语句的作用是将代码的作用域设置到一个特定的对象中:
with(expression) statement;
举例,假如多次使用一个对象,可以这样用,用法:
原来:
var qs=location.search.substring(1);
var hostName=location.hostname;
更改后:
with(location){
var qs=search.substring(1);
var hostName=hostname;
}
3.6.9 switch 语句
JS中的switch语句比其他语言强大很多。switch的表达式可以传递任何数据类型。
switch("hello world"){
case "hello"+" world":
alert("1");
break;
case "goodbye":
alert("12");
break;
}
也可以当做if语句来使用。
var num=25;
swtich(true){
case num<0:
alert("1");
break;
case nume>=0 &&num<=10:
alert("12");
break;
}
3.7 函数
在使用return;时,将会返回一个undefined值。这种用法一般用在需要提前停止函数执行而又不需要返回值的情况下。
3.7.1 理解参数
ECMAScript函数的参数与大多数语言中函数的参数不同。它可以传递很多个参数,即使定义只定义了几个。原因是ECMAScript中的参数在内部是用一个数组(arguments)来表示。其实arguments对象只是与数组类似,因为可以使用方括号语法访问他的每一个元素。
函数一个重要的特点:
1.命名的参数只提供便利,但不是必须的。
2.此外,arguments对象可以与命名参数一起使用。
3.arguments的值永远与对应命名参数的值保持同步:当修改arguments的值,命名参数值也会改变。但是命名参数改变,
arguments的值不会改变。
4.当你只传入一个参数时,那么修改arguments[1],并不会影响第二个命名参数。因为arguments对象长度由传入参数决定
而不是由定义函数时的命名参数的个数决定的。
5.没有传递值的命名参数自动被赋予undefined。
ECMAScript中的所有参数传递的都是值,不可能通过引用传递参数。
3.7.2 没有重载
如果有两个同名函数,则该名字只属于后定义的函数。
第四章 变量、作用域和内存问题
4.1 基本类型和引用类型的值
基本类型值指的是简单的数据段。
引用类型值指的是那些可能由多个值构成的对象。
4.1.1 动态的属性
只能为引用类型的值动态添加属性,普通的数据类型不能添加属性。
var name="NAC";
name.age=27; //错误的
4.1.2 复制变量值
基本数据类型是复制一个副本,对象是引用,复制的是一个指针,指向同一个对象。
4.1.3 传递参数
值传递:复制一个副本。
指针传递:是特殊的值传递,它可以改变指向对象的值,也可以改变指向的对象。
引用传递:可以改变指向对象的值,但是不能改变指向的对象,他是对象的别名。
4.1.4 检测类型
使用typeof
instanceof
4.2 执行环境及作用域
执行环境定义了变量或函数有权访问的其他数据,决定它们各自的行为。 每个执行环境都有一个与之关联的变量对象,环境
中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台
使用它。
全局执行环境是最外围的一个执行环境。不同的宿主环境,表示执行环境的对象也不一样。在web中,全局执行环境被认为
window对象,所有的全局变量和函数都作为window对象的属性和方法创建的。
当代码在一个环境中执行时,会创建变量对象的一个作用链。作用链的用途,是保证对执行环境有权访问的所有变量和函数的
有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象,即arguments对象。一级一级的包含。
标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程使用从前段开始,然后逐渐向后回溯。
此外,在局部作用域中定义的变量可以在局部环境中与全局变量互换使用。
内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中任何变量和函数。
4.2.1 延长作用域链
有一些办法可以延长作用链,会在作用链的前端临时增加一个变量对象,使用完后移除。
两种情况:
1.try-catch的catch块:会创建一个新的变量对象,其中包含错误对象的声明。
2.with语句: 会将制定的对象添加到作用域链中。
function buildUrl(){
var qs="?debug=true";
with(location){
var url=href+qs;
}
return url;
}
在这个函数中,首先with函数接受了location对象,把它放在了作用链的前端,并且引用它的属性href(location.
href)。使用了with后,内部url,可以被外部执行环境接受。
4.2.2 没有块级作用域
if(true){
var color="blue";
}
alert(color); //"blue"
在c语言中,color在if中执行完后,会销毁。后面会报错。而在JS中,if声明的变量会添加到当前的执行环境。
再举例,
for(var i=0;i<10;i++){
}
alert(i); //10
对于有块级作用域的语言,for所定义的变量只存在循环中。而在JS中,执行完for,依然存在。
1.声明变量
使用var 声明的变量会自动被添加到最接近的环境中。
2.查询标识符
从作用链前端开始查询,查询到停止。
4.3 垃圾收集
JS具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。
垃圾收集器会按照固定的时间间隔,周期性地执行这一操作:找出不再继续使用的变量,然后释放其占用的内存。
工作机制:垃圾收集器必须追踪哪个变量游泳哪个变量没用,对于不再有用的变量搭上标记,以备将来回收,有两种
策略。
4.3.1 标记清除
垃圾收集器在运行的时候会给储存在内存中的所有变量都加上标记。然后,他会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将视为准备删除的变量。
4.3.2 引用计数
另一种不太常见的垃圾手机策略叫做引用计数。含义是跟踪记录每个值被引用的次数。
当一个值被变量引用时,则该值的引用次数加1。当变量的值被其他值所取代,引用数减1.
当变为0时,说明无法再访问这个值,当垃圾收集器下次运行时,他会释放引用为0的内存。
循环引用:会导致无法销毁内存,所以不再采用。
BOM和DOM中的对象就是使用C++以COM对象的形式实现的,c++采用引用计数,当IE中涉及COM对象,就会存在循环引用的问题。
后来改版后,DOM和BOM都转换成了JS对象,避免了常见的内存泄漏。
4.3.3 性能问题
4.3.4 管理内存
分配给Web浏览器的可用内存数量通常比程序的少。目的是处于安全方面的考虑,目的防止运行的网页耗尽呢堃导致系统崩溃。内存限制不仅影响给变量分配内存,同时还影响一个线程中同时执行的语句数量。
因此,优化内存最佳的方式,就是为执行中的代码只保存必要数据,一旦数据不用,设为null,来释放引用---解除引用。 这适用于大多数全局变量和全局对象的属性。
4.4 小结:
1.基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中。
2.饮用类型的值是对象,保存在堆内存中。
第五章 引用类型
在JS中,引用类型是一种数据结构,用于将数据和功能组织在一起。常被称为类。但它不具备传统的面相对象语言所支持的类和接口等基本结构。
5.1 Object 类型
到目前为止,我们看到的大多数引用类型值都是object类型的实例。
var person=new Object();
person.name="nicho";
person.age=29;
另一种是使用对象字面量表示法,简写形式,目的在于简化创建包含大量属性的对象。
var person={
name:"nico",
age:29,
5:true //5回自动转换成字符串
};
可以为空:
var person={}; //花括号代表对象。()代表数组。
可使用对象字面量向函数传递大量可选参数的首选方式。
function displayInfo(args){
var output="";
if(typeof args.name=="string"){
output+=args.name;
}
}
displayInfo({
name:"nico",
age:29
});
访问属性: person["name"] person.name;
第一种方括号语法的优势是通过变量名访问、易出错的属性名访问:
var pro="name";
person[pro];
person["first name"] //有空格
5.2 Array类型
在JS中,数组每一项能够装任何数据类型。如:第一个装数组,第二个装对象。
并且自动增加数组大小。
var colors=new Array();
var colors=new Array(20);
var colors=new Array("hello","wolrd",50);
var colors=Array();
//数组字面量法。
var colors=[]; //方括号是数组,花括号是对象
var colors=[“world”,123];
数组的索引值很有意思。如果超出现有lengh,会自动增加到该索引值加1.
lengh 的值是可以改变的,增加这个值,改变数组大小。(增大或减小)
var colors=['red','blue'];
colors[colors.length]='black'; //在位置2添加,
colors[colors.length]='brown‘; //在位置3添加。
5.2.1 检测数组
if(value instanceof Array){
}
但是instanceof有问题的是,如果网页有多个框架,两个框架间传递值,可能Array构造函数不同。
更好的办法是: Array.isArray();
if(Array.isArray(value)) //php中是 is_array(value);
5.2.2 转换方法
var colors=['red','blue'];
alert(colors.toString()); //red,blue 这个方法以逗号分隔字符串。
alert(colors.valueOf()); //red,blue 返回数组,后调用toString
alert(colors) //red,blue 因为调用alert,会后台调用toString
alert(colors.join(',')) //red,blue
alert(colors.join('||')) //red||blue
5.2.3 栈方法
jS提供了让数组类似于栈的行为。 后进先出。 push\pop
var colors=new Array();
var count=colors.push("red","black"); //返回数组长度
alert(count); //2
count=colors.push("blk");
alert(count); //3
var item=colors.pop();
alert(item); //blk
alert(colors.length); //2
5.2.4 队列方法
先进先出 push \shift
var colors=new Array();
var count=colors.push("red","black"); //返回数组长度
alert(count); //2
count=colors.push("blk");
alert(count); //3
var item=colors.shift();
alert(item); //"red"
alert(colors.length); //2
unshift():它能在数组前端添加任意个项并返回新数组的长度
pop():从数组后端取出数据。
这模拟了反向队列。
var colors=new Array();
var count=colors.push("red","black");
alert(count); //2
count=colors.unshift("green"); green red black
alert(count); //3
var item=colors.pop();
alert(item); //"black"
alert(colors.length); //2
5.2.5 重排序方法:
reverse(): 反转数组项的顺序
sort():默认会为每个数组项调用toString()方法,之后对字符串进行比较。
var values=[0,1,5,10,15];
values.sort();
alert(values); //0,1,10,15,5
sort()可以接受一个比较函数:
function compare()
sort(compare); //和java中的排序树类似。
5.2.6 操作方法
concat() 无参,只是复制副本,返回新数组
有参,复制,若第二个参数为数组,每一项添加到副本中,若不是,简单添加。
slice() 它能够基于当前数组中的一个或多个项创建一个新数组。
返回从初始位置到结束位置之间的项。
splice() 主要用途向数组的中部插入项
1.删除 splice(index,length) splice(0,2)
2.插入多个项 splice(index,length,value1,value2...) splice(2,0,value,value2)
3.替换 splice(2,1,value,value2)
返回一个数组,该数组中包含从原始数组中删除的项
var colors=["red","green","blue"];
var remove=colors.splice(0,1);
alert(colors); //greem blue
alert(removed); //red
var remove=colors.splice(1,0,"yellow","orange");
alert(colors); //green yello orange blue
alert(removed); //空数组
var remove=colors.splice(1,1,"red","purple");
alert(colors); //green red purple orange blue
alert(removed); //yellow
5.27 位置方法
indexOf(searchString)\lastIndexOf(searchString).
要查找的项在数组中的的位置。
都是严格查找,使用===.
var numbers=[1,2,3,4,5,4,3,2,1];
alert(numbers.indexOf(4)); //3
alert(number.lastIndexOf(4)); //5
alert(numbers.indexOf(4,4)); //5, 从4开始往后查找。
alert(number.lastIndexOf(4,4)); //3 从位置4开始从后往前查。
var person={name:"nice"};
var people=[{name:"nice"}];
var morePeople=[person];
alert(people.indexOf(person)); //-1 person和people不是一个对象
alert(morePeople.indexOf(person)); //0
5.2.8 迭代方法
5个方法:每个方法都接受两个参数:要在每一项上运行的函数和运行该函数的作用域对象——影响this的值。
every(): 如果该函数每一项都返回true,则返回true
filter(): 返回true的项组成的数组
forEach(): 无返回值
map() 返回每次函数调用的结果组成的数组。
some(): 如果该函数的任一项返回true,则返回true。
every()和some()比较:
var numbers=[1,2,3,4,5,4,3,2,1];
var everyResult=numbers.every(function(item,index,array){
return (item>2);
});
alert(everyResult); //false
var someResult=numbers.some(function(item,index,array){
return (item>2);
});
alert(someResult); //true
filter():过滤函数,通过函数,筛选出符合条件的项。
var numbers=[1,2,3,4,5,4,3,2,1];
var filterResult=numbers.filter(function(item,index,array){
return (item>2);
});
alert(filterResult); //[3,4,5,4,3]
map():返回函数运行的结果
var numbers=[1,2,3,4,5,4,3,2,1];
var mapResult=numbers.map(function(item,index,array){
return (item*2);
});
alert(filterResult); //[2,4,6,8,10,8,6,4,2]
foreEach():和for循环没什么区别,
5.2.9 缩小方法
reduce()\reduceRight() 从头到尾|从尾到头
迭代所有的项,然后构件一个最终返回的值。
reduce(): 他的第一个参数是前一项的函数运行的结果
var values=[1,2,3,4,5];
var sum=values.reduce(function(prev,cur,index,array){
return prev+cur;
});
alert(sum); //15
5.3 Date类型
var now=new Date(); //自动获取当前日期和时间。
两个方法帮助创建日期对象:Date.parse()和Data.UTC(); 都是格林尼治时间
Date.parse():
var someDate=new Date(Date.parse("May 25,2004"));
等价于
var someDate=new Date("May 25,2004"); //自动调用Date.parse():
Data.UTC(): 使用不同的参数,其他没什么不同
//2000年1月1日0点0分
var y2k=new Date(Date.UTC(2000,0));
//2005.5.5,17:55:55
var allfiv= new Date(Date.UTC(2005,4,5,17,55,55)); //月、小时从0计数
本地时间:
var data=new Date(2000,5);
Date.now() 返回此时的毫秒数。
5.3.1 继承的方法
5.4 RegExp类型
var expression=/pattern/flags;
flag: g: 全局模式,即搜索全局,才返回,而不是查找到第一个就返回
i :不区分大小写
m:表示多行,即在一行文本末尾是否会继续查找下一行。
字面量形式:
var pattern1=/at/g; //查找包含at的所有
var pattern2=/[bc]at/i; //查找bat或cat的匹配项,不区分大小写
var pattern3=/.at/gi; //查找所有以at结尾的三个字符的组合,不区分大小写
//这里的.不是元字符,指的是任意一个字符。想要表示.,需要转义
所有的元字符必须转义。有:
([{ \ ^ $ | ) ? * + . ] }
如:
var pattern2=/\[bc\]at/i; 匹配第一个“[bc]at”,不区分大小写。
var pattern3=/\.at/gi; 查找所有以".at"的组合,不区分大小写
构造函数方式:
var pattern2=new RegExp("[bc]at","i");
//注意:这里传入的字符串,那么想要使用特殊的字符就需要双重转义,才能变成字面量的模式。
字面量模式 等价的字符串
/\[bc\]at/ “\\[bc\\]at”
\.at "\\.at"
\w\\hello\\123 "w\\\\hello\\\\123"
var re =null,i;
for(i=0;i<10;i++){
re=/cat/g;
re.test("catastrophe");
}
for(i=0;i<10;i++){
re=new RegExp("cat","g");
re.test("catastrophe");
}
第一种,实际上只产生了一个RegExp实例。由于实例属性不会重置,第二次会从索引值为3的字符开始的。
而使用构造函数,则每次会创建新的实例。
5.4.1 RegExp 实例属性
global: 是否设置g标志。
ignoreCase:是否设置i标志。
lastIndex: 表示开始搜索下一个匹配项的字符位置。
multiline:是否设置了m标志
source:正则表达式字符串表示,会返回字面量形式。
5.4.2 RegExp 实例方法
RegExp对象的主要方法是exec()。
使用全局变量g后,执行exec()函数会返回字符串中的下一个匹配项,直到末尾。
var text="cat,bat,sat,fat";
var pattern1=/.at/;
var match=pattern1.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern1.lastIndex); //0
var match=pattern1.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern1.lastIndex); //0
var pattern2=/.at/g;
var match=pattern2.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern2.lastIndex); //0
var match=pattern2.exec(text);
alert(matches.index); //5
alert(matches[0]); //bat
alert(pattern2.lastIndex); //8
text() :传一个参数,判断目标字符串与某个模式是否匹配。 true\false。
RegExp 继承的toString()方法都会返回正则表达式的字面量。
var pattern=new RegExp("\\[bc\\]at","gi");
alert(pattern.toString()); // /\[bc\]at/gi
5.4.3 RegExp 构造函数属性
通过RegExp可以查看到最近一次正则表达式操作。
var text="this has been a short summer.";
var pattern=/(.)hort/g;
if(pattern.test(text)){
alert(RegExp.input); //this has been a short summer
alert(RegExp.leftContext); //this has been a
alert(RegExp.rightContext); //summer.
alert(RegExp.lastMatch); //short
alert(RegExp.lastParen); //s
alert(RegExp.multiline); //false
}
5.5 Function 类型
函数实际上是对象,每个函数都是Function类型的实例。
function sum(num1,num2){}
等价于
var sum= function(num1,num2){};
在函数中,函数名仅仅是指向函数的指针,可以多次赋值。
5.5.1 没有重载
function addSomeNumber(num){
return num+100;
}
function addSomeNumber(num){
return num+200;
}
var result=addSomeNumber(100); //300
声明了同名函数,但其实后面的覆盖前面的。
5.5.2 函数声明与函数表达式
解析器会执行任何代码之前优先解析函数声明,而函数表达式只会在运行到此行才解析。
alert(sum(10,10));
function sum(){}
完全可以正常运行。
5.5.3 作为值的函数
可以将函数作为值传给函数。
function A(someFunction,someArgument){
return someFunction(someArgument);
}
也可以从一个函数中返回另一个函数。
function createFunction(propertyName){
return function(object1,object2){
var value1=object1[propertyName];
var value2=object1[propertyName];
if(value1>value2)
...
...
...
}
}
var data=[{name:"zhang",age:20},{name:"li",age:21}];
data.sort(createFunction("name"));
5.5.4 函数内部属性
在函数内部,有两个特殊的对象:arguments和this.
arguments的callee属性,指向拥有这个arguments对象的函数。如阶乘:
function sum(num){
if(num<=1){
return 1;
}else{
return num*arguments.callees(num-1);
}
}
this引用的是函数已执行的环境对象。(谁调用它,谁就是this.)
caller. 这个属性保存着调用当前函数的函数的引用。
function outer(){
inner();
}
function inner(){
alert(arguments.callee.caller);
}
outer();
它会显示outer的源代码。因为outer()调用了inter(),所以caller指向outer()..
5.5.5 函数属性和方法
函数是一个对象,既然是对象,就有属性和方法。属性: length和prototype
length 代表函数想要接受的参数的个数
function sayName(name){}
function sayHi(name1,nam2){}
alert(sayName.length) //1
alert(sayHi.length) //2
prototype 是保存引用类型所有实例方法的真正所在。即:toString()\valueOf()等方法都保存在prototype
名下。
每个对象都包含两个非继承而来的方法:apply()\call().
用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
apply()传入参数数组。
function sum(num1,num2){}
function callSum1(num1,num2){
return sum.apply(this,arguments);
}
function callSum1(num1,num2){
return sum.apply(this,[num1,num2]);
}
alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20
解释:this,指代的谁调用的它,这里是window对象,那么就变成了window.sum(10,10);
call要传入每个参数。
function sum(num1,num2){}
function callSum1(num1,num2){
return sum.call(this,[num1,num2]);
}
alert(callSum1(10,10)); //20
来个复杂的例子:
function baseClass()
{
this.showMsg = function()
{
alert("baseClass::showMsg");
}
}
function extendClass()
{
this.showMsg =function ()
{
alert("extendClass::showMsg");
}
}
如果我想使用extendClass的一个实例instance调用baseClass的对象方法showMsg怎么办?
extendClass.prototype = new baseClass();
var instance = new extendClass();
var baseinstance = new baseClass();
baseinstance.showMsg.call(instance);//显示baseClass::showMsg
这句话的意思就是:使用instance是调用者,调用他方法中和baseinstance.showMsg相同的方法。
apply()和call()的真正用武之地就是:扩充函数赖以运行的作用域。
window.color="red";
var o={color:"blue"};
function sayColor(){ alert(this.color);}
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //red
使用call和apply()方法最大的好处就是降低耦合, 我们不需要在对象中定义方法,当对象需要方法时,直接
让这个方法.call(对象)即可。
bind()方法:会闯一个函数的实例,其this值会被绑定到传给bind()函数的值。
window.color="red";
var o={color:"blue"};
function sayColor(){ alert(this.color);}
var objectSayColor=sayColor.bind(o);
objectSayColor(); //blue
5.6 基本包装类型
为了便于操作基本类型值,还提供了3个特殊的引用类型:Boolean\Number和String。
实际上,每当读取一个基本类型,后台会创建一个对应的基本包装类型的对象,能够调用一些方法操作这些数据。
eg: var s1="some text";
var s2=s1.substring(2);
基本包装类型和引用类型的区别主要在生存期。基本包装类型的生存期在执行完即销毁,而引用类型是一直保存在内存中的。
eg:
var s1="some text";
s1.color="red"; //当代码执行到这行时,创建实例对象,调用指定方法或属性,销毁。
alert(s.color); //undefined
5.6.1 Boolean类型: 不推荐使用。
Boolean类型的实例重写了valueOf()方法,返回基本类型值true和false.toString 返回字符串"true"和“false”
var falseObject=new Boolean(false);
var result=falseObject && true;
alert(result); //true
var falseValue=false;
result=falseValue && true;
alert(result); //false
第一个创建了一个对象,在布尔表达式中的所有对象都会被转换为true,因此结果为true。
alert(typeof falseObject); //object
alert(typeof falseValue) ; //Boolean
alert(falseObject instanceof Boolean); true
alert(falseValue instanceof Boolean ); false
typeof对基本类型返回Boolean. 对引用类型返回object.
由于Boolean对象是Boolean类型的实例,所以为true.
5.6.2 Number 类型
Number 类型重写了valueOf()\toString等方法。
var number =10;
alert(num.toString(2)); //"1010"
toString()方法加参数,可以转换进制。
还提供了一些用于将数值格式化为字符串的方法
toFixed():按照指定小数位返回数值的字符串表示。 适用于货币值。
var num=10;
alert(num.toFixed(2)); //"10.00"
如果本身包含的小数位比指定的还多。那么指定的最后一位舍入。
var num=10.005;
alert(num.toFixed(2));"10.01"
toExponential():返回以指数表示法表示的数值的字符串形式。
var num=10;
alert(num.toExponential(1)); //1.0e+1
toPrecision():会根据规则看哪个表示合适返回值。接受一个函数,即表示数值的所有
位数。
var num=99;
alert(num.toPrecision(1)); //1e+2
alert(num.toPrecision(2)); //"99"
alert(num.toPrecision(3)); //"99.0"
5.6.3 String 类型
1.字符方法
charAt()和charCodeAt()。一个返回给定位置的字符,一个返回给定位置的字符编码。
var stringValue="hello world".
alert(stringValue.chartAt(1));"e"
alert(stringValue.chartCodeAt(1));"101"
alert(stringValue[1]); //"e" 也可以使用这种方式访问。
2.字符串操作方法
concat():将一或多个字符串拼接起来。
var stringValue="hello ";
var result=stringValue.concat("world");
alert(result); //"hello world"
var result=stringValue.concat("world","!"); //可拼接多个。
alert(result); //"hello world !"
slice()\substr()和substring():三个都是字符切割函数。
var stringValue="hello world";
alert(stringValue.slice(3)); //"lo world"
alert(stringValue.substring(3)); //"lo world"
alert(stringValue.substr(3)); //"lo world"
alert(stringValue.slice(3,7)); //"lo w"
alert(stringValue.substring(3,7)); //"lo w"
alert(stringValue.substr(3,7)); //"lo worl"
//substr第二个参数是返回字符个数
3.字符串位置方法
indexOf()和lastIndexOf().这两个方法都是从一个字符串中搜索给定的子字符串,返回
返回位置,如果没有返回-1.一个从前,一个从后。
第一个参数是字符串,第二个参数是搜索起始位置。
4.trim()方法
创建一个字符串副本,删除前置及后缀的所有空格,然后返回结果。
5.字符串大小写转换方法
toLowerCase()、toUpperCase().
6.字符串的模式匹配方法
match():只接受一个参数,要么正则表达式,要么是一个RegExp对象。
var text="cat,bat,sat,fat";
var pattern=/.at/;
var matches=text.match(pattern);
alert(matches.index);
search():一个参数,字符串或RegExp对象指定的一个正则表达式。
replace()方法:
var text="cat,bat,sat,fat";
var result=text.replace("at","ond");
alert(result); //"crond"
字符序列
result=text.replace(/.at/g,"word ($1)");
alert(result); //word (cat),word (bat),word (sat),word (fat)
第二个参数为函数
text.replace(/[<>"&]/g,function(match,pos,originalText){
switch(match){
}
})
var colorText="red,blue,green,yellow";
var color1=colorText.split(",");
var color2=colorText.split(/{FNXX==XXFN}+/);
7.localeCompare()
比较:规则就是前面的减去后面的
var stringValue="yellow";
alert(stringValue.localeCompare("brick")); //1
alert(stringValue.localeCompare("zoo")); //-1
8.fromCharCode()方法
接受字符编码,转换成字符出阿妹。
5.7 单体内置对象
由ECMAScript实现提供的、不依赖于宿主环境的对象,这些对象在ECMAScript程序执行前就已经存在了。
如:Oject|Array|String|Global|Math
5.7.1 Global对象
不属于任何其他对象的属性和方法,最终都是它的属性和方法。
1.URI编码方法(URI:uniform Resource Identifiers 通用资源标识符,是更高层次的URL)
Global对象的encodeURI()和encodeURIComponent()方法可以对URI进行编码。
encodeURI:用于整个URI,只对空格编码.这个作用于URL跳转的时候。
和encodeURIComponent():对任何非标准字符进行编码。 使用它,传递一个长的url不会被截断。
2.eval()方法 ==>能够解释代码字符串。
像是一个完整的ECMAScirpt解析器。只接受一个参数,即要执行的ECMAScript字符串。
eval("alert('hi')"); === alert("hi");
当解析器发现代码中调用eval方法时,他会将传入的参数当作实际的ECMAScript语句来解析,然后把执行结果插入到原位置。通过eval()
执行的代码被认为是包含该次调用的执行环境的一部分,因此被执行的代码具有与该执行环境相同的作用链。
var msg="hello world";
eval("alert(msg)"); //hello world
eg2:
eval("fucntion sayHi(){alert("123")}");
sayHi();
3。Global 对象的属性
4.window 对象
浏览器将Global对象作为window对象的一部分加以实现。
可以取得Global对象的方法:
var global=function(){return this}();
5.7.2 Math对象
min()和max()方法
var max=Math.max(3,4,5,6123,15);
这种避免多余循环和if语句来检验最大值。
要找到数组中最大最小值,使用apply();
var values=[1,2,3,45,67,4,];
var max=Math.max.apply(Math,values); //这里关键是Math作为第一个参数,正确设置了this值。
舍入方法: Math.ceil()\Math.floor()\Math.round()
4.random()方法
var num=Math.floor(Math.random()*10+1);