Array类型
ECMAScript数组中每一项都可以保存任何类型的数据且大小可以动态调整(随着数据的添加自动增长以容纳新的数据)。即第一位置存字符串,第二位置存值,第三个存对象等。
创建数组两种方式:使用数组字面量 [] 创建新数组,除非想要创建的是指定长度的数组。
一、用Array构造函数。
var arr=new Array();参数可以代表数组大小,还可以代表应包含的数据项。New也可以省略。
二、使用数组字面量表示法。由一对包含数组项的方括号表示,多个项用逗号隔开。
var arr1=[“lisi”,20];
取值时:arr[下标数字],可以设置、修改、替换、新增数组项的值。Length属性不是只读的。可以用length属性为数组末尾添加新项。
检测数组-某个对象是不是数组---instanceof
if(value instanceof Array){//对于网页,或者全局作用域而言
//对数组执行某些操作
}
确定某个值是不是数组,不管在哪个全局执行环境中创建的。
if(Array.isArray(value)){
//对数组执行某些操作
}
转换方法
所有对象都有toLocalString()、toString()和valueOf()方法。
toString()会返回由数组中每个值的字符串形式拼接成的一个以逗号隔开的字符串。
valueOf()返回的还是数组。
toLocalString()常返回与toString和valueOf方法相同的值。
join():接受一个参数,及用做分隔符的字符串,返回包含所有数组项的字符串
栈方法—栈(后进先出都是在栈顶进行操作)
ECMAScript为数组专门提供了push()和pop()方法,以便实现类似栈的行为。
push():接受任意数量的参数,把他们逐个加到数组末尾,并返回修改后数组长度。
pop():从数组末尾移除最后一项,减少数组length值,返回移除的项。
队列方法---(先进先出,列表末尾添加,列表头部删除)
push():就是从末尾添加数据
shift():移除数组第一项并返回该项,同时将数组长度减1
unshift():在数组前端添加任意个项并返回新数组长度。
重新排序方法
reverse():反转数组项的顺序。
sort():按升序排列数组项。(默认调用每个数组项的tostring方法,然后比较得到字符串在排序)。比较的是字符串,比如结果0,1,10,15,5。
Sort也可以接受一个比较函数作为参数,指定哪个值位于哪个值前面。
操作方法
concat():基于当前数组中所有项创建一个新的数组。原来数组不变
无参:返回原来数组的拷贝
有参:参数为数组,直接添加到原来数组里面,字符串,添加导师数组后面。
slice():基于当前数组中一个或多个创建一个新数组。接受一个或两个参数,即要返回项的其实和结束位置。一个参数,返回从指定位置开始到当前数组末尾的所有项。Slice也不会影响原来数组。
splice():向数组中部插入项。,始终返回一个数组。
删除:删除任意数量项。指定两个参数,要删除项的第一个位置和删除的个数。
插入:向指定位置插入多个项。三个参数,起始位置,0(要删除的项),要插入的项。如果要插入多个项可以在传入第四、五任意多项。splice(2,0,”red”,”green”);从当前数组位置2开始插入字符串red和green。
替换:向指定位置插入任意数量项,且删除任意数量项,3个参数:起始位置、要删除的项数、要插入的任意数量的项。插入和删除项数不必相等。Splice(2,1,”red”,”green”)删除当前数组位置的第二项,然后再从位置2开始插入字符串red和green
位置方法
indexOf()、lastIndexOf()都接受两个参数:要查找的项和(可选的)查找起点位置的索引。
indexOf()从数组开头向后查找,lastIndexOf()从数组末尾开始向前查找。
都返回要查找的项在数组中的位置,或在没找到下返回-1.会使用===全等
迭代方法-5个迭代方法(每个都接受两个参数:要在每一项运行的函数和(可选的)运行该函数的作用域对象---影响this的值)。
传入这些方法中的函数会接受三个参数:数组项的值、该项在数组中的位置和数组对象本身。根据方法不同,函数返回值可能也不相同。
下面前提都是对数组中每一项运行给定函数
every():如果该函数对每一项都返回true,则返回true。
filter():返回该函数会返回true的项组成的数组。
forEach():这个方法没有返回值。
map():返回每次函数调用的结果组成的数组。
some():如果函数对任一项返回true,则返回true。
Every和some比较相似,都是查询是否满足某种条件。
归并方法
reduce()和reduceRight()都会迭代数组的所有项,构建一个最终返回的值。都会接受两个参数:在每一项上调用函数和(可选的)作为归并基础的初始值。传给reduce和reduceRight的函数接受4个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项,因此第一个参数是数组的第一项,第二个参数是数组的第二项。
reduce()方法从数组中第一项开始遍历到最后。
reduceRight()方法从数组最后一项开始向前遍历到第一项。
var value=[1,2,3,4];
var sum=value.reduce(function(prev,cur,index,array){
return prev+cur;
});//10
Date类型
创建一个日期对象,使用new操作符和Date构造函数,如下:
varnow=new Date();
不传参的话,自动获取当前日期时间。如果要根据特定日期和时间创建日期对象,必须传入该日期的毫秒数(从1970年计算)。ECMAScript提供了两个方法简化这一计算过程:Date.parse()和Date.UTC();
Date.parse()接受一个表示日期的字符串参数,尝试根据这个字符串返回相应日期的毫秒数。格式因实现、地区而异。
将地区设置为美国浏览器通常接受下列日期格式:
月/日/年,如6/13/2014;
英文月名 日,年,如January 7,2016
英文星期几 英文月名 日 年 时:分:秒 时区,如 Tue May 25 200400:00:00 GMT-0700
ISO8601扩展格式 YYYY-MM-DDTHH:mm:ss:sssZ(如:2004-05-25T00:00:00)
ECMAScript实现支持这种格式
如:var someDate=new Date(Date.prase(“May 25, 2004”))
VarsomeDate=new Date(“May 25, 2004”)
上面两个等价,如果直接传参给Date构造函数,会在后台调用Date.prase()
Date.UTC()方法同样返回日期的毫秒数。它与Data.parse()构建时使用不同的信息。
Date.UTC()参数分别是年份、基于0的月份(0-11)、月中哪一天(1-31)、小时(0-23)、分钟、秒、及毫秒数。只有年和月前两个是必须的。天数没提供就为1,其他为0。基于本地时区计算
vars=new Date(Date.UTC(2000,0));//2000年1月1日凌晨
var s1=newDate(Date.UTC(2000,4,5,15,11,11));//2000年5月5日下午3:11:11
vars=new Date(2000,0);
vars1=new Date(2000,4,5,15,11,11);
ECMAScript添加了Date.now()方法,返回表示调用这个而方法的日期和时间的毫秒数。
继承的方法
Date类型也重写了toLocalString(),toString()和valueOf()方法;
Date类型的toLocalString方法会按照与浏览器设置的地区相适应的格式返回日期和时间。时间格式中会包含AM或PM,但不会包含时区信息;
toString方法返回带有时区信息的日期和时间,时间一般以军用时间(0-23)表示。
日期格式化方法—格式化为字符串
toDateString():以特定于实现的格式显示星期几、月、日和年;
toTimeString():以特定于实现的格式显示时、分、秒和时区;
toLocalDateString():以特定于地区的格式显示星期几、月、日和年;
toLocalTimeString():以特定于实现的格式显示时、分、秒;
toUTCString():以特定于实现的格式完整的UTC日期
toGMTString():与上面一个等价,在于向后兼容,推荐使用前者。
日期时间组件方法
getTime:日期毫秒数,与valueOf方法值一样。
getFullYear:取得4位数的年份
setFullYear:设置4位数的年份
getMonth:返回日期中月份
setMonth:设置日期的月份
getDate:返回日期月份中的天数
setDate:设置日期月份中天数,超过该月中天数,则增加月份(从1开始,其他都是从0开始)
getDay:返回日期中星期的星期几
getHours:返回日期中小时数
setHours:设置日期中小时数
getMinutes:返回日期中分钟数
setMinutes:设置日期中分钟数
getSeconds:返回日期中的秒数
setSeconds:设置日期中秒数
getMilliseconds:返回日期中毫秒数
setMilliseconds:设置日期中毫秒数
getTimezoneOffset:返回本地时间与UTC时间相差的分钟数。
RegExp类型
ECMAScript通过RegExp类型支持正则表达式。
varexpression = / pattern / flags ;
pattern可以是任何简单或复杂的正则表达式,可包含字符类、限定符、分组、向前查找以及反向引用。
flag:每个正则表达式都可以带一个或多个标志标明表达式的行为。
g:表示全局模式,模式被应用于所有字符串,而非发现第一个就立即停止;
i:表示不区分大小写模式,确定匹配项忽略模式与字符串的大小写;
m:表示多行模式,到达一行文本尾时还继续查找下一行时候存在于模式匹配的项。
字面量形式定义正则表达式
例如:var pattern1=/at/g;//匹配字符串所有at的实例
var pattern2=/[bc]at/i;//匹配第一个bat或cat,不区分大小写。
构造函数创建正则表达式
var pattern3=new RegExp(“[bc]at”,”i”);//与pattern2相同只不过是用构造函数创建的。
RegExp实例属性
global:布尔值,是否设置了g标志
ignoreCase:布尔值,是否设置了i标志
multiline:布尔值,是否设置了m标志
lastIndex:整数,开始搜索下一个匹配项的字符位置,从0算
source:正则表达式的字符串表示,按照字面量形式而非传入构造函数的字符串模式返回。
通过这些属性:可知一个正则表达式的各方面信息,却没有多大用处。
RegExp实例方法
exec():为捕获组而设计。接受一个参数,即要应用模式的字符串,返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回null。返回的数组虽然是Array的实例,但包含两个额外属性:index(表示匹配项在字符串的位置)和input(应用正则表达式的字符串)。数组中,第一项:与整个模式匹配的字符串,其他项是与模式中捕获组匹配的字符串(若模式没有捕获组,则该数组只包含一项)。
test():接受一个字符串参数。在模式与该参数匹配情况下返回true;否则返回false。
var text = "000-00-0000";
var pattern = /\d{3}-\d{2}-\d{4}/;
console.log(pattern.test(text));
RegExp构造函数属性
构造函数包含一些属性,适用于作用域中所有正则表达式,并基于所执行的最近一次正则表达式操作而变化。属性另一个独特处:还可以通过两种方式访问他们(属性分别有一个长属性名和一个短属性名)。
Function类型
函数实际上是对象。每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。函数通常使用函数声明语法定义。
function sum (num1, num2){
returnnum1 + num2;
}//函数定义
var sum=function(num1, num2){
returnnum1 + num2;
};//函数表达式
function构造函数定义函数:最后一个参数是函数体,不建议使用,但是可以理解函数是对象,函数名是指针。
varsum = function(“num1”, “num2”, “return num1 + num2” );
由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没什么不同。一个函数可能会有多个名字
eg:
function sum(num1, num2){
return num1 + num2;
}
console.log(sum(2,3));
var sum1=sum;
console.log(sum1(3,4));
sum=null;
console.log(sum1(2,7));
console.log(sum(2,5));
函数没有重载
function sum(){
return arguments[0]+10;
}
function sum(){
return arguments[0]+100;
}
var sum = function (){
return arguments[0]+10;
};
sum = function (){
return arguments[0]+100;
};
实际上在创建第二个函数时,覆盖了引用第一个函数的变量sum
函数声明与函数表达式
解释器在向执行环境中加载数据时,对函数声明与函数表达式并非一视同仁。
解释器会率先读取函数声明,并使其在执行任何代码之前可用(可用访问);
函数表达式:必须等到解释器执行到它所在的代码行,才会被正确的解释执行。
console.log(sum(1,3)); function sum(num1, num2){ return num1 + num2; }//可以
因为在代码开始执行前,解释器就已经通过一个名为函数声明提升过程,读取并将函数声明添加到执行环境中。在对代码进行求值是,js引擎在第一遍会声明函数,并将它们放到源代码树的顶部。所以,即使声明函数的代码在调用代码后,js引擎也能把函数声明提升到顶部。
console.log(sum(1,3)); var sum = function (num1, num2){ return num1 + num2; };//运行会报错
函数位于一个初始化语句中,而不是一个函数声明。即执行到函数所在语句前,变量sum不会保存对函数的引用;而且,由于第一行代码会导致unexpected identifier(意外标识符)错误,实际上也不会执行到下一步。
作为值的函数
ECMAScript函数名本身就是变量,所以函数也可以作为值来使用。不仅可以把一个函数作为传递参数传给另外一个函数,也可以将一个函数作为另一个函数的结果返回。
function callSomeFunction(someFunction, someArgument){ return someFunction(someArgument); } function add10(num){ return num + 10; } var result1=callSomeFunction(add10,10); console.log(result1); function getGreeting(name){ return "hello, " + name; } var result2=callSomeFunction(getGreeting,"zhangsan"); console.log(result2);
比如上面要访问函数的指针,而不执行函数的话,比如去掉函数名称后面的那对圆括号,因此上面传递的是add10和getGreeting而不是执行他们之后的结果。
函数的内部属性
函数内部有两个特殊对象:arguments(类数组对象,包含着传入参数中所有参数,主要用来保存函数参数,但是这个对象还有个callee属性(属性是一个指针,指向拥有这个arguments对象的函数))和this。
this与java中类似。this引用的是函数数据以执行的环境对象----或者也可以说是this值(当在网页全局作用域中调用函数时,this对象引用的就是window)。
window.color = "red"; var o = { color: "blue" }; function sayColor() { console.log(this.color); } sayColor();//red o.sayColor = sayColor; o.sayColor();//blue
ECMAScript规范了另一个函数对象的属性:caller(保存着调用当前函数的函数的引用,如果在全局作用域中调用当前函数,它的值为null)
函数属性和方法
ECMAScript函数也是对象,因此函数也有属性和方法。每个函数都包含两个属性:
length:表示函数希望接受的命名参数的个数。如下:
function sayName(name) { console.log(name); } function sum(sum1, sum2) { return sum1 + sum2; } function sayHi() { console.log("hi"); } console.log(sayName.length);//1 console.log(sum.length);//2 console.log(sayHi.length);//0
prototype:对于ECMAScript中引用类型,prototype保存他们所有实例方法的真正所在。即如toString和valueOf等方法实际上都保存在prototype名下,只不过是通过各自对象的实例访问。在创建自定义引用类型以及实现继承时,prototype属性很重要。在ECMAScript中prototype属性不可枚举,使用for-in无法发现。
每个函数都包含两个非继承而来的方法:apply()和call()。用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。首先apply方法接受两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是Array的实例,也可以是arguments对象。在哪调用this就是代表哪个环境对象。
call和apply方法作用相同。区别在于接受参数方式不同。对于call方法,第一个参数this值没有变,变得是其余参数都直接传递给函数。换句话说,在使用call方法时,传递给函数的参数必须逐个列举出来。
function sum(num1,num2){
return num1 + num2;
}
functioncallSum1(num1, num2){
return sum.apply(this, arguments); // 传入arguments 对象
}
functioncallSum2(num1, num2){
return sum.apply(this, [num1, num2]); // 传入数组
}
alert(callSum1(10,10));//20
alert(callSum2(10,10)); //20
function sum(num1,num2){
return num1 + num2;
}
function callSum(num1,num2){
return sum.call(this, num1, num2);
}
alert(callSum(10,10)); //20
bind():方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。
基本包装类型
ECMAScript还提供了三个特殊的应用类型:Boolean、Number、String,这些类型和其他引用类型相似,但也具备与各自基本类型相应的特殊行为。实际上每读取一个基本类型值时,后台就会创建一个对应的基本包装类型的对象,可以调用一些方法来操作这些数据。
vars1=“some text”;
vars2=s1.substring(2);
引用类型与基本包装类型主要区别就在对象的生存期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型对象则存在一行代码的执行瞬间,然后立即被销毁。意味着不能在运行时为基本类型添加属性和方法。
var s1 ="some text";
s1.color ="red";
alert(s1.color);//undefined
Object构造函数会向工厂方法一样,根据传入值的类型返回相应基本包装类型的实例。
如:var obj =new Object(“some text”);
console.log(objinstanceof String);//true
new调用基本包装类型构造函数与直接调用同名的转型函数是不一样的。
var value = "25";
var number = Number(value); //转型函数
alert(typeof number); //"number"
var obj = new Number(value); //构造函数
alert(typeof obj); //"object"
Boolean类型—建议永远不要使用Boolean对象
Boolean类型是与布尔值对应的引用类型
创建Boolean对象,可以像下面调用Boolean构造函数并传入true或false
varbooleanObject = new Boolean(true);
Boolean类型的实例重写了valueOf方法,返回基本类型值true或false;
重写了toString方法返回字符串“true”和“false”。
布尔表达式中所有对象都会被转换true。
var falseObject = new Boolean(false);
var result = falseObject && true;
alert(result); //true
var falseValue = false;
result = falseValue && true;
alert(result); //false
Number类型—Number是与数字值对应的引用类型。要创建Number对象,可以在调用Number构造函数时向其中传递相应的数值。不建议实例化。
var numberObject = new Number(10);
同样Number类型重写了valueOf方法、toLocalString方法、toString方法。
除了继承的方法以外,Number类型提供了将数值格式化为字符串的方法。
toFixed(4),4表示显示几位小数。范围0-20
toExponential(),返回以指数表示法,表示的数值的字符串形式。也接受一个参数,指定了输出结果中的小数的位数。
toPrecision(),返回固定大小格式,也可能返回指数格式;具体看哪种格式合适,接受一个参数,表示数值的所有数字的位数(不包括指数部分)
String类型—String类型是字符串的对象包装类型,可以使用String构造函数来创建
var stringObject = newString(“hello,world”);
String对象的方法也可以在所有基本的字符串值中访问到。其中继承的valueOf和toLocalString和toString方法,都返回对象所表示的基本字符串值。
String类型的每个实例都有一个length属性,表示字符串包含多少个字符。
字符方法
charAt和charCodeAt方法,都接受一个参数,基于0的字符位置。
var stringValue = "hello world";
alert(stringValue.charAt(1)); //"e"以单字符字符串的形式返回给定位置的字符
var stringValue = "hello world";
alert(stringValue.charCodeAt(1)); //输出"101"得到的不是字符,是字符编码。
还可以使用方括号加数字索引来访问字符串中特定字符
var stringValue = "hello world";
alert(stringValue[1]); //"e"
都不会改变原来字符串的值 |
字符串操作方法
concat():将一或多个字符串拼接起来,返回拼接得到的新的字符串。
基于子字符串创建新字符串方法:
slice()、substr()、substring()都会返回被操作字符串的一个子字符串,而且也都接受一个或两个参数。第一个参数指定子字符串的开始位置,第二个参数(若有指定)表示子字符串到哪里结束。如果没有指定第二个参数,则将字符串长度作为结束位置。
slice和substring第二个参数是子字符串最后一个字符后面位置;正负结果一样
substr第二个参数指定的是返回字符个数。负的话和上面不一样
字符串位置方法-从字符串中查找子字符串
indexOf、lastIndexOf从一个字符串中搜索给定字符串,然后返回子字符串的位置(找不到,返回-1)。indexOf从头开始找,lastIndexOf从尾部开始搜索。这两个函数也都可以接受可选的第二个参数,表示从字符串中哪个位置开始搜索。indexOf从指定位置向后找,lastIndexOf从指定位置向前搜索。
trim()方法
创建一个字符串副本,删除前置及后缀的所有空格,返回结果。不改变原字符串的值。
字符串大小写转换方法
toLowerCase()、toUpperCase()、toLocalLowerCase()、toLocalUpperCase()
后面两个针对特定地区实现。
字符串的模式匹配方法
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
match()方法返回了一个数组;如果是调用RegExp 对象的exec()方法并传递本例中的字符串作为参数,那么也会得到与此相同的数组:数组的第一项是与整个模式匹配的字符串,之后的每一项(如果有)保存着与正则表达式中的捕获组匹配的字符串。
search()方法参数与match相同为正则表达式。返回第一个匹配项的索引,没找到返回-1。而且是从头开始找。
replace()方法接受两个参数,第一个是一个RegExp对象或字符串,第二个参数可以使一个字符串或函数,如果第一个参数是字符串,那么会替换第一个子字符串。要想替换子字符串,就是提供一个正则表达式,且指定全局标志。
localCompare()方法—比较两个字符串,并返回下列值中一个:
如果字符串在字母表中应该排在字符串参数前,则返回一个负数(大都返回-1)
如果字符串等于字符串参数,返回0;
如果字符串在字母表中应该排在字符串参数后,则返回一个正数(大都返回1)
fromCharCode()方法—接受一或多个字符编码,然后将他们转换成一个字符串。
与charCodeAt()执行相反操作
单体内置对象
内置对象:由ECMAScript实现提供的、不依赖于宿主环境的对象,这些对象在ECMAScript程序执行前就已经存在了。不必显示实例化内置对象,因为已经实例化了。如:Object、Array、String,还有两个单体内置对象Global和Math
Global对象
Global对象不属于任何其他对象的属性和方法,最终都是它的属性和方法。事实上,没有全局变量和全局函数;所有在全局作用域中定义的属性和函数,都是Global对象的属性。isNaN()、isFinite()、parseInt()及parseFloat()实际上都是Global对象的方法。除此还包含其他方法。
URI(通用资源标识符)编码方法
Global对象的encodeURI()和encodeURIComponent()方法可以对URI进行编码,以便发送给浏览器。有效的URI中不能包含某些字符,如空格。而编码方法可以对URI进行编码,用特殊的UTF-8编码替换所有无效的字符,从而让浏览器可以接受和理解。
encodeURI对于整个URI,encodeURIComponent用于对URI中某一段进行编码,区别在于encodeURI不会对本身属于URI的特殊字符进行编码,例如冒号、正斜杠、问号和井子号;而encodeURIComponent会对它发现的任何非标准字符进行编码。
与encodeURI和encodeURIComponent相对应的两个方法分别是decodeURI和decodeURIComponent,其中decodeURI只能对使用encodeURI替换的字符进行解码。同样,decodeURIComponent()能够解码使用encodeURIComponent()编码的所有字符,即它可以解码任何特殊字符的编码。
eval()方法:像ECMAScript解析器,只接受一个参数,即要执行的ECMAScript或js字符串
eval(“alert(“hi”)”);等价于alert(“hi”);
当解析器发现调用eval方法时,会将传入的参数当做实际的ECMAScript语句来解析,然后把执行结果插入到原位置。通过eval执行的代码被认为是包含该次调用的执行环境的一部分,因此被执行的代码具有与该执行环境相同的作用域链。意味着通过eval执行的代码可以引用在包含环境中定义的变量。
在eval中创建的任何变量和函数都不会被提升,因为在解析代码的时候,他们被包含在一个字符串中,他们只在eval执行的时候创建。
Global对象的属性,undefined、NaN、Infinity都是对象的属性。所有原生引用类型的构造函数,像Object和Function都是Global对象的属性:下列是Global对象的所有属性
window对象
ECMAScript 虽然没有指出如何直接访问Global 对象,但Web 浏览器都是将这个全局对象作为window 对象的一部分加以实现的。因此,在全局作用域中声明的所有变量和函数,就都成为了window对象的属性。
Math对象
方法
min()和max()确定一组数值中最大最小值,都可以接受任意多个数值参数。
要找到数组中最大值,最小值,可以用apply方法,把math对象作为第一个参数,将任何数组作为第二个参数。
ceil:向上舍入,将数值向上舍入为接近的整数
floor:向下舍入,将数值向下舍入为最接近的整数
round:标准舍入,四舍五入
random:返回大于等于0小于1的一个随机数。
值 =Math.floor(Math.random() * 可能值的总数 + 第一个可能的值)
selectFrom:接受两个参数:应该返回的最小值和最大值。用最大值减去最小值再加1得到可能值的总数,随机取出一项。