一、JavaScript对象简介
JavaScript数据类型分为基本数据类型和引用类型两种。在ECMAScript中,引用类型是一种数据结构,用于将数据和功能组织在一起,这有点类似于传统面向对象语言中的“类”,但ECMAScript只是一种基于对象的语言,它不具备传统的面向对象语言所支持的类和接口等基本结构,因此,在ECMAScript中,引用类型被称为“对象定义”,它描述一类对象所具有的属性和方法。而引用类型的值则称为“对象”,它是引用类型的一个实例。
•ECMAScript中的对象有三种:
☞ 本地对象:ECMA-262 把本地对象定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。简单来说,本地对象就是 ECMA-262 定义的引用类型。它们包括:Object、Function、Array、String、Boolean、Number、Date、RegExp。
☞ 内置对象:ECMA-262 把内置对象定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。
•创建本地对象:JavaScript中,创建对象有以下几种常用的方式:
☞ 使用new操作符后跟一个构造函数来创建
如 var obj=new Object();
var d=new Date();
☞ 使用对象字面量表示法
如 var person={
name:“张三”,
age:25,
height:“78KG”}
使用函数来构造对象
如 function person(name,age,height){
this.name=name;
this.age=age;
this.height=height;
}
var person3=new person("王五",28,"68kg");
建议多使用对象字面量法,因为这种语法要求的代码量少,而且能给人封装数据的感觉。实际上,对象字面量也是向函数传递大量可选参数的首选方式:例如:
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”;
}
console.log(output);
}
displayInfo({name:'abc',age:29})
displayInfo({name:'def'});
在这个例子中,函数displayInfo()接受一个名为args的参数。这个参数可能带有一个名为name或age的属性,也可能这两个属性都有或者都没有。
这种传递参数的模式最适合需要向函数传入大量可选参数的情形。一般来讲,命名参数虽然容易处理,但在有多个可选参数的情况下就会显得不够灵活。最好的做法是对那些必需值使用命名参数,而使用对象字面量来封装多个可选参数。
一般来说,访问对象属性时使用的都是点表示法,这也是很多面向对象语言中通用的语法。不过,在javascript也可以使用方括号表示法来访问对象的属性。在使用方括号时,应该将要访问的属性以字符串的形式放在方括号中。例如:
person['name'] person.name
从功能上看,这两种访问对象属性的方法没有任何区别。但方括号的主要优点是可以通过变量来访问属性,例如:
var propertyName ='def';
console.log(person[propertyName]);
如果属性名中包含会导致语法错误的字符,或者属性名使用的关键字或保留字,也可以使用方括号表示法例如:
person[“first name”]='abc';
由于 “first name”中包含一个空格,所以不能使用点表示法来访问它。
然而,属性名中是可以包含非字母非数字的,这时候就可以使用方括号表示法来访问它们。通常,除非必须使用变量来访问属性,建议使用点表示法。
访问对象属性
如 var arr=new Array();
alert(arr.length);
调用对象方法
如 var d1=new Date();
alert(d1.getFullYear());
二、Object类型
Object类型用来创建一个通用的对象,它是ECMAScript中使用最多的一个类型,虽然Object的实例不具备多少功能,但对于在应用程序中存储和传输数据来说,它是非常理想的选择。
ECMAScript中的所有对象都由这个对象继承而来,Object 对象中的所有属性和方法都会出现在其他对象中 。
Object类型的使用:
格式: var obj=new Object([value]);
obj—必选项,代表要赋值为Object对象的变量名。
vaule—可选项,可以是任意一种 JavaScript的基本数据类型。(Number、Boolean、或 String。)如果 value 为一个对象,返回不作改动的该对象。如果value 为 null、undefined,或者没有给出,则产生没有内容的对象。
Object对象的属性和方法:
属性/方法 |
说 明 |
constructor |
对象的构造函数 |
hasOwnProperty(propname) |
判断对象是否有某个特定的属性 |
isPrototypeof(0bject) |
判断对象是否是另一个对象的原型 |
propertyIsEnumerable(pro)name) |
判断给定的属性是否可以用 for...in 语句进行枚举 |
toLocaleString() |
返回对象的本地化字符串 |
toString() |
返回对象的字符串形式 |
valueOf() |
返回对象的原始值 |
三、Array类型
Array类型也是ECMAScript中最常用的类型之一,ECMAScript中的数组与其他语言中的数组有着相当大的区别:
☞ ECMAScript中的数组的每一项可以保存任何类型的数据。
☞ ECMAScript数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据。
数组的创建
☞ 使用Array()构造函数创建
如 var arr1=new Array();
var arr2=new Array(10);
var arr3=new Array(“张三”);
var arr4=Array(3);
使用字面量形式创建
如 var colors=["red","blue","green"];
var name=[];
访问数组元素
使用方括号加索引值得形式。
如 colors[0]
colors[2]
数组的length属性
ECMAScript中,数组的length属性不是只读的,通过改变这个属性,可以从数组的末尾移除数组元素或向数组中添加新项。
如 var colors=["red","blue","green"];
colors.length=2; //移除末尾项green
colors[colors.length]=black; //新增一项
colors.lenght=5; //新增两个空项
检测数组
要判断某个对象是否为数组,ECMAScript 3使用instanceof操作符检测。在ECMAScript 5中则新增了一个Array.isArray()方法来判断。
•数组对象的常用属性和方法:
属性/方法 |
说 明 |
length |
数组的长度 |
toString() |
把数组的值转换为字符串,并返回结果 |
toLocaleString() |
把数组转换为本地化数组,并返回字符串结果 |
valueOf() |
返回数组对象的原始值 |
push() |
向数组的末尾添加一个或多个数组元素,并返回数组长度 |
pop() |
删除并返回数组的最后一个元素 |
shift() |
删除并返回数组的第一个元素 |
unshift() |
向数组的开头添加一个或多个元素,并返回数组长度 |
sort() |
对数组元素进行排序 |
reverse() |
颠倒数组元素的排列顺序 |
数组对象的常用属性和方法:
属性/方法 |
说 明 |
join() |
把数组中的元素放入字符串。元素通过指定的分隔符进行分隔 |
concat() |
连接两个或更多的数组,并返回结果 |
slice(start,end) |
返回数组中的一部分元素(不含end位置元素) |
splice(start,deleteCount,value..) |
插入、删除或替换数组中的元素 |
迭代方法(es5新增)每个方法都接收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象-影响this的值。传入这些方法中的函数会接收三个参数:数组项的值,该项在数组中的位置和数组对象本身。根据使用的方法不同,这个函数执行后的返回值可能会也可能不会影响方法的返回值。
every():对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true.
下例检测数组中的所有元素是否都大于 10。
function isBigEnough(element, index, array) {
return (element >= 10);
}
var passed = [12, 5, 8, 130, 44].every(isBigEnough);
// passed is false
passed = [12, 54, 18, 130, 44].every(isBigEnough);
filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组。
返回数组的一个子集,回调函数用于逻辑判断是否返回,返回true则把当前元素加入到返回数组中,false则不加;
新数组只包含返回true的值,索引缺失的不包括,原数组保持不变。
var data = [1,2,3,4,5];
console.log(data.filter(function(e){
return e%2==0;
}));
console.log(data);
forEach()对数组中的每一项给定函数。这个方法没有返回值
从头到尾遍历数组,为每个元素调用指定函数
第一个参数:传递的函数
该函数调用的参数:数组元素、元素索引、数组本身
var data =[1,2,3,4,5];
var sum =0;
data.forEach(function(value){
sum+=value;
});
console.log(“sum:”+sum);
data.forEach(function(a,i,v){
a [i]=v+1;
});
console.log(“加1后的值:”+data);
map()对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
调用数组的每个元素传递给指定的函数,并返回一个包含返回值的新数组;传递给map()的函数有返回值,map()返回新数组,不会修改调用的数组;
a =[1,2,3];
b = a.map(function(x){return x*x});
console.log(a);
some():对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true.以上方法都不会修改数组中的包含值。
var a = new Array(1,2,3,4,5,6);
console.log(a.some(function(e){
return e>3;}));
console.log(a.every(function(e){
return e>3}));
every每一项都为true才为true,some只要有一项为true就为true。
every(function(item,index,array){});
some(function(item,index,array){});
归并方法:
ECMAScript5还新增了两个归并数组的方法:reduce()和reduceRight().这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。其中reduce()方法从数组的第一项开始,逐个遍历到最后。而reduceRight()则从数组的最后一项开始,向前遍历到第一项。
这两个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。传给reduce()和reduceRight()的函数接收4个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。
var values = [1,2,3,4,5]
var sum = values.reduce(function(prev,cur,index,array){
return prev+cur;
});
console.log(sum);
values.reduceRight(function(prev,cur,index,array){
return prev+cur;
});
console.log(sum);
四、Date类型
Date对象提供了与日期、时间相关的操作功能。ECMAScript中的Date类型是在早期java中的java.util.Date类基础上构建的,它使用来自UTC(国际协调时间)1970年1月1日零时开始经过的毫秒数来保存日期。在使用这种数据存储格式的条件下,Date类型保存的日期能够精确到1970年1月1日之前或之后285616年。
创建日期对象:
var d1=new Date();
var d2=new Date(“May 25,2008”);
Date对象的常用属性和方法:
属性/方法 |
说 明 |
Date() |
返回当日的日期和时间 |
getDate() |
返回日期对象中的天数,如超过了改月份应有的天数,则增加月份 |
getDay() |
返回日期对象中星期的星期几(0-6) |
getMonth() |
返回日期对象的月份(0-11) |
getFullYear() |
从日期对象中返回四位数字表示的年份 |
getYear() |
返回日期对象的年份(真实年份减去1900) |
getHours() |
返回日期对象中的小时(0-23) |
getMinutes() |
返回日期对象中的分钟(0-59) |
getSeconds() |
返回日期对象中的秒(0-59) |
getMilliseconds() |
返回日期对象中的毫秒(0-999) |
属性/方法 |
说 明 |
getTime() |
返回1970年1月1日至今的毫秒数 |
getTimezoneOffset() |
返回本地时间与格林威治标准时间的分钟差 |
getUTCDate() |
根据世界时从 Date 对象返回月中的一天 (1 ~ 31)。 |
getUTCDay() |
根据世界时从 Date 对象返回周中的一天 (0 ~ 6)。 |
getUTCMonth() |
根据世界时从 Date 对象返回月份 (0 ~ 11)。 |
getUTCFullYear() |
根据世界时从 Date 对象返回四位数的年份。 |
getUTCHours() |
根据世界时返回 Date 对象的小时 (0 ~ 23)。 |
getUTCMinutes() |
根据世界时返回 Date 对象的分钟 (0 ~ 59)。 |
getUTCSeconds() |
根据世界时返回 Date 对象的秒钟 (0 ~ 59)。 |
getUTCMilliseconds() |
根据世界时返回 Date 对象的毫秒(0 ~ 999)。 |
属性/方法 |
说 明 |
parse() |
返回1970年1月1日零时到指定日期的毫秒数 |
setDate() |
设置日期对象中的天数,如超过了改月份应有的天数,则增加月份 |
setDay() |
设置日期对象中星期的星期几(0-6) |
setMonth() |
设置日期对象的月份(0-11) |
setFullYear() |
设置日期对象中年份(四位数字) |
setYear() |
设置日期对象的年份(请用setFullYear代替) |
setHours() |
设置日期对象中的小时(0-23) |
setMinutes() |
设置日期对象中的分钟(0-59) |
setSeconds() |
设置日期对象中的秒(0-59) |
setMilliseconds() |
设置日期对象中的毫秒(0-999) |
属性/方法 |
说 明 |
setTime() |
以毫秒数设置日期对象 |
setUTCDate() |
根据世界时设置 Date 对象月中的一天 (1 ~ 31)。 |
setUTCMonth() |
根据世界时设置 Date 对象中的月份 (0 ~ 11)。 |
setUTCFullYear() |
根据世界时设置 Date 对象中的年份(四位数)。 |
setUTCHours() |
根据世界时设置 Date 对象中的小时 (0 ~ 23)。 |
setUTCMinutes() |
根据世界时设置 Date 对象中的分钟 (0 ~ 59)。 |
setUTCSeconds() |
根据世界时设置 Date 对象中的秒钟 (0 ~ 59)。 |
setUTCMilliseconds() |
根据世界时设置 Date 对象的中毫秒(0 ~ 999)。 |
toString() |
把Date对象转为字符串 |
toTimeString() |
把Date对象的时间部分转为字符串 |
toDateString() |
把Date对象的日期部分转为字符串 |
五、RegExp类型
RegExp对象表示正则表达式,它是字符串执行模式匹配的强大工具。ECMAScript正则表达式使用类似Perl的语法。
创建正则表达式
格式: var expression=/pattern/flags;
或 var expression=new RegExp(pattern,flags);
参数说明:
pattern:字符串,指定正则表达式的模式或其他正则表达式
flags:可选参数 i-忽略大小写 g-全局匹配 m-多行模式
i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写
g:表示全局(glob)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止
m:表示多行模式(multiline)即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。
测试正则表达式
如 var re1=new RegExp("abc","i");
var re2=/abc/i;
test()方法
如 alert(re1.test("abc1234edefg"));
alert(re2.test("ABCA1234edefg"));
属性/方法 |
说 明 |
global |
RegExp对象是否具有标志g |
ignoreCase |
RegExp对象是否具有标志i |
lastIndex |
一个整数,标示开始下一次匹配的字符位置 |
multiline |
RegExp对象是否具有标志m |
source |
正则表达式的源文本 |
compile() |
编译正则表达式 |
exec() |
检查字符串中指定的值,返回找到的值,并确定其位置 |
test() |
检查字符串是否包含指定的模式,返回true或fals |
六、Function类型
ECMAScript中最有趣的是—函数实际上是对象。每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上一个指向函数对象的指针,不会与某个函数绑定。
函数可以使用function关键字来声明
如 function sum(num1,num2){
return num1+num2;
}
函数也通过函数表达式来定义
如 var sum=function(num1,num2){
return num1+num2;
};
也可以通过构造函数来定义
var sum=new Function(“num1”,”num2”,”return num1+num2”); //不推荐
没有重载(深入理解)
var addSomeNumber = function(num){return num+100};
addSomeNumber = function(num){return num+200};
var result = addSomeNumber;
函数声明与函数表达式
解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明
并使其在执行任何代码之前可用(可以访问);至于函数表达式则必须等到解析器执行到它所在的代码行,才会真正被解释执行
console.log(sum(10,10))
function sum(num1,num2){return num1+num2}
以上代码完全可以正常运行,因为在代码开始之前,解析器就已经通过一个名为函数声明提升(function declaration hosting)的过程,读取并将函数声明添加到执行环境中。对代码求值时,JavaScript引擎在第一遍会声明函数并将它们放到源代码树的顶部。所以,即使声明函数的代码在调用它的代码后面,javascript引擎也能把函数声明提升到顶部。
console.log(sum(10,10))
var sum = function(num1,num2){return num1+num2}
函数位于一个初始化语句中,而不是一个函数声明。在执行函数所在的语句之前,变量sum中不会保存对函数的引用;而且,由于第一个行代码就会导致意外标示符的错误。也不会执行到下一行。var sum = function sum(){}
作为值的函数
因为ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。不仅可以像传递参数一样把函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。
function callSomeFunction(someFunction,someArgument){
return someFunction(someArgument);
}
这个函数接收两个参数,第一个参数应该是一个函数,第二个参数是要传递给该函数的一个值。
function add10(num){return num+10;}
var result = callSomeFunction(add10,10);
console.log(result);
function getGreeting(name){ return “Hello,”+name;}
var result1= callSomeFunction(getGreeting,'abc');
console.log(result1);
这里的callSomeFunction()函数是通用的,即无论第一个参数中传递进来的是什么函数。它都会返回执行第一个参数后的结果
要访问函数指针而不执行函数的话,必须去掉函数名后面的那对大括号,因此上面例子中传递给callSomeFunction()的是add10和 getGreeting,而不是执行它们之后的结果。
当然,可以从一个函数中返回另一个函数,而且这也是一种极为有用的一种技术。例如,假设有一个对象数组,想要根据某个对象属性对数组进行排序。而传递给数组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;}
};}
var data = [{name:'abc',age:28},{name:'def',age:29}];
data.sort(createComparisonFunction('name'));
console.log(data[0]);
data.sort(createComparisonFunction('age'));
console.log(data[0]);
函数内部属性
在函数内部,有两个特殊的对象:arguments和this.arguments的主要用途是保存函数参数,但这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
function factorial(num){
if(num<=1){return 1;}else{return num*factorial(num-1);}
}
定义阶乘一般都要用到递归算法:在函数有名字,而且名字以后也不会变的情况下,这样定义没有问题。但问题是这个函数的执行与函数名factorial紧紧耦合在了一起。
为了消除这种紧密耦合的现象,可以使用arguments.callee
return num*arguments.callee(num-1);
var trueFactorial = factorial;
factorial = function(){return 0;};
函数内部的另一个特殊对象是this.其行为与java和C#中的this类似。this 引用的是函数执行的环境对象—或者也可以说是this值(当在网页的全局作用域中调用函数时,this对象的引用就是window)
window.color = “red”;
var o ={color:”blue”};
function sayColor(){
console.log(this.color);
}
sayColor();
o.sayColor = sayColor;
o.sayColor();
上面这个函数sayColor()是在全局作用域中定义的,它引用了this对象。由于在调用函数之前,this的值并不确定,因此this可能会在代码执行过程中引用不同的对象。当在全局作用域中调用sayColor()时,this引用的是全局对象window;换句话说,对this.color求值会转换成对window.color求值,于是结果就返回了“red”.而当把这个函数赋给对象o并调用o.sayColor()时,this引用的是对象。因此对this.color求值会转换成对o.color求值。结果就返回了“blue”.
函数的名字仅仅是一个包含指针的变量而已。因此即使是在不同的环境中执行,全局的sayColor()函数与o.sayColor()指向的仍然是同一个函数。
ES5也规范化了另一个函数对象的属性:caller.这个属性中保存着调用当前函数的函数引用,如果是在全局作用域中调用当前函数,它的值为null.
function outer(){inner();}
function inner(){console.log(inner.caller);}
outer();
以上代码会导致警告框中显示outer()函数的源代码。因为outer()调用了inner().所以。inner.caller就指向outer().为了实现更松散的耦合,也可以通过arguments.callee.caller来访问相同的信息。
console.log(arguments.callee.caller);
当函数在严格模式下运行时,访问argument.callee会导致错误。ES5还定义了arguments.caller属性。但在严格模式下访问它也会导致错误,而在非严格模式下这个属性始终是undefined.定义arguments.callee属性是为了分清arguments.caller和函数的caller属性。
不能为caller属性赋值。
函数属性和方法
ECMAScript中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:length和prototype其中,length属性表示函数希望接收的命名参数的个数。
function sayName(name){
console.log(name);
}
function sum(num1,num2){
return num1+num2;
}
function sayHi(){
alert('hi');
}
console.log(sayName.length);
console.log(sum.length);
console.log(sayHi.length);
在ECMAScript核心所定义的全部属性中,最耐人寻味的就要数prototype属性了。对于ECMAScript中的引用类型而言,prototype是保存它们所有实例方法的真正所在。toString()和valueOf()等方法实际都保存在prototype名下,只不过是通过各自对象的实例访问罢了。
每个函数都包含两个非继承而来的方法:apply()和call().这两个方法的用途都是在特定的作用域中调用的函数。实际上等于设置函数体内this对象的值。首先,apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是Array实例,也可是是arguments对象。
function sum(num1,num2){
return num1+num2;
}
function callSum1(num1,num2){
return sum.apply(this,arguments);
}
function callSum2(num1,num2){ return sum.apply(this,[num1,num2]);}
console.log(callSum1(10,10))
console.log(callSum2(10,10))
callSum1在执行sum()函数时传入this做为this值(因为是在全局作用域中调用的,所以传入的就是window对象)和arguments对象。而callSum2同样也调用了sum()函数,但它传入的则是this和一个参数数组。
在严格模式下,未指定环境对象而调用函数,则this值不会转型为window.除非明确把函数添加到某个对象或者调用apply()或call()。否则this值将是undefined.
call()方法与apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于call()方法而言,第一个参数是this值没有变化,变化的是其余参数都直接传递给函数。在使用call()方法时,传递给函数的参数必须逐个列举出来。
function sum(num1,num2){
return num1+num2;
}
function callSum(num1,num2){return sum.call(this,num1,num2)} console.log(callSum(1,1));
在使用call()方法的情况下,callSum()必须明确地传入每一个参数。结果与使用apply()没有什么不同。至于是使用apply()还是call(),完全取决于采取哪种给函数传递参数的方式最方便。打算直接传入arugments对象,或者包含函数中先接收的也是一个数组,那么使用apply()肯定更方便,否则,选择call()可能更合适。(在不给函数传递参数的情况下,使用哪个方法都无所谓。)
事实上,传递参数并非apply()和call()真正的用武之地;它们真正强大的地方是能够扩充函数赖以运行的作用域。
window.color='red';
var o = {color:'red'};
function sayColor(){
console.log(this.color);
}
sayColor();
sayColor.call(this);
sayColor.call(window);
sayColor.call(o);
这一次,sayColor()也是作为全局函数定义的,而且当在全局作用域中调用它时,它确实会显示”red”-因为对this.color的求值会转换成对window.color的求值。而sayColor.call(this)和sayColor.call(window),则是两个显式地在全局作用域中调用函数的方式,结果当然都会显示“red”.但是当运行 sayColor.call(o)时,函数的执行环境就不一样了,因为此时函数体内的this对象指向了o,于是结果显示的是“blue”.使用call()(或apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。
ES5 还定义了一个方法:bind().这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。
window.color = 'red';
var o = {color:'blue'};
function sayColor(){ console.log(this.color);} var objectSayColor = sayColor.bind(o); objectSayColor();
七、基本包装类型
为了便于操作基本类型值,ECMAScript中还提供了3个特殊的引用类型:Boolean、Number和String。这些类型与其他的引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。
实际上,每当读取一个基本类型值得时候,后台就会创建一个对应的基本包装类型的对象,从而让我们可以调用一些方法来操作这些数据。
如 var s1=“Hello”;
var s2=s1.substring(2);
引用类型与基本包装类型的主要区别就在于对象的生存期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前一直都保存在内存中;而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。
如 var str=“Hello”;
str.color=“red”;
alert(str.color); //输出undefined
八、基本包装类型—Boolean类型
Boolean类型是与布尔值对应的引用类型。
创建Boolean对象
如 var bool1=new Boolean(true);
var bool2=new Boolean(false);
Boolean类型的对象重写了valueOf()方法,返回基本类型值true或false,重写了toString()方法,返回字符串”true”或”false”。
Boolean对象在ECMAScript中的用处不大,建议不要使用。
九、基本包装类型—Number类型
Number类型是与数字值对应的引用类型。
创建Number对象
var num=new Number(10);
构造函数 Number() 可以不与运算符 new 一起使用,而直接作为转化函数来使用。以这种方式调用 Number() 时,它会把自己的参数转化成一个数字,然后返回转换后的原始数值(或 NaN)。
构造函数通常还用作 5 个有用的数字常量的占位符,这 5 个有用的数字常量分别是可表示的最大数、可表示的最小数、正无穷大、负无穷大和特殊的 NaN 值。 注意,这些值是构造函数 Number() 自身的属性,而不是单独的某个 Number 对象的属性。
Number对象的常用属性和方法:
属性/方法 |
说 明 |
Number.MAX_VALUE |
最大数 |
Number.MIN_VALUE |
最小数 |
Number.NaN |
非数字值 |
Number.NEGATIVE_INFINITY |
负无穷大 |
Number.POSITIVE_INFINITY |
正无穷大 |
toString() |
把数字转换为字符串 |
toLocaleString() |
把数字转换为字符串,使用本地数字格式顺序。 |
toFixed(digit) |
把数字转换为字符串,小数点后有指定位数的数字。 |
toExponential(digit) |
把对象的值转换为指数计数法。 |
toPrecision(n) |
把数字格式化为指定的长度。 |
valueOf() |
返回一个 Number 对象的基本数字值。 |
十、基本包装类型—String类型
String类型是与字符串的对象包装类型。
创建String对象
var str=new String(“Hello”);
或 var str=String(“Hello”);
String对象的常用属性和方法:
属性/方法 |
说 明 |
length |
字符串的长度 |
charAt(n) |
返回在指定位置的字符 |
charCodeAt(n) |
返回指定位置字符的unicode编码 |
concat() |
连接字符串 |
slice(start,end) |
返回字符串的一部分 |
substring(start,end) |
提取字符串中两个指定的索引号之间的字符。 |
substr(start,length) |
从起始索引号提取字符串中指定数目的字符。 |
indexOf() |
从前面开始向后检索字符串 |
lastIndexOf() |
从后向前检索字符串 |
trim() |
删除字符串前后空格 |
toLowerCase() |
把字符串转为小写 |
toUpperCase() |
把字符串转为大写 |
String对象的常用属性和方法:
属性/方法 |
说 明 |
match() |
找到一个或多个正则表达式的匹配。 |
replace() |
替换与正则表达式匹配的子串。 |
search() |
检索与正则表达式相匹配的值。 |
split() |
把字符串分割为字符串数组 |
fromCharCode() |
接收多个字符编码,转换成字符串 |
十一、单体内置对象
ECMA-262 把内置对象定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。ECMA-262 只定义了两个内置对象,即 Global 和 Math。
十三、单体内置对象-Global对象
Global(全局)对象是ECMAScript中最特别的对象,因为实际上它根本不存在。但刚才不是说Global是对象吗?没错。这里需要理解的主要概念是,在ECMAScript中,不存在独立的函数,所有函数都必须是某个对象的方法。我们前面介绍的函数,如isNaN()、isFinite()、parseInt()和parseFloat()等,看起来都像独立的函数。实际上,它们都是Global对象的方法。
Global对象不只有方法,它还有属性。还记得那些特殊值undefined、NaN和Infinity吗?它们都是Global对象的属性。此外,所有本地对象的构造函数也都是Global对象的属性。
ECMAScript虽然没有指出如何直接访问Global对象,但WEB浏览器都是将这个全局对象作为window对象的一部分加以实现的。因此,在全局作用域中声明的所有变量和函数,就都成为了window对象的属性。
如: var color=“red”;
function sayColor(){
alert(window.color);
}
window.sayColor();
eval()方法
它只接受一个参数,即要执行的ECMAScript(或javascript)字符串
eval(“alert('hi')”);
等价于alert('hi');
当解析器发现代码中调用eval()方法时,它会将传入的参数当作实际的ECMAScript语句来解析,然后把执行结果插入到原来的位置。通过eval()执行的代码被认为是包含该次调用的执行环境的一部分。因此被执行的代码具有与该执行环境相同的作用域链。通过eval()执行的代码可以引用在包含环境中定义的变量。
var message='hello world';
eval('alert(“message”)');
变量msg是在eval()调用的环境之外定义的,但其中调用的alert()仍然能够显示“hello world”.代码被替换成了一行真正的代码。定义一个函数在该调用的外部代码中引用这个函数
eval(“function sayHi(){alert('hi')}”);
sayHi();
在eval()中创建的任何变量或函数都不会被提升,因为在解析代码的时候,它们被包含在一个字符串中;它们只在eval()执行的时候创建。
严格模式下,在外部访问不到eval()中创建的任何变量或函数,因此前面两个例子都会导致错误。同样,在严格模式下,为eval赋值也会导致错误。
eval解释代码字符串的能力非常强大,但也非常危险,因此在使用eval()时必须极为谨慎。特别是在用它执行用户输入数据的情况下。
十三、单体内置对象-Math对象
Math对象提供了一组数学常数的定义和数学函数。与用JavaScript代码编写的计算功能相比,Math对象提供的计算功能执行起来要快得多。
Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(),像 Math.sin() 这样的函数只是函数,不是某个对象的方法。您无需创建它,通过把 Math 作为对象使用就可以调用其所有属性和方法。
Math对象的常用属性和方法:
属性/方法 |
说 明 |
Math.E |
自然对数的底数e |
Math.LN10 |
10的自然对数 |
Math.LN2 |
2的自然对数 |
Math.LOG10E |
以10为底的e的对数 |
Math.LOG2E |
以2为底的e的对数 |
Math.PI |
圆周率 |
Math.SQRT1_2 |
2的平方根的倒数 |
Math.SQRT2 |
2的平方根 |
Math.abs(x) |
返回数的绝对值。 |
Math.ceil(x) |
返回大于等于x的最小整数 |
Math.exp(x) |
返回 e 的指数。 |
Math.floor(x) |
返回小于等于x的最大整数 |
属性/方法 |
说 明 |
Math.log(x) |
返回数的自然对数(底为e)。 |
Math.max(x,y,..) |
返回一组数的最大值 |
Math.min(x,y,..) |
返回一组数的最小值 |
Math.pow(x,y) |
返回x的y次幂 |
Math.random() |
返回 0 ~ 1 之间的随机数。 |
Math.round(x) |
把数四舍五入为最接近的整数。 |
Math.sqrt(x) |
返回数的平方根 |