您的位置:首页 > Web前端 > JavaScript

JavaScript高级程序设计笔记(3)

2015-08-15 17:21 573 查看

第五章 引用类型

创建Object 实例的方式有两种。

第一种是使用new 操作符后跟Object 构造函数,如下所示:

var person = new Object();

person.name = "Nicholas";

person.age = 29;


另一种方式是使用对象字面量表示法。对象字面量是对象定义的一种简写形式,目的在于简化创建包含大量属性的对象的过程。下面这个例子就使用了对象字面量语法定义了与前面那个例子中相同的person 对象:

var person = {

name : "Nicholas",

age : 29

};


对象字面量也是向函数传递大量可选参

数的首选方式,例如:

function displayInfo(args) {

var output = "";

if (typeof args.name == "string"){

output += "Name: " + args.name + "\n";

}

if (typeof args.age == "number") {

output += "Age: " + args.age + "\n";

}

alert(output);

}

displayInfo({

name: "Nicholas",

age: 29

});

displayInfo({

name: "Greg"

});


在这个例子中,函数displayInfo()接受一个名为args 的参数。这个参数可能带有一个名为name

或age 的属性,也可能这两个属性都有或者都没有。在这个函数内部,我们通过typeof 操作符来检测每个属性是否存在,然后再基于相应的属性来构建一条要显示的消息。然后,我们调用了两次这个函数,每次都使用一个对象字面量来指定不同的数据。这两次调用传递的参数虽然不同,但函数都能正常执行。

表示法

方括号语法

alert(person[“name”]); //”Nicholas”

主要优点是可以通过变量来访问属性,例如:

var propertyName = “name”;

alert(person[propertyName]); //”Nicholas”

如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括号表示法。例如:

person[“first name”] = “Nicholas”;

点表示法

除非必须使用变量来访问属性,否则我们建议使用点表示法

Array数组

与其他语言不同的是,ECMAScript 数组的每一项可以保存任何类型的数据。也就是说,可以用数组的第一个位置来保存字符串,用第二位置来保存数值,用第三个位置来保存对象,以此类推。而且,ECMAScript 数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据。

创建数组的基本方式有两种。

第一种是使用Array 构造函数,如下面的代码所示。

var colors = new Array();

如果预先知道数组要保存的项目数量,也可以给构造函数传递该数量,而该数量会自动变成length属性的值。例如,下面的代码将创建length 值为20 的数组。

var colors = new Array(20);

也可以向Array 构造函数传递数组中应该包含的项。以下代码创建了一个包含3 个字符串值的数组:
var colors = new Array("red", "blue", "green");

在使用Array 构造函数时也可以省略new 操作符。如下面的例子所示,省略new 操作符的

结果相同:

var colors = Array(3); // 创建一个包含3 项的数组

var names = Array("Greg"); // 创建一个包含1 项,即字符串"Greg"的数组


创建数组的第二种基本方式是使用数组字面量表示法。数组字面量由一对包含数组项的方括号表

示,多个数组项之间以逗号隔开,如下所示:

var colors = ["red", "blue", "green"]; // 创建一个包含3 个字符串的数组

var names = []; // 创建一个空数组

var values = [1,2,]; // 不要这样!这样会创建一个包含2 或3 项的数组

var options = [,,,,,]; // 不要这样!这样会创建一个包含5 或6 项的数组


数组的length 属性很有特点——它不是只读的。因此,通过设置这个属性,可以从数组的末尾移

除项或向数组中添加新项。请看下面的例子:

var colors = ["red", "blue", "green"]; // 创建一个包含3 个字符串的数组

colors.length = 2;

alert(colors[2]); //undefined


利用length 属性也可以方便地在数组末尾添加新项,如下所示:

var colors = ["red", "blue", "green"]; // 创建一个包含3 个字符串的数组

colors[colors.length] = "black"; //(在位置3)添加一种颜色

colors[colors.length] = "brown"; //(在位置4)再添加一种颜色


当把一个值放在超出当前数组大小的位置上时,数组就会重新计算其长度值,即长度值

等于最后一项的索引加1,如下面的例子所示

var colors = ["red", "blue", "green"]; // 创建一个包含3 个字符串的数组

colors[99] = "black"; // (在位置99)添加一种颜色

alert(colors.length); // 100


