目录
四、数据类型、内置对象
8、Array类型
属性和方法:prototype, isArray
原型对象属性、方法:constructor, join, push, pop, shift, unshift, reverse, sort, concat, slice, splice, indexOf, forEach, every, some, filter, map, reduce…
实例对象属性、方法:length
(1)创建数组
var a=new Array(); //使用Array构造函数
var b=new Array(size); //初始大小
var c=new Array(d1,d2,…,dn); //只有一个数据可能为size
var d=[d1,d2,…,dn]; //使用数组字面量表示法
ECMAScript数组的每一项可以保存任何类型的数据。
数组大小可以动态调整。设置的某个值的索引超过了数组现有项数,自动增加到该索引值+1的长度。使用length属性,可以从数组的末尾移除项或向数组添加新项。越界、未初始化均打印undefined。
(2)检测数组
确定某个对象是不是数组。
value instanceof Array,假定只有一个全局执行环境。
Array.isArray(value),不管它在哪个全局执行环境中创建。
(3)转换方法
数组转换为字符串。某一项值是null或undefined,返回空字符串。
toString(),返回由数组中每个值的字符串形式拼接而成的以逗号分隔的字符串。
valueOf(),返回数组。
数组名
join(“,”),指定分隔符。
(4)栈、队列方法
push(),将参数添加至数组末尾,多个参数用逗号分隔,修改length,返回新数组长度。
pop(),移除数组最后一项并返回该项,length-1。
shift(),移除数组第一项并返回该项,length-1。
unshift(),在数组前端添加任意项,返回新数组长度。
(5)排序方法
reverse(),反转数组,返回排序后的数组。
sort(),默认按升序排列,返回排序后的数组。
sort()方法调用每个数组项的toString()方法,比较得到的字符串,即使是数值。sort()方法可以接收一个比较函数作为参数,指定排序方法。比较函数接收两个参数,如果第一个参数位于第二个参数之前则返回一个负数,两个参数相等则返回0,如果第一个参数应该位于第二个参数之后则返回一个正数。
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);
//简化方法,对数值类型或valueOf()方法返回数值类型的对象类型
function compare(value1,value2){
return value2-value1;
}
(6)操作方法
colors.concat(“yellow”,[“red”]); 连接,返回新数组
colors.slice(1,4); 截取,取1-3,返回新数组
返回从起始位置到结束位置-1的项;只有一个参数,则至数组末尾;有负数,则与length相加;结束位置小于起始位置则返回空数组。
splice(start, deleteCount[, item1[, item2[, …]]]),从数组中删除或添加元素,并更改数组内容,返回一个数组,该数组包含从原始数组中删除的项。
var arr=["1","2","a","b","6"];
var ret=arr.splice(2,2,"3","4","5"); //["a","b"]
arr; //["1","2","3","4","5","6"]
(7)位置方法
indexOf(item[,index]),从指定位置开始从前往后查找。
lastIndexOf(item[,index]),从后往前查找,返回查找项在数组中的位置。
(8)迭代方法
有5个迭代方法,对数组中的每一项运行给定函数。不会修改数组中包含的值。
forEach():没有返回值。遍历数组元素并调用回调函数。
every():该函数对每一项都返回true,则返回true。
some():该函数对任一项返回true,则返回true。
filter():返回该函数会返回true的项组成的数组。
map():返回每次函数调用的结果组成的数组。
function logArray(value,index,array){
console.log(value);
console.log(value===array[index]);
}
[2,5,,9].forEach(logArray); //2 true 5 true 9 true
//没有空元素,Note ellision,在位置2没有值无法访问
/*
forEach(callback[, thisArg])
function callback(value, index, arrayObject){…}
在每一项上运行的函数,运行该函数的作用域对象-影响this值。
*/
(9)归并方法
reduce(function[, 初始值]),在每一项上调用的函数,作为归并基础的初始值
function f(前一个值, 当前值, 项的索引, 数组对象){…}
迭代数组所有项,构建一个最终返回值。reduce()方法从数组第一项开始,遍历至最后。reduceRight()从数组最后一项开始,遍历至第一项。该函数返回的值作为第一个参数传给下一项。
var values=[1,2,3,4,5];
var sum=values.reduce(function(prev,cur,index,array){
return prev+cur;
});
console.info(sum); //15
9、Function类型
用于定义函数或新对象的构造器。Function构造器构造的实例对象还是Function对象,仍可以被当作构造器使用,实例对象有prototype属性,可以用来生成其它对象。
原型对象属性、方法:constructor, apply, call, bind
实例对象属性、方法:length, prototype, arguments, callee, caller…
9.1 创建函数
function functionName(arg0,arg1,arg2){ //函数声明语法
//函数体
}
var functionName=function(arg0,arg1,arg2){ //函数表达式
//函数体
};
var functionName=new Function(“x”,”y”,”return x*y”); //构造函数,不推荐,影响性能
定义时不必指定是否返回值,推荐让函数返回一个值或没有返回值,不要使用return;。
解析器通过函数声明提升先读取函数声明,函数表达式则必须等到解析器执行到它所在代码行,才会被解释执行,将函数表达式写在其调用之前,否则执行期间导致错误。(对于if-else语句使用函数声明结果不可预测,但使用函数表达式没问题。)除此以外,二者的语法等价。
functionName(); //函数调用
//如果要传复杂的需要配置的参数(具体属性不可预测),通过配置对象的方式给函数提供参数
function setTeacher(configure){}
setTeacher({
name:"yaocong",
age:29
});
(function(){ //匿名函数的调用,强制运算符返回函数自身,使匿名函数自执行
})();
(function(){ //最外面的强制运算符,将其中的代码执行,返回调用结果
}());
void function(){
}();
ECMAScript函数不介意传递参数的个数和类型,命名的参数只是提供便利,但不是必须的,解释器不会验证命名参数。arguments对象(类数组对象)表示函数传递进来的实际参数,使用arguments[i]访问每个元素,使用arguments.length确定传递进来的参数个数,与命名参数无关。命名参数与arguments对象内存空间独立,但是值同步,二者可以互换使用,没有传递值的命名参数自动赋予undefined。严格模式下命名参数和arguments对象初始值相同,但完全独立,不会值同步。
typeof arguments; //"object"
this指函数当前作用域。
9.2 没有重载
ECMAScript函数是对象,每个函数是Function类型的实例,函数名是指向一个指定函数对象的指针,可以通过赋值使函数有多个名字。函数没有重载,没有函数签名的概念, 后定义的重名函数覆盖之前定义的,相当于更改了函数名的引用。通过检查传入参数的类型和数量可以模仿重载。
值传递?引用类型就是在栈中复制地址,指向堆内存中的同一块区域。(明明C语言管这个叫址传递啊)
9.3 作为变量使用
函数可以作为变量来使用,被赋值、作为参数传给函数或从函数中返回。
function add(a,b){return a+b;}
function cal(f,a,b){return f(a,b);}
console.info(cal(add,5,6));
function createComparisonFunction(propertyName){
return function(object1,object2){
var value1=object1[propertyName];
var value2=object2[propertyName];
return value1-value2;
}
}
9.4 函数内部属性
callee属性是一个指针,指向拥有这个arguments对象的函数。caller指向调用当前函数的函数的引用,arguments.callee.caller,如果是在全局作用域中调用当前函数,值为null。
function factorial(num){
if(num<=1){
return 1;
}
else{
return num*arguments.callee(num-1);
//arguments.callee代替函数名,防止函数名被修改后影响函数执行
}
}
9.5 函数属性和方法
length属性表示函数希望接收的命名参数的个数,函数名.length。
call()、apply()让函数在特定的作用域下进行调用,即设置函数体内this对象的值。扩充函数运行的作用域,对象不需要与方法有任何耦合关系。区别仅在于接受参数的方式不同, call()方法传递的参数逐个列举,而不是以数组的形式传递;apply()方法接收两个参数,作用域和参数数组。
Object.prototype.toString.apply("123”); //”[object String]”
window.color="red";
var o={color:"blue"};
function sayColor(){alert(this.color);}
sayColor(); //red
sayColor.call(this); //red
atyColor.call(window); //red
sayColor.call(o); //blue
function Point(x,y){
this.x=x;
this.y=y;
}
Point.prototype.move=function(x,y){
this.x+=x;
this.y+=y;
}
var p=new Point(0,0);
p.move(2,2);
var circle={x:1,y:1,r:1};
p.move.apply(circle,[2,1]); //{x:3,y:2,r:1}
bind()传入新作用域,返回新函数,该函数在bind作用域执行。第二个参数是参数列表,与call一致。
9.6 闭包
静态作用域,又称词法作用域,在编译阶段由程序定义的位置决定变量的引用,与代码执行的顺序无关。js使用静态作用域,使用词法环境管理静态作用域。词法环境是描述静态作用域的数据结构,由环境记录(形参、变量、函数等)和对外部词法环境的引用(outer)组成,形成嵌套结构。
一段代码开始执行前,先初始化词法环境。首先创建全局词法环境window对象,outer=null;,传入变量和函数,var定义的变量值为undefined,碰到函数声明语句,创建该函数词法环境(形参、arguments对象、this对象、变量、当前作用域outer等)。开始执行代码,执行到赋值语句时,修改变量的值;函数表达式,创建函数词法环境,此时的作用域可能与函数声明不同。
如果形参、函数定义、变量定义名称冲突,优先级:函数定义>形参>变量定义。
如果函数表达式有标识符,此时创建新的词法环境,只有A,没有其它内容,在A环境中定义的A函数不能被修改。
闭包是指有权访问另一个函数作用域中的变量的函数,由函数和与其相关的引用环境组成。闭包允许函数访问其引用环境中的变量,有可能是外部环境变量,该变量称为自由变量。创建闭包的常见方式,在一个函数内部创建另一个函数。广义上来说,所有js的函数都可以称为闭包,因为js函数在创建时保存了当时的词法环境。
当一个函数返回后,其词法环境中的作用域链会被销毁,但它的环境记录仍可能留在内存中,直到引用它的作用域链全部被销毁。
闭包的应用,保存变量现场。闭包只能取得包含函数中任何变量的最后一个值,但可以强制创建另一个匿名函数强制让闭包的行为符合预期。
function applyArr(){
var arr=[];
for(var i=0;i<10;i++){
(function(index){
arr.push(function(){
return index;
});
})(i);
//arr.push(function(){return i;});数组中每个值都是10
}
return arr;
}
var arr=applyArr();
var b=arr[3]();//3
闭包的应用,私有作用域的匿名函数。临时需要一些变量,就可以使用私有作用域,限制向全局作用域中添加过多的变量和函数。私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。
(function(){
//这里是块级作用域
})();
私有属性前加_,仅在函数内部访问,给对象添加方法来访问该属性。
prototype方法使用_定义的方式,不能直接说在外部不能调用,但在代码书写上能区分私有和公开。
10、RegExp类型
用于定义正则表达式对象,一个RegExp对象包含一个正则表达式和关联的标志。
属性和方法:prototype
原型对象的属性和方法:constructor, test, exec…
var reg1=/pattern/flags; //字面量形式
var reg2=new RegExp(pattern[,flags]); // RegExp构造函数,接收的参数均是字符串
pattern是任何简单或复杂的正则表达式,每个正则表达式带一个或多个标志flag,标明正则表达式的行为。支持三个标志:g全局模式,模式将被应用于所有字符串;i不区分大小写模式;m多行模式。所有元字符( [ { \ ^ $ |) ? * + . } ]都必须转义。
test()接受一个字符串参数,在正则表达式与该字符串匹配的情况下返回true,否则返回false。通常用于表单字段的验证,if语句。
var reg=/^abc/i; //以abc开头并忽略大小写
reg.test("Abc123"); //true
exec()为捕获组设计,接受要应用模式的字符串,返回包含第一个匹配项信息的数组,没有匹配项返回null。包含两个额外的属性index表示匹配项在字符串中的位置,input表示应用正则表达式的字符串。设置全局标志后每次也只返回一个匹配项,每次调用exec()都会在字符串中继续查找新匹配项。
var text="mom and dad and baby";
var pattern=/mom( and dad( and baby)?)?/gi;
var matches=pattern.exec(text);
alert(matches.index); //0
alert(matches.input); //"mom and dad and baby"
alert(matches[0]); //"mom and dad and baby"
alert(matches[1]); //" and dad and baby"
alert(matches[2]); //" and baby"
11、Date类型
用于定义日期对象。使用自UTC1970年1月1日零时开始经过的毫秒数(ms)保存日期。
属性和方法:prototype, parse, now…
原型对象的属性和方法:constructor, Date, getDate, getHours, setDate, setHours…
var myDate=new Date(); //自动获得当前时间日期,传入ms获得指定日期
var myDate=new Date(2014,3,1,7,1,1,100); //调用Date.parse()或Date.UTC()返回表示指定日期的ms
Date.parse()方法接收一个表示日期的字符串参数,尝试根据这个字符串返回相应日期的ms,如果字符串格式不对返回NaN。
Date.UTC()参数分别是年、月(0-11)、日(1-31)、小时(0-23)、分钟、秒、毫秒,年和月是必须的,省略其它参数则假设为0。
+new Date()===Date.now(),针对ms时间戳生成随机数返回表示调用这个方法时的日期和时间的ms。
日期可以用比较操作符进行比较,通过其valueOf()方法比较其毫秒表示。
日期格式化方法及其它设置或获得日期的方法见课本。
12、Global对象
Web浏览器将Global对象作为window对象的一部分加以实现,在全局作用域中声明的所有变量和函数,都是Global对象的属性。全局对象不像Math和JSON对象可以直接访问,但是定义了一系列的属性和方法,在js编码时可以被直接调用。
var global=function(){ //另一种取得Global对象的方法
return this;
}();
属性:NaN,Infinity,undefined
方法:parseInt,parseFloat,isNaN,isFinite,eval, 处理URI方法
构造器属性:Boolean,String,Number,Object,Function,Array,Date,Array
对象属性:Math,JSON
encodeURI(uri)对整个URI进行编码,但不对本身属于URI的特殊字符进行编码,除空格外,其它字符都原封不动。encodeURIComponent(uri)对URI的某一段进行编码,对任何非标准字符(中文、特殊字符等)进行编码,用于附加在现有URI后面的字符串使用。decodeURI()和decodeURIComponent()与前二者对应,用于解码。
//在登录页面中输入用户名、密码等一系列参数,点击提交功能时,将用户输入进行编码,防止注入性攻击。
var url="http://www.163.com/reg.html?name+encodeURIComponent(name)";
//依赖于URI进行参数传递时,如果不编码,直接将参数复制到URI会导致解析错误。
var url="test.html?param0="+encodeURIComponent("jack&lucy")+"¶m1="+encodeURIComponent("/image/test.png");
eval()方法是一个完整的ECMAScript解析器,接收执行的字符串,将传入的参数当作实际的语句来解析,把执行结果插入到原位置。实际使用中,eval()会带来一系列的安全性、性能及代码逻辑上的问题,不建议使用。
13、Math对象
拥有一些属性和方法的单一对象,主要用于数字计算。
属性:Math.E, Math.LN10, Math.LN2, Math.LOG2E, Math.LOG10E, Math.PI,Math.SQRT1_2, Math.SQRT2
方法:min, max, ceil, floor, round, random, abs, exp, log, pow, sqrt,…
min()和max()确定一组数值中的最小值和最大值,可接收多个参数。
var values=[1,2,3,4,5,6];
var max=Math.max.apply(Math,values);// 找到数组中的最大值
ceil()向上取整,floor()向下取整,round()四舍五入。
random(),返回大于等于0小于1的一个随机数。
值=Math.floor(Math.random()*可能值的总数+第一个可能的值); //从某个整数范围内选择一个随机值
abs(num), exp(num), log(num), pow(num,power), sqrt(num), 正弦余弦正切等其它方法。
14、JSON对象
用于存储和交换文本信息。
方法:parse、stringify
stringify(),将json对象序列化为字符串,JSON.stringify(value[,replacer[,space]])。
var json={1:1,2:'2',3:{4:'4',5:{6:6}}};
JSON.stringify(json); //'{"1":1,"2":"2","3":{"4":"4","5":{"6":6}}}'
parse(),将json字符串转换成json对象,JSON.parse(text[,reviver])。
var str='{"1":1,"2":"2","3":{"4":"4","5":{"6":6}}}';
JSON.parse(str); //{1:1,2:'2',3:{4:'4',5:{6:6}}}