引用类型的值(对象)是引用类型的实例。ECMAScript提供了很多原生引用类型,如Object
Object 类型
创建一个对象:
var person=new Object();person.name="xiaohong";person.age=12;可以使用对象字面量来简写:
var person={ name:"xiaohong", age:12};属性名也可以用字符串,没什么区别。
创建对象时,也可以留空花括号:
var person={}; //与 var person=new Object(); 含义相同,只包含默认属性和方法可以用方括号来表示访问属性,属性名需要字符串表示,也可以用变量代替:
var person=new Object();
person["name"]="xiaoming"; //和person.name="xiaoming"是一个意思
var m="name";
alert(person[m]);Array 类型
数组中每一项可以是不同的数据类型值。
创建一个数组:
var colors1=new Array();
var colors2=Array(); //可以省略new
var colors3=Array(3); //创建含3项的数组
var colors4=Array("xiao") //创建一个包含一项""xiao"。非数值时为具体项数可以使用数组字面量来简写:
var colors=["green","bule","black"];
var colors1=[]; //空数组
var colors2=[,,,] //不推荐,每一项都是undefined值读取和设置数组可以:
var colors=["green","bule"];
alert(colors[0]); //读取第一项
colors[1]="red"; //修改第二项
colors[3]="black" //新增2项,其中一项为undefined数组项数保存在length属性中。length不是只读的,可以通过设置这个属性,在末尾新增或者去除项数。
var colors=["red","bule","green"];colors.length=2; //去掉末尾项alert(colors[2]); //undefcolors[colors.length]="yellow"; //末尾新增一项alert(colors[2]); //yellow当把一个值放在超出数组大小的位置上时,数组就会重新计算其长度,即长度为索引加1。中间空的值为undefined。
检测数组
对于单个网页可以用 value instanceof Array
对于多个网页可以用 Array.isArray()方法:Array.isArray(value)
转化方法
每个对象都有toString()、toLocaleString()、toValue()方法。转化不影响原本的数组。
一般情况下数组会每一项都调用toString(),返回的是拼接成一个以逗号为分隔符的字符串。
toLocaleString()和toString()差不多,只是每一项调用的是toLocaleString()方法。
toValue()方法返回的还是数组。
join()方法可以使用不同的分隔符构建字符串。在没有接受参数或者参数为undefined的情况下默认为逗号。
alert()会自动转型为字符串。
var person1={ toString:function(){ return "nihao"; }, toLocaleString:function(){ return "xwt"; }};var person2={ toString:function(){ return "nihao11"; }, toLocaleString:function(){ return "xwt11"; }};var person=[person1,person2];alert(person); //nihao,nihao11alert(person.toString()); //nihao,nihao11alert(person.toLocaleString()); //xwt,xwt11alert(person.join("||")); //nihao||nihao11栈方法
后进先出,末端操作。执行了便会修改原来数组。
push()方法:接收任意数量的参数,逐个添加到数组末尾,并返回修改后数组长度。
pop()方法:从数组末尾移除一项,并返回移除项。
队列方法
先进先出,首尾操作。执行了便会修改原来数组。用push()末尾增加项。这里列出两种前端操作方法。
shift()方法:移除数组中第一项,并返回该项。
unshift()方法:在数组前端添加项,并返回修改后的数组长度。
重排序方法
会改变原数组,返回的是经排序后的数组
reverse()方法:反转数组。
sort()方法:将数组中每一项转化为字符串比较大小后,按升序排列。也可以自己写个函数,作为参数,自定义比较规则,函数中交换返回正数,不交换负数,相等0。
function compare(value1,value2){ if(value1>value2){ return 1; } else if(value2>value1){ return -1; } else{ return 0; }}var array=[1,15,10,5];array.sort(compare);console.log(array); //[1,5,10,15]操作方法
concat()方法:不影响原数组。创建一个新的数组副本。参数可以是数组或者数组项。
var xwt=["ni","shi"],xwtCopy=xwt.concat(":",["sha","bi"]);alert(xwt); //ni,shialert(xwtCopy); //ni,shi,:,sha,bislice()方法:不影响原数组。基于当前数组,创建一个新数组。参数分别为起始和结束位置(返回的项不包括结束位置的项)。只有一个参数时,表示起始位置至末尾所有项。
如果参数中有负数,则实际为各自加上数组长度。起始位置大于结束位置则返回空数组。
var xwt=["ni","shi","da","sha","zi"];var xwtc=xwt.slice(0,2);var xwtCopy=xwt.slice(2);alert(xwt); //ni,shi,da,sha,zialert(xwtc) //ni,shialert(xwtCopy) //da,sha,zisplice()方法:会改变原数组。splice(起始位置,删除的项数,[插入项])。返回删除的项组成的数组,如果没删除,则为空数组。注意插入项插在起始位置前面。
var xwt=["ni","shi","da","sha","zi"];var a=xwt.splice(0,2); //da,sha,zialert(xwt); //ni,shialert(a);xwt.splice(1,0,"ge","da","da"); alert(xwt); //da,ge,da,da,sha,zi 插在起始位置前位置方法
indexOf():返回查找的项在数组中的位置。从头查找
lastIndexOf():返回查找的项在数组中的位置。从尾巴查找
都接收两个参数:要查找的项和可选的起始查找位置。找不到时,返回-1。
迭代方法
每个方法都接受2个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象。
函数会接收三个参数:数组项的值、该项在数组中对应的位置、数组对象本身,需要返回的必须要return。
every():运行每一项都true,则返回true。
some():运行每一项,有一项是true,则返回true。
filter():运行每一项,返回结果是true项组成的数组。
map():运行每一项,返回处理结果组成的数组。
forEach():运行每一项,没返回值。类似for循环。
以上方法都不会改变数组中包含的值。
var arr=[1,5,9,7,9,8];var num=0;var erverArray=arr.every(function(item,index,array){ return item>2;});var someArray=arr.some(function(item,index,array){ return item>2;})var filterArray=arr.filter(function(item,index,array){ return item>2;});var mapArray=arr.map(function(item,index,array){ return item+2;})arr.forEach(function(item,index,array){ num+=1;})console.log(erverArray); //falesconsole.log(someArray); //trueconsole.log(filterArray); //[5, 9, 7, 9, 8]console.log(mapArray); //[3, 7, 11, 9, 11, 10]console.log(num); //6归并方法
reduce()方法:参数一个可选的每一项上都调用的函数和一个初始值。参数函数会接受4个参数:前一个值、当前值、项的索引、数组对象。这个函数返回的任何值会作为第一个参数传给下一项。
reduceRight()方法:从数组尾部往前遍历,其他和reduce()方法一样。
使用reduce()求和例子如下:
var arr=[1,5,9,7,9,8];var num=arr.reduce(function(pre,cur,index,array){ return pre+cur;},1);alert(num); //40reduce()第二个参数省略时,第一次迭代发生在数组第二项,否则pre为初始值,cur为数组第一项。
Date 类型
创建一个日期对象:
var now=new Date(); //调用构造函数不传参数的情况下,会自动获得当前时间Date.parse()方法:能接受表示日期的字符串参数,返回一个创建的日期。参数格式有:
- ”月/日/年“——"5/7/2020"
- 英文月名 日,年——"May 7,2004"
- 英文星期 英文月名 日 年 时:分:秒 时区——"Tue May 7 2020 11:29:32 GTM-0700"
- ISO 8601扩展格式 YYYY-MM-DDTHH:mm:ss:sssZ——"2020-05-07T11:29:32"
构造函数Date()能根据接受的参数,省略Date.parse()和Date.UTC()。
var date1=new Date();var date2=new Date(Date.parse("5/7/2020"));var date3=new Date(Date.UTC(2020,4,7));var date4=new Date(2020,4,7);
//以上值都为:Thu May 07 2020 00:00:00 GMT+0800 (中国标准时间)Date.now()方法:返回调用这个方法时的时间毫秒数。
var arr=[1,2,3,4,5,6];var start=Date.now();arr.reduce(function(pre,cru,index,array){ return pre+cru;},2);var stop=Date.now();alert(stop-start);继承的方法
Date类型也重写了toString()、toLocaleString()、valueOf()方法(返回日期毫秒数)。
比较日期的时候,使用valueOf()方法。
日期格式化和操作日期的一些方法:P102
日期格式化主要是转化字符串。
操作日期主要是分别获取(get)和设置(set)年 月 日 时 分 秒的一些方法。
RegExp 类型
创建一个正则表达式:
var expression=new RegExp("[bc]at","i")字面量:
var expression=/ pattern / flags;正则的字面量和RegExp()构造函数创建的不一样。字面量会共享一个实例,而构造函数创建的每个实例都是新实例。P105
exec()方法:接受一个参数,即要应用的字符串,返回包含第一个匹配项信息的数组,没有的情况下返回null。数组第一项为整个模式匹配的字符串,其他项为捕获项。如果没有捕获项,则数组只有一项。不是全局模式,每次调用返回的都是第一个匹配项。全局模式,每次调用都是返回下一个匹配项。
test()方法:只接受一个字符串参数。可以用来验证用户输入的内容是否与某个模式匹配。
转字符串都是返回对象的字面量表达,与创建方式无关。
Function 类型
每个函数都是Function类型的实例,都有与其他引用类型一样的具体属性和方法。
声明一个函数对象:
function sum(sum1,sum2){ return sum1+sum2;}用函数表达式创建:
var sum=function(sum1,sum2){ return sum1+sum2;};用函数表达式声明要注意}后面的逗号。
也可以用new Function()构造函数创建。
函数声明和函数表达式唯一的区别是:解析器会率先读取函数声明,并使其在执行任何代码之前可用。至于函数表达式,必须等到解析器执行它所在的代码行。
函数名是指针,使用不带圆括号的函数名是访问指针,而非调用函数。
作为值的函数
函数名本身就是变量,可在函数中把另一个函数作为参数传入。
function callSomeFunction(someFuction,obj){ return someFuction(obj);}function sum(sum1){ return sum1+2;}var result=callSomeFunction(sum,2);console.log(result); //4函数为引用数据类型可以作为值,当然也可以从一个函数中返回另一个函数。
function compareObject(property){ return function(obj1,obj2){ if (obj1[property]>obj2[property]){ return -1; } else if(obj1[property]<obj2[property]){ return -1; } else{ return 0; } }}var data=[{name:"nihao",age:12},{name:"w",age:13},{name:"hh",age:14}];data.sort(compareObject("age"));console.log(data); //按年龄降序排列函数内部属性
函数内部有两个特殊对象(内部的属性类似于在函数里自己var一个,作用域来说只能在函数内使用):
- arguments类数组对象,保存传入的参数。arguments中有个callee属性指向函数(指针指向函数,便可以用这个属性调用函数)。
- this:指向的是执行这个函数的环境对象(不是函数本身的活动对象,是它作用域链下一级。所有引用类型的对象,对可看成变量对象)
- caller:保存着调用当前函数的函数引用。
function outer(){ inner();}function inner(){ alert(inner.caller); //返回outer()方法}outer();函数的属性和方法
和函数内部的属性不同,这个是继承Functione类型的。
- length:表示希望接收的命名参数个数。
- prototype:对于引用类型而言,是保存它们所有实例方法的所在,例如valueOf()等实际保存在这个属性中,只是通过实例访问罢了。
- apply()、call():非继承的方法。用来在特定的作用域中调用函数(运行了函数),实际上等于设置函数内的this值。接受两个参数:一个是运行函数的作用域;两个方法唯一的区别是,apply()的另一个参数是数组,call()的另一个参数必须一一罗列出来。减少了代码的耦合,不用非得放到一个对象中this才能指代该对象。
var o={color:"blue"};var color="red";function bd(){ return this.color; }alert(bd()); //redalert(bd.call(o));//blue
alert(bd.apply(o));//blue- bind():创建一个函数的实例,其this会被绑定到传给bind()的值。
var o={color:"blue"};var color="red";function bd(){ return this.color; }alert(bd()); //redvar bd2=bd.bind(o);alert(bd2());//blue- toString()、toLocaleString()会返回函数的代码,每个浏览器不一样。
基本包装类型
有了它,能像操作对象一样操作基本数据类型。
Number、Boolean、String三个特殊的引用类型是对于基本数据类型设计的。因为基本数据类型不是对象,值不能进行操作,但事实上我们能操作。如:
var s1="some text";
s2=s1.substring(2);为什么能操作呢,起始读取访问时,系统后台会完成以下处理:
var s1=new String("some text");
var s2=s1.substring(2);
s1=null;一般的引用类型与基本包装类型的最大区别:使用new创建的引用类型的实例,在执行流离开当前作用域时,一直保存在内存中。而自动创建的基本包装类型对象,只存在于代码执行的一瞬间,然后立即被销毁。
不在绝对必要的情况下,不要显示地调用基本包装类型创建对象,容易和基本数据类型弄混。
Object()构造函数也会像工厂模式一样,根据传入值的类型返回相应基本包装类型的实例:
var str=new Object("nihaoa");alert(str instanceof String); //true要注意调用new创建对象和转型函数是有区别的:
var value="23";var num=new Number(value);alert(typeof num); //objectvar num1=Number(value);alert(typeof num1);//numberBoolean 基本包装类型
建议永远不要使用Boolean对象,容易混淆。特别是&&、||操作符中。
Number 基本包装类型
- toString()方法:可带一个参数,设置进制转化为字符串。
- toFixed()方法:按照指定的小数位数返回数值的字符。能够自动舍入的特性,方便处理货币。
var num=12.008;alert(num.toFixed(2)); //12.01toExponential():按照指定的小数位数返回指数表示法的字符串。
String 基本包装类型
这里的方法操作完,原字符串都不变,都是创建新的字符串。这与对象,数组不一样,数组concat()和slice()是创建副本,还有迭代、归并方法不变,其他都改变原数组。对象要体现可便,基本类型体现不可变。
也可以用方括号加索引来访问其中的字符。
- length属性:字符串中包含多少个字符。
- charAt():参数为位置的数字,返回一个字符
- charCodeAt():参数为位置的数字,返回这个字符的编码
②字符串操作方法:都不影响原字符串:
- concat():与数组中的类似。将一个或多个字符串拼接起来,返回拼接后的字符串。(事实上,字符串拼接一般用+)
- slice():与数组中的类似。返回起始位置至结束位置的字符串,不包含结束位置。参数为负数时,都加上字符串长度
- substring():正数时,和slice()用法一样。负数时,第一个参数加字符串长度,第二个转换为0。
- substr():第一个参数为起始位置,第二个参数是取字符的个数。参数为负时都转换为0。
- indexOf():从前往后找,返回位置,没找到返回-1.。第二个参数可以指定从哪个位置开始找。
- lastIndexOf():从后往前找,返回位置,没找到返回-1。第二个参数可以指定从哪个位置开始找。
- trim():创建一个字符串副本,删除前缀和后缀所有空格。
var s=" 你好 啊 ";alert(s); //" 你好 啊 "alert(s.trim()); //"你好 啊"⑤字符串大小写转换方法,不改变原字符串:
- toLowerCase():转换为小写。
- toUpperCase():转换为大写。
- toLocaleLowerCase()和toLocaleUpperCase()分别是针对地区的大小写转化。在不知道地区的情况下,用这个更靠谱。
⑥字符串的模式匹配方法,不改变原字符串:
- match():和regExp的exec相同。只接受一个参数:regExp对象或者正则表达式。
var ptest="cat,bat,gat";var reg=/.at/g;console.log(ptest.match(reg)); //["cat", "bat", "gat"]console.log(reg.exec(ptest)); //["cat", index: 0, input: "cat,bat,gat", groups: undefined]- search():参数和match()相同,返回字符串中第一个匹配项的索引,没找到就返回-1。
- replace():替换子字符串。第二个参数也可以是函数,使用更加灵活。
var s="cat,bat,sat";var s1=s.replace("at","ond");var s2=s.replace(/at/g,"ond");console.log(s); //cat,bat,satconsole.log(s1); //cont,bat,satconsole.log(s2); //cond,bond,sond- split():用指定的分隔符,将字符串分割成多个字符串,放入数组中,返回一个数组。第二个参数,可以用于指定数组的大小。
var ha="cat,ni,mie,m";console.log(ha.split(",")); //["cat", "ni", "mie", "m"]⑦localeCompare()方法
- localeCompare():用于比较两个字符串。大的情况下返回正数,相等返回0,小的时候返回负数。由于具体返回值不确定,可以这样用来约束返回值:
var stringvalue="nihao";function compareStr(text){ var result=stringvalue.localeCompare(text); switch(true){ case result> 0: return 1; break; case result<0: return -1; break; default:return 0; }}alert(compareStr("hh")); //1⑧formCharCode()方法
- formCharCode:String的构造函数本身的方法,接收一或多个字符编码,然后将他们转化为字符串。
alert(String.fromCharCode(104,101,108,108,111));//hello单体内置对象
内置对象:不依赖宿主环境的对象,这些对象在程序执行之前就已经存在了。开发人员不必显式的实例化内置对象。前面已经介绍了很多内置对象,如Object、Aarry、String。ECMAScript还定义了两个单体内置对象Global和Math。
Global 对象
所有在全局中定义的函数和变量,都是Global的属性。
①URL编码函数
- encodeURL():编码整个url,只把空格转化为%20。对应的解码函数decodeURL()。
- encodeURLComponent():所有的特殊符号都会编码,所以一般只用于编码最后一段。对应的解码函数decodeURLComponent()。
②eval()函数
- eval():会将传入的参数当作ECMAScript语句来执行。非严格模式下,和平时写代码没什么区别,但是里面创建的任何变量和函数都不会被提升,它们只在eval()执行的时候创建。严格模式下,外部不能访问eval()中定义的变量。
eval("alert('nihao')"); //就是弹出"nihao"弹出框如特殊值undefined、NaN、infinite都是Global的属性,构造函数Object等都是Global属性。
注:永远不要给特殊值赋值。
window对象:web浏览器都是将这个全局对象作为window对象的一部分。因此在全局作用域中声明的所有变量和函数,都成了window对象的属性。
/** 用立即执行函数表达式来获取Global对象。在浏览器中也是window对象*/var global=function(){ return this;}(); Math 对象
保存数学公式信息的公共位置。
①Math属性:p134
②max()、min()方法:确定一组数中的最大最小值。一般用于避免多余的循环或者在if语句中确定最小最大值。var math=Math.min(12,34,89,23);alert(math); //12要在数组中找到最小最大值,可以如下使用:
var values=[1,2,3,4,5]var max=Math.max.apply(Math,values); //这里很好的使用了apply()方法的传参功能③舍入方法
- Math.ceil():向上舍入为整数。
- Math.floor():向下舍入为整数。
- Math.round():四舍五入为整数。
random():返回大于等于0,小于1的一个随机数。
/**取两个数区间的随机整数*/function selectForm(lowerValue,upperValue){ var choice=upperValue-lowerValue+1; return Math.floor(Math.random()*choice+lowerValue);}alert(selectForm(2,10));var color=["red","green","yellow"];var form=color[selectForm(0,color.length-1)]; //随机返回数组中一项⑤一些不太用的方法:P136