ECMAScript 5 新增了Array.isArray()方法。这个方法的目的是最终确定某

个值到底是不是数组,而不管它是在哪个全局执行环境中创建的。这个方法的用法如下。

if (Array.isArray(value)){

//对数组执行某些操作

}

数组- - ->字符串

数组继承的toLocaleString()、toString()和valueOf()方法,在默认情况下都会以逗号分隔的字

符串的形式返回数组项。而如果使用join()方法,则可以使用不同的分隔符来构建这个字符串。join()方

法只接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的字符串。请看下面的例子:

var colors = ["red", "green", "blue"];

alert(colors.join(",")); //red,green,blue

alert(colors.join("||")); //red||green||blue


数组的栈方法

var colors = new Array(); // 创建一个数组

var count = colors.push("red", "green"); // 推入两项

alert(count); //2

count = colors.push("black"); // 推入另一项

alert(count); //3

var item = colors.pop(); // 取得最后一项

alert(item); //"black"

alert(colors.length); //2


数组的队列方法

用push从末尾添加项,用shift从前端移除

var colors = new Array(); //创建一个数组

var count = colors.push("red", "green"); //推入两项

alert(count); //2

count = colors.push("black"); //推入另一项

alert(count); //3

var item = colors.shift(); //取得第一项

alert(item); //"red"

alert(colors.length); //2


用unshift从前端添加项,用pop从末尾移除

reverse方法:反转

var values = [1, 2, 3, 4, 5];

values.reverse();

alert(values); //5,4,3,2,1


sort()方法:排序,默认升序。即使数组中的每一项都是数值,sort()方法比较的也是字符串

var values = [0, 1, 5, 10, 15];

values.sort();

alert(values); //0,1,10,15,5


sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。

function compare(value1, value2) {

if (value1 < value2) {

return -1;

} else if (value1 > value2) {

return 1;

} else {

return 0;

}

}


升序

var values = [0, 1, 5, 10, 15];


values.sort(compare);

alert(values); //0,1,5,10,15


对于数值类型或者其valueOf()方法会返回数值类型的对象类型,可以使用一个更简单的比较函

数。这个函数只要用第二个值减第一个值即可。

function compare(value1, value2){

return value2 - value1;

}


concat方法:这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。

var colors = ["red", "green", "blue"];

var colors2 = colors.concat("yellow", ["black", "brown"]);

alert(colors); //red,green,blue

alert(colors2); //red,green,blue,yellow,black,brown


slice方法:可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。

var colors = ["red", "green", "blue", "yellow", "purple"];

var colors2 = colors.slice(1);

var colors3 = colors.slice(1,4);

alert(colors2); //green,blue,yellow,purple

alert(colors3); //green,blue,yellow


如果slice()方法的参数中有一个负数,则用数组长度加上该数来确定相应的位

置。例如,在一个包含5 项的数组上调用slice(-2,-1)与调用slice(3,4)得到的

结果相同。如果结束位置小于起始位置,则返回空数组。

splice方法:主要用途是向数组的中部插入项,方式有如下3 种。

删除:可以删除任意数量的项,只需指定2 个参数:要删除的第一项的位置和要删除的项数。

例如,splice(0,2)会删除数组中的前两项。

插入:可以向指定位置插入任意数量的项,只需提供3 个参数:起始位置、0(要删除的项数)

和要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。splice(2,0,”red”,”green”)会从当前数组的位置2 开始插入字符串”red”和”green”。

替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定3 个参数:起

始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,

splice (2,1,”red”,”green”)会删除当前数组位置2 的项,然后再从位置2 开始插入字符串

“red”和”green”。

var colors = ["red", "green", "blue"];

var removed = colors.splice(0,1); // 删除第一项

alert(colors); // green,blue

alert(removed); // red,返回的数组中只包含一项

removed = colors.splice(1, 0, "yellow", "orange"); // 从位置1 开始插入两项

alert(colors); // green,yellow,orange,blue

alert(removed); // 返回的是一个空数组

removed = colors.splice(1, 1, "red", "purple"); // 插入两项,删除一项

alert(colors); // green,red,purple,orange,blue

alert(removed); // yellow,返回的数组中只包含一项


位置方法

:indexOf()和lastIndexOf()。这两个方法都接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中,indexOf()方法从数组的开头(位置0)开始向后查找,lastIndexOf()方法则从数组的末尾开始向前查找。这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回1。在比较第一个参数与数组中的每一项时,会使用全等操作符;也就是说,要求查找的项必须严格相等(就像使用===一样)。

迭代方法

每个方法都接收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响this 的值。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。

对every()来说,传入的函数必须对每一项都返回true,这个方法才返回true;否则,它就返回

false。而some()方法则是只要传入的函数对数组中的某一项返回true,就会返回true。

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()也返回一个数组,而这个数组的每一项都是在原始数组中的对应项上运行传入函数的结果。

例如,可以给数组中的每一项乘以2,然后返回这些乘积组成的数组,如下所示。

var numbers = [1,2,3,4,5,4,3,2,1];

var mapResult = numbers.map(function(item, index, array){

return item * 2;

});

alert(mapResult); //[2,4,6,8,10,8,6,4,2]

适合创建包含的项与另一个数组一一对应的数组。

最后一个方法是forEach(),它只是对数组中的每一项运行传入的函数。这个方法没有返回值,

本质上与使用for 循环迭代数组一样。来看一个例子。

var numbers = [1,2,3,4,5,4,3,2,1];

numbers.forEach(function(item, index, array){

//执行某些操作

});

归并方法

reduce()和reduceRight()。这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。reduce()方法从数组的第一项开始,逐个遍历到最后。而reduceRight()则从数组的最后一项开始,向前遍历到第一项。

var values = [1,2,3,4,5];

var sum = values.reduce(function(prev, cur, index, array){

return prev + cur;

});

alert(sum); //15

4 个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。

Date类型

创建 var now = new Date(); 在调用Date 构造函数而不传递参数的情况下,新创建的对象自动获得当前日期和时间

Date.parse方法 var someDate = new Date(Date.parse(“May 25, 2004”));也可以var someDate = new Date(“May 25, 2004”);

Date.UTC方法

// GMT 时间2000 年1 月1 日午夜零时

var y2k = new Date(Date.UTC(2000, 0));

// GMT 时间2005 年5 月5 日下午5:55:55

var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));


也可以直接

// 本地时间2000 年1 月1 日午夜零时

var y2k = new Date(2000, 0);

// 本地时间2005 年5 月5 日下午5:55:55

var allFives = new Date(2005, 4, 5, 17, 55, 55);


Date.now方法返回表示调用这个方法时的日期和时间的毫秒数

//取得开始时间

var start = Date.now();

//调用函数

doSomething();

//取得停止时间

var stop = Date.now(),

result = stop – start;


于Date 类型的valueOf()方法,则根本不返回字符串,而是返回日期的毫秒表示.可以用<.>符号比较日期

日期格式化方法:推荐toUTCString()——以特定于实现的格式完整的UTC 日期。

日期/时间组件方法

RegExp类型 正则

以字面量形式var expression = / pattern / flags ;

其中的模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、

向前查找以及反向引用。每个正则表达式都可带有一或多个标志(flags),用以标明正则表达式的行为。

正则表达式的匹配模式支持下列3 个标志。

g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即

停止;

i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写;

m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模

式匹配的项。

所有元字符都必须转义。正则表达式中的元字符包括:

( [ { \ ^ $ | ) ? * + .]}

另一种创建正则表达式的方式是使用RegExp 构造函数,它接收两个参数:一个是要匹配的字符串模式,另一个是可选的标志字符串

var pattern2 = new RegExp("[bc]at", "i");


由于RegExp 构造函数的模式参数是字符串,所以在某些情况下要对字符进行双重转义。所有元字符都必须双重转义,那些已经转义过的字符也是如此,例如\n(字符\在字符串中通常被转义为\,而在正则表达式字符串中就x 会变成\\)

exec(),该方法是专门为捕获组而设计的。exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组

test(),它接受一个字符串参数。在模式与该参数匹配的情况下返回true;否则,返回false

RegExp 实例继承的toLocaleString()和toString()方法都会返回正则表达式的字面量,与创

建正则表达式的方式无关。

正则表达式的valueOf()方法返回正则表达式本身。

Function类型

每个函数都是Function 类型的实例,而且都与其他引用类型一样具有属性和方法。由于函

数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。

function sum (num1, num2) {

return num1 + num2;

}


这与下面使用函数表达式定义函数的方式几乎相差无几。

var sum = function(num1, num2){

return num1 + num2;

};


由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没有什么不同。换句话

说,一个函数可能会有多个名字,如下面的例子所示。

function sum(num1, num2){

return num1 + num2;

}

alert(sum(10,10)); //20

var anotherSum = sum;

alert(anotherSum(10,10)); //20

sum = null;

alert(anotherSum(10,10)); //20


即使将sum 设置为null,让它与函数“断绝关系”,但仍然可以正常调用anotherSum()。

将函数名想象为指针,也有助于理解为什么ECMAScript 中没有函数重载的概念。以下是曾在第3

章使用过的例子。

function addSomeNumber(num){

return num + 100;

}

function addSomeNumber(num) {

return num + 200;

}

var result = addSomeNumber(100); //300

显然,这个例子中声明了两个同名函数,而结果则是后面的函数覆盖了前面的函数。以上代码实际

上与下面的代码没有什么区别。

解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。请看下面的例子。

alert(sum(10,10));

function sum(num1, num2){

return num1 + num2;

}
可以正常执行

alert(sum(10,10));

var sum = function(num1, num2){

return num1 + num2;

}
出错

函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。

可以从一个函数中返回另一个函数,而且这也是极为有用的一种技术。例如,假设有一个

对象数组,我们想要根据某个对象属性对数组进行排序。而传递给数组sort()方法的比较函数要接收

两个参数,即要比较的值。

function createComparisonFunction(propertyName) {

return function(object1, object2){

var value1 = object1[propertyName];

var value2 = object2[propertyName];

if (value1 < value2){

return -1;

} else if (value1 > value2){

return 1;

} else {

return 0;

}

};

}

在内部函数接收到propertyName 参数后,它会使用方括号表示法来

取得给定属性的值。取得了想要的属性值之后,定义比较函数就非常简单了。上面这个函数可以像在下

面例子中这样使用。

var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];

data.sort(createComparisonFunction("name"));

alert(data[0].name); //Nicholas

data.sort(createComparisonFunction("age"));

alert(data[0].name); //Zachary


函数内部属性arguments 和this

arguments主要用途是保存函数参数,但这个对象还有一个名叫callee 的属性,该属性是一个指针,指向拥有这个arguments 对象的函数。请看下面这个非常经典的阶乘函数。

function factorial(num){

if (num <=1) {

return 1;

} else {

return num * factorial(num-1)

}

}

定义阶乘函数一般都要用到递归算法;如上面的代码所示,在函数有名字,而且名字以后也不会变

的情况下,这样定义没有问题。但问题是这个函数的执行与函数名factorial 紧紧耦合在了一起。为

了消除这种紧密耦合的现象,可以像下面这样使用arguments.callee。

function factorial(num){

if (num <=1) {

return 1;

} else {

return num * arguments.callee(num-1)

}

}

在这个重写后的factorial()函数的函数体内,没有再引用函数名factorial。这样,无论引用

函数时使用的是什么名字,都可以保证正常完成递归调用。例如:

var trueFactorial = factorial;

factorial = function(){

return 0;

};

alert(trueFactorial(5)); //120

aler t(factorial(5)); //0


函数属性:length(希望传入的参数个数)和prototype

函数方法:每个函数都包含两个非继承而来的方法:apply()和call()。这两个方法的用途都是在特定的作

用域中调用函数,实际上等于设置函数体内this 对象的值。

首先,apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是Array 的实例,也可以是arguments 对象。

call()方法与apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于call()

方法而言,第一个参数是this 值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用

call()方法时,传递给函数的参数必须逐个列举出来

传递参数并非apply()和call()真正的用武之地;它们真正强大的地方是能够扩充函数

赖以运行的作用域

window.color = "red";

var o = { color: "blue" };

function sayColor(){

alert(this.color);

}

sayColor(); //red

sayColor.call(this); //red

sayColor.call(window); //red

sayColor.call(o); //blue


使用call()(或apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。

在前面例子的第一个版本中,我们是先将sayColor()函数放到了对象o 中,然后再通过o 来调用它的;

而在这里重写的例子中,就不需要先前那个多余的步骤了。

bind()。这个方法会创建一个函数的实例,其this 值会被绑定到传给bind()函数的值。例如:

window.color = "red";

var o = { color: "blue" };

function sayColor(){

alert(this.color);

}

var objectSayColor = sayColor.bind(o);

objectSayColor(); //blue


包装类型

3 个特殊的引用类型:Boolean(建议不使用)、Number 和String

每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们

能够调用一些方法来操作这些数据

引用类型与基本包装类型的主要区别就是对象的生存期。使用new 操作符创建的引用类型的实例,

在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一

行代码的执行瞬间,然后立即被销毁。

要注意的是,使用new 调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的。

例如:

var value = “25”;

var number = Number(value); //转型函数

alert(typeof number); //”number”

var obj = new Number(value); //构造函数

alert(typeof obj); //”object”

Number 类型还提供了一些用于将数值格式化为字符串的方法。

其中,toFixed()方法会按照指定的小数位返回数值的字符串表示,例如:

var num = 10;

alert(num.toFixed(2)); //”10.00”

toExponential方法 科学计数

var num = 10;

alert(num.toExponential(1)); //”1.0e+1”

对于一个数值来说,toPrecision()方法可能会返回固定大小(fixed)格式,也可能返回指数

(exponential)格式;具体规则是看哪种格式最合适。这个方法接收一个参数,即表示数值的所有数字的

位数(不包括指数部分)

String 字符串拼接一般用+

slice , substring, substr

slice()和substring()的第二个参数指定的是子字符串最后一个字符后面的位置。而substr()的第二个参数指定的则是返回的字符个数。如果没有给这些方法传递第二个参数,则将字符串的长度作为结束位置

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"


在传递给这些方法的参数是负值的情况下,它们的行为就不尽相同了。其中,slice()方法会将传

入的负值与字符串的长度相加,substr()方法将负的第一个参数加上字符串的长度,而将负的第二个

参数转换为0。最后,substring()方法会把所有负值参数都转换为0。

var stringValue = "hello world";

alert(stringValue.slice(-3)); //"rld"

alert(stringValue.substring(-3)); //"hello world"

alert(stringValue.substr(-3)); //"rld"

alert(stringValue.slice(3, -4)); //"lo w"

alert(stringValue.substring(3, -4)); //"hel"

alert(stringValue.substr(3, -4)); //""(空字符串)


有两个可以从字符串中查找子字符串的方法:indexOf()和lastIndexOf()

var stringValue = "Lorem ipsum dolor sit amet, consectetur adipisicing elit";

var positions = new Array();

var pos = stringValue.indexOf("e");

while(pos > -1){

positions.push(pos);

pos = stringValue.indexOf("e", pos + 1);

}

alert(positions); //"3,24,32,35,52"


trim()方法。这个方法会创建一个字符串的副本,删除前置及后缀的所有空格,然后返回结果

var stringValue = " hello world ";

var trimmedStringValue = stringValue.trim();

alert(stringValue); //" hello world "

alert(trimmedStringValue); //"hello world"


由于trim()返回的是字符串的副本,所以原始字符串中的前置及后缀空格会保持不变

toLowerCase()和toUpperCase()

String 类型定义了几个用于在字符串中匹配模式的方法。

第一个方法就是match(),在字符串上调用这个方法,本质上与调用RegExp 的exec()方法相同。match()方法只接受一个参数,要么是一个正则表达式,要么是一个RegExp 对象。

var text = "cat, bat, sat, fat";

var pattern = /.at/;

//与pattern.exec(text)相同

var matches = text.match(pattern);

alert(matches.index); //0

alert(matches[0]); //"cat"

alert(pattern.lastIndex); //0


另一个用于查找模式的方法是search()。这个方法的唯一参数与match()方法的参数相同:由字

符串或RegExp 对象指定的一个正则表达式。search()方法返回字符串中第一个匹配项的索引;如果没

有找到匹配项,则返回-1。而且,search()方法始终是从字符串开头向后查找模式。看下面的例子。

var text = "cat, bat, sat, fat";

var pos = text.search(/at/);

aler t(pos); //1


为了简化替换子字符串的操作,ECMAScript 提供了replace()方法。这个方法接受两个参数:第

一个参数可以是一个RegExp 对象或者一个字符串(这个字符串不会被转换成正则表达式),第二个参

数可以是一个字符串或者一个函数。如果第一个参数是字符串,那么只会替换第一个子字符串。要想替

换所有子字符串,唯一的办法就是提供一个正则表达式,而且要指定全局(g)标志,如下所示。

var text = "cat, bat, sat, fat";

var result = text.replace("at", "ond");

alert(result); //"cond, bat, sat, fat"

result = text.replace(/at/g, "ond");

aler t(result); //"cond, bond, sond, fond"


$1是第一个捕获组

var text = "cat, bat, sat, fat";

result = text.replace(/(.at)/g, "word ($1)");

alert(result); //word (cat), word (bat), word (sat), word (fat)


replace的参数可以是函数

function htmlEscape(text){

return text.replace(/[<>"&]/g, function(match, pos, originalText){

switch(match){

case "<":

return "<";

case ">":

return ">";

case "&":

return "&";

case "\"":

return """;

}

});

}

alert(htmlEscape("<p class=\"greeting\">Hello world!</p>"));

//<p class="greeting">Hello world!</p>


最后一个与模式匹配有关的方法是split(),这个方法可以基于指定的分隔符将一个字符串分割成

多个子字符串,并将结果放在一个数组中。分隔符可以是字符串,也可以是一个RegExp 对象(这个方

法不会将字符串看成正则表达式)。split()方法可以接受可选的第二个参数,用于指定数组的大小,

以便确保返回的数组不会超过既定大小。请看下面的例子。

var colorText = "red,blue,green,yellow";

var colors1 = colorText.split(","); //["red", "blue", "green", "yellow"]

var colors2 = colorText.split(",", 2); //["red", "blue"]

var colors3 = colorText.split(/[^\,]+/); //["", ",", ",", ",", ""]


内置对象

内置对象的定义是:“由ECMAScript 实现提供的、不依赖于宿主环境的对象,这些对象在ECMAScript 程序执行之前就已经存在了

在所有代码执行之前,作用域中就已经存在两个内置对象:Global 和Math。在大多数ECMAScript

实现中都不能直接访问Global 对象;不过,Web 浏览器实现了承担该角色的window 对象。全局变

量和函数都是Global 对象的属性。Math 对象提供了很多属性和方法,用于辅助完成复杂的数学计算

任务。

global对象

Global 对象的encodeURI()和encodeURIComponent()方法可以对URI(Uniform Resource

Identifiers,通用资源标识符)进行编码,以便发送给浏览器。有效的URI 中不能包含某些字符,例如

空格。而这两个URI 编码方法就可以对URI 进行编码,它们用特殊的UTF-8 编码替换所有无效的字符,

从而让浏览器能够接受和理解。

当解析器发现代码中调用eval()方法时,它会将传入的参数当作实际的ECMAScript 语句来解析,

然后把执行结果插入到原位置。通过eval()执行的代码被认为是包含该次调用的执行环境的一部分,

因此被执行的代码具有与该执行环境相同的作用域链。这意味着通过eval()执行的代码可以引用在包

含环境中定义的变量,举个例子:

var msg = “hello world”;

eval(“alert(msg)”); //”hello world”

Global 对象还包含一些属性,其中一部分属性已经在本书前面介绍过了。例如,特殊的值

undefined、NaN 以及Infinity 都是Global 对象的属性。此外,所有原生引用类型的构造函数,像

Object 和Function,也都是Global 对象的属性

Math对象

min和max

Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;

Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;

Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数

Math.random()方法返回大于等于0 小于1 的一个随机数。对于某些站点来说,这个方法非常实用,

因为可以利用它来随机显示一些名人名言和新闻事件。套用下面的公式,就可以利用Math.random()

从某个整数范围内随机选择一个值。

值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值)

举例来说,如果你想选择一个1

到10 之间的数值,可以像下面这样编写代码:

var num = Math.floor(Math.random() * 10 + 1);

多数情况下,其实

都可以通过一个函数来计算可能值的总数和第一个可能的值,例如:

function selectFrom(lowerValue, upperValue) {

var choices = upperValue - lowerValue + 1;

return Math.floor(Math.random() * choices + lowerValue);

}

var num = selectFrom(2, 10);

aler t(num); // 介于 2 和10 之间(包括 2 和 10)的一个数值

var colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"];

var color = colors[selectFrom(0, colors.length-1)];

aler t(color); // 可能是数组中包含的任何一个字符串
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: