javascript--5引用类型


  Object类型是JavaScript中使用最多的一种类型。虽然Object的实例不具备多少功能,但对于在应用程序中存储和传输数据而言,它确实是非常理想的选择。

  创建Object实例的方式有两种,第一种是使用new操作符后跟Object构造函数。

    var person = new Object();
    person.name = "tt";
    person.age = 12;
  另一种方式是使用对象字面量表示法。

    var person = {
        name : 'tt',
        age : 12
    }
  另外,使用对象字面量语法时,如果留空其花括号,则可以定义值包含默认属性和方法的对象。

    var person = {};            //与new Object()相同
    person.name = "tt";
    person.age = 12;
  虽然可以使用前面介绍的任何一种方法来定义对象,但开发人员更青睐第二种方法(对象字面量语法),因为这种语法要求的代码量少,而且能给人封装数据的感觉。实际上,对象字面量也是向函数传递大量可选参数的首选方式,例如:

    function showInfo(args)
    {
        if(args.name != undefined)
        {
            alert(args.name);
        }
        if(args.age != undefined)
        {
            alert(args.age);
        }
    }

    showInfo({
        name:'name',
        age:12
    });

    showInfo({name:'name'});
  一般来说,访问对象属性时使用的都是点表示法,这也是很多面向对象语言中通用的语法。不过,在JavaScript也可以使用方括号表示法来访问对象的属性。例如:

    alert(person.name);
    alert(person['name']);   
  从功能上看,这两种访问对象属性的方法没有任何区别。但方括号语法的主要优点是可以通过变量来访问属性。

    var propertyName = 'name';
    alert(person[propertyName]);
  通常,除非必须使用变量来访问属性,否则我们建议使用点表示法。

Array类型

  JavaScript中的数组与其他多数语言中的数组有着相当大的区别。虽然JavaScript数组与其他语言中的数组都是数据的有序列表,但与其他语言不同的是,JavaScript数组的每一项可以保持任何类型的数据。也就是说,可以用数组的第一个位置来保存字符串,用第二个位置来保存数值,用第三个位置来保存对象。而且,JavaScript数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据。

  创建数组的基本方式有两种。第一种是使用Array构造函数。

    var colors1 = new Array();
    var colors2 = new Array(20);                       
    var colors3 = new Array('red','blue','yellow');
  创建数组的第二种基本方式是使用数组字面量表示法。

    var colors1 = [];
    var colors2 = ['red','blue','yellow'];
  在读取和设置数组的值时,要使用方括号并提供相应值的基于0的数字索引。

    var colors = ['red','blue','yellow'];    //定义一个字符串数组
    alert(colors[0]);                        //显示第一项
    colors[2] = 'green';                     //修改第三项
    colors[3] = 'black';                     //新增第四项
  数组的长度保存在其length属性中,这个属性始终会返回0或更大的值。

    var colors = ['red','blue','yellow'];
    var names = [];
    alert(colors.length);        //3
    alert(names.length);        //0
  数组的length属性很有特点——它不是只读的。因此,通过设置这个属性,可以从数组的末尾移除项或想数组中添加新项。

    var colors = ['red','blue','yellow'];
    colors.length = 2;
    alert(colors[2]);        //undefined
  这个例子中的数组colors一开始有3个值。将其length属性设置为2会移除最后一项,结果再访问colors[2]就会显示undefined了。

  利用length属性也可以方便地在数组末尾添加新项。

    var colors = ['red','blue','yellow'];
    colors[colors.length] = 'green';        //在位置3添加一种颜色
    colors[colors.length] = 'black';        //再在位置4添加一种颜色
  由于数组最后一项的索引始终是length-1,因此下一个新项的位置就是length。

  转换方法

  所有对象都具有toLocaleString()、toString()和valueOf()方法。其中,调用数组的toString()和valueOf()方法会返回相同的值,即由数组中每个值的字符串形成拼接而成的一个以逗号分隔的字符串。实际上,为了创建这个字符串会调用数组每一项的toString()方法。

    var colors = ['red','blue','yellow'];
    alert(colors.toString());   //red,blue,yellow
    alert(colors.valueOf());    //red,blue,yellow
    alert(colors);              //red,blue,yellow
  我们首先显式地调用了toString()和valueOf()方法,以便返回数组的字符串表示,每个值的字符串表示拼接成了一个字符串,中间以逗号分隔。最后一行代码直接将数组传递给了alert()。由于alert()要接收字符串参数,所有它会在后台调用toString()方法,由此会得到与直接调用toString()方法相同的结果。

  另外,toLocaleString()方法经常也会返回与toString()和valueOf()方法相同的值,但也不总是如此。当调用数组的toLocaleString()方法时,它也会创建一个数组值的以逗号分隔的字符串。而与前两个方法唯一的不同之处在于,这一次为了取得每一项的值,调用的是每一项的toLocaleString()方法,而不是toString()方法。例如:

    var person1 = {
        toLocaleString : function(){
            return "person1 : toLocaleString";
        },
        toString : function(){
            return "person1 : toString";
        }
    };
    var person2 = {
        toLocaleString : function(){
            return "person2 : toLocaleString";
        },
        toString : function(){
            return "person2 : toString";
        }
    };
    var people = [person1,person2];
    alert(people);                       //person1 : toString,person2 : toString
    alert(people.toString());            //person1 : toString,person2 : toString
    alert(people.toLocaleString());      //person1 : toLocaleString,person2 : toLocaleString
  数组继承的toLocaleString()、toString()和valueOf()方法,在默认情况下都会以逗号分隔的字符串的形式返回数组项。而如果使用join()方法,则可以使用不同的分隔符来构建这个字符串。

    var colors = ['red','blue','yellow'];
    alert(colors.join(','));    //red,blue,yellow
    alert(colors.join('||'));    //red||blue||yellow
  注意:如果数组中的某一项的值是null或者undefined,那么该值在join()、toString()、toLocaleString()和valueOf()方法返回的结果中以空字符串表示。

  栈方法

  JavScript数组也提供了一种让数组的行为类似于其他数据结构的方法。具体来说,数组可以表现得就像栈一样,后者是一种可以限制插入和删除项的数据结构。栈是一种后进先出后进先出的数据结构。而栈中项的插入(叫做推入)和移除(叫做弹出),只发生在一个位置——栈的顶部。JavaScript提供了push()和pop()方法,以便实现类似的栈行为。

  push()方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。而pop()方法则从数组末尾移除最后一项,减少数组的length值,然后返回移除的项。

    var colors = new Array();                    //创建一个数组
    var count = colors.push('red','blue');       //推入两项
    alert(count);                                //2
    count = colors.push('yellow');               //再推入一项
    alert(count);                                //3
    var item = colors.pop();                     //取得最后一项
    alert(item);                                 //yellow
    alert(colors.length);                        //2
  队列方法

  队列数据结构的访问规则是先进先出。队列在列表的末端添加项,从列表的前端移除项。由于push()是向数组末端添加项的方法,因此要模拟队列只需一个从数组前端取得项的方法。实现这一操作的数组方法就是shift(),它能够移除数组中的第一个项并返回该项,同时将数组长度减1。结合使用shift()和push()方法,可以像使用队列一样使用数组:

    var colors = new Array();                    //创建一个数组
    var count = colors.push('red','blue');       //推入两项
    alert(count);                                //2
    count = colors.push('yellow');               //再推入一项
    alert(count);                                //3
    var item = colors.shift();                   //取得第一项
    alert(item);                                 //red
    alert(colors.length);                        //2
  JavaScript还为数组提供了一个unshift()方法。顾名思义,unshift()与shift()的用途相反:它能在数组前端添加任意个项并返回新数组的长度。因此,同时使用unshift()和pop()方法,可以从反方向来模拟队列,即在数组的前端添加项,从数组的末端移除项,例如:

    var colors = new Array();                    //创建一个数组
    var count = colors.unshift('red','blue');    //推入两项
    alert(count);                                //2
    count = colors.unshift('yellow');            //再推入一项
    alert(count);                                //3
    var item = colors.pop();                     //取得第一项
    alert(item);                                 //blue
    alert(colors.length);                        //2
  注意:IE对JavaScript的实现中存在一个偏差,其unshift()方法总是返回undefined而不是数组的新长度。

  重排序方法

  数组中已经存在两个可以直接用来重排序的方法:reverse()和sort(),reverse()方法会反转数组项的顺序。

    var values = [1,2,3,4,5];
    values.reverse();
    alert(values);                //5,4,3,2,1
  在默认情况下,sort()方法按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。为了实现排序,sort()方法会调用每个数组项的toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值,sort()方法比较的也是字符串,如下所示:

    var values = [0,1,5,10,15];
    values.sort();
    alert(values);                //0,1,10,15,5
  可见,即使例子中值的顺序没有问题,但sort()方法也会根据测试字符串的结果改变原来的顺序。因为数值5虽然小于10,但在进行字符串比较时,“10”则位于“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);                //15,10,5,1,0
  对于数值类型或者其valueOf()方法会返回数值类型的对象类型,可以使用一个更简单的比较函数。这个函数主要用第二个值减第一个值即可。

    function compare(value1,value2){
        return value2 - value1;
    }
  操作方法

  JavaScript对操作数组提供了很多方法。其中,concat()方法可以基于当前数组中的所有项创建一个新数组,如果传递给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()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之前的项——但不包括结束位置的项。

    var colors = ['red','green','blue','yellow','black','brown'];
    var colors2 = colors.slice(1);
    var colors3 = colors.slice(1,4);
    alert(colors2);        //green,blue,yellow,black,brown
    alert(colors3);        //green,blue,yellow
  下面我们来介绍splice()方法,这个方法恐怕要算是最强大的数组方法了,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','black');    //从位置1开始插入两项
    alert(colors);                                    //green,yellow,black,blue
    alert(removed);                                   //返回一个空数组
    removed = colors.splice(1,1,'red','brown');       //插入两项,删除一项
    alert(colors);                                    //green,red,brown,black,blue
    alert(removed);                                   //yellow
Date类型

  JavaScript中的Date类型是在早期Java中的java.util.Date类基础上构建的。为此,Date类型使用自UTC 1970年1月1日零时开始经过的毫秒数来保存日期。在使用这种数据存储格式的条件下,Date类型保存的日期能够精确到1970年1月1日之前或之后的285 616年。

  要创建一个日期对象,使用new操作符和Date构造函数即可。

    var now = new Date();
  在调用Date构造函数而不传递参数的情况下,新创建的对象自动获得当前日期和时间。如果想根据特定的日期和时间创建日期对象,必须传入表示该日期的毫秒数。为了简化这一计算过程,JavaScript提供了两个方法:Date.parse()和Date.UTC()。

  其中,Date.parse()方法接收一个表示日期的字符串参数,然后尝试根据这个字符串返回相应日期的毫秒数。JavaScript没有定义Date.parse()应该支持哪种格式,因此这个方法的行为因实现而异,而且通常是因地区而异。将地区设置为美国的浏览器通常都接受下列日期格式:

  ● "月/日/年",如:6/13/2204

  ● "英文月名 日,年",如:January 12,2004

  ● "英文星期几 英文月名 日 年 时:分:秒 时区",如:Tue May 25 2004 00:00:00 GMT-0700

  例如,要为2004年5月25日创建一个日期对象,可以使用下面的代码:

  var someDate = new Date(Date.parse("May 25 , 2004"));
  如果传入Date.parse()方法的字符串不能表示日期,那么它会返回NaN。实际上,如果直接将表示日期的字符串传递给Date构造函数,也会在后台调用Date.parse()。换句话说,下面的代码与前面的例子是等价的:

  var someDate = new Date('May 25 , 2004');
  Date.UTC()方法同样也返回表示日期的毫秒数,但它与Date.parse()在构建值时使用不同的信息。Date.UTC()的参数分别是年份、基于0的月份(一月是0,二月是1,以此类推)。月中的哪一天(1到31)、小时数(0到23)、分钟、秒以及毫秒数。在这些参数中,只有前两个参数(年和月)是必需的。如果没有提供月中的天数,则假设天数为1;如果省略其他参数,则统统假设为0。

  //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));
  如同模仿Date.parse()一样,Date构造函数也会模仿Date.UTC(),但有一点明显不同:日期和时间都基于本地时区而非GMT来创建的。可以将前面的例子重写如下:

  //本地时间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类型还有一些专门用于将日期格式化为字符串的方法,这些方法如下:

  ● toDateString()——以特定于实现的格式显示星期几、月、日和年

  ● toTimeString()——以特定于实现的格式显示时、分、秒和时区

  ● toLocaleDateString()——以特定于地区的格式显示星期几、月、日和年

  ● toLocaleTimeString()——以特定于实现的格式显示时、分、秒

  ● toUTCString()——以特定于实现的格式完整的UTC日期

  以上这些字符串格式方法的输出也是因浏览器而异的,因此没有哪一个方法能够用来在用户界面中显示一致的日期信息。

  以下是Date类型的所有方法:

方法 描述
Date() 返回当日的日期和时间。
getDate() 从 Date 对象返回一个月中的某一天 (1 ~ 31)。
getDay() 从 Date 对象返回一周中的某一天 (0 ~ 6)。
getMonth() 从 Date 对象返回月份 (0 ~ 11)。
getFullYear() 从 Date 对象以四位数字返回年份。
getYear() 请使用 getFullYear() 方法代替。
getHours() 返回 Date 对象的小时 (0 ~ 23)。
getMinutes() 返回 Date 对象的分钟 (0 ~ 59)。
getSeconds() 返回 Date 对象的秒数 (0 ~ 59)。
getMilliseconds() 返回 Date 对象的毫秒(0 ~ 999)。
getTime() 返回 1970 年 1 月 1 日至今的毫秒数。
getTimezoneOffset() 返回本地时间与格林威治标准时间 (GMT) 的分钟差。
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() 设置 Date 对象中月的某一天 (1 ~ 31)。
setMonth() 设置 Date 对象中月份 (0 ~ 11)。
setFullYear() 设置 Date 对象中的年份(四位数字)。
setYear() 请使用 setFullYear() 方法代替。
setHours() 设置 Date 对象中的小时 (0 ~ 23)。
setMinutes() 设置 Date 对象中的分钟 (0 ~ 59)。
setSeconds() 设置 Date 对象中的秒钟 (0 ~ 59)。
setMilliseconds() 设置 Date 对象中的毫秒 (0 ~ 999)。
setTime() 以毫秒设置 Date 对象。
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)。
toSource() 返回该对象的源代码。
toString() 把 Date 对象转换为字符串。
toTimeString() 把 Date 对象的时间部分转换为字符串。
toDateString() 把 Date 对象的日期部分转换为字符串。
toGMTString() 请使用 toUTCString() 方法代替。
toUTCString() 根据世界时,把 Date 对象转换为字符串。
toLocaleString() 根据本地时间格式,把 Date 对象转换为字符串。
toLocaleTimeString() 根据本地时间格式,把 Date 对象的时间部分转换为字符串。
toLocaleDateString() 根据本地时间格式,把 Date 对象的日期部分转换为字符串。
UTC() 根据世界时返回 1970 年 1 月 1 日 到指定日期的毫秒数。
valueOf() 返回 Date 对象的原始值。
Function类型

  JavaScript中什么最有意思,我想那莫过于函数了——而有意思的根源,则在于函数实际上时对象。每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。

  函数通常是使用函数声明语法定义的,如下面例子所示:

    function sum(num1,num2)
    {
        return num1 + num2;
    }
  这与下面使用函数表达式定义函数的方式几乎相差无几:

    var sun = function(num1,num2){
        return num1 + num2;
    };
  以上代码定义了变量sum并将其初始化为一个函数。function关键字后面没有函数名,这是因为在使用函数表达式定义函数时,没有必要使用函数名——通过变量sum即可引用函数。另外,还要注意函数末尾有一个分号,就像声明其他变量时一样。

  最后一种定义函数的方式是使用Function构造函数。Function构造函数可以接收任意数量的参数,但最后一个参数始终都被看成是函数体,而前面的参数则枚举出了新函数的参数。

  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
  注意:使用不带括号的函数名是访问函数指针,而非调用函数。

  函数声明与函数表达式

  目前为止,我们一直没有对函数声明和函数表达式加以区别。而实际上, 解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。

    alert(sum(10,10));
    function sum(num1,num2)
    {
        return num1 + num2;
    }
  以上代码完全可以正常运行。因为在代码开始执行之前,解析器就已经读取函数声明并将其添加到执行环境中了。如果像下面例子所示,把上面的函数声明改为变量初始化方式,就会在执行期间导致错误。

    alert(sum(10,10));
    var sum = function(num1,num2)
    {
        return num1 + num2;
    }
  作为值的函数

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

    function callSomeFunction(someFunction , someArgument)
    {
        return someFunction(someArgument);
    }
  这个函数接受两个参数,第一个参数应该是一个函数,第二个参数应该是要传递给该函数的一个值。然后,就可以像下面的例子一样传递函数了:

    function add(num)
    {
        return num + 10;
    }
    var result = callSomeFunction(add,10);
    alert(result);        //20
  当然,可以从一个函数中返回另一个函数,而且这也是极为有用的一种技术。

    function createSumFunction()
    {
        return function(num1,num2){
            return num1 + num2;
        };
    }
    var sumFunction = createSumFunction();
    alert(sumFunction(10,10));        //20
  函数内部属性

  在函数内部,有两个特殊的对象:arguments和this。其中,arguments是一个类数组对象,包含着传入函数中的所有参数,而且可以使用length属性来确定传递进来多少个参数。

    function sayHi()
    {
        alert(arguments.length);                        //2
        alert(arguments[0] + ',' + arguments[1]);        //hello,world
    }
    sayHi('hello','world');
  虽然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
    alert(factorial(5));            //0
  函数内部的另一个特殊对象是this,this引用的是函数据以执行操作的对象——或者也可以说,this是函数在执行时所处的作用域(当在网页的全局作用域中调用函数时,this对象引用的就是window)。看下面的例子:

    window.color = 'red';
    var o = {color:'blue'};
   
    function sayColor()
    {
        alert(this.color);
    }

    sayColor();                //red
    o.sayColor = sayColor;
    o.sayColor();              //blue
  上面这个函数sayColor()是在全局作用域中定义的,它引用了this对象。由于在调用函数之前,this的值并不确定,因此this可能会在代码执行过程中引用不同的对象。当在全局作用域中调用sayColor()时,this引用的是全局对象 window;换句话说,对this.color求值会转换成对window.color求值,于是结果就是'red'。而当把这个函数赋给对象o并调用o.sayColor()时,this引用的是对象o,因此对this.color求值会转换成对o.color求值,结果就是'blue'。

  函数属性和方法

  因为JavScript中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:length和prototype。其中,length属性表示函数希望接收的命名参数的个数。

    function sayName(name)
    {
        alert(name);
    }
    function sayHi()
    {
        alert('hi');
    }

    alert(sayName.length);      //1
    alert(sayHi.length);         //0
  在JavaScript中最耐人寻味的就要数prototype属性了。对于引用类型而言,prototype是保存它们所有实例方法的真正所在。诸如toString()和valueOf()等方法实际上都是保存在prototype名下,只不过是通过各自对象的实例访问罢了。在创建自定义引用类型以及实现继承时,prototype属性的作用是极为重要的(这里就不对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]);
    }
    alert(callSum1(10,10));                    //20
    alert(callSum2(10,10));                    //20
  在上面例子中,callSum1()在执行sum()函数时传入了this作为作用域(因为是在全局作用域中调用的,所以传入的就是window对象)和arguments对象。而callSum2同样也调用了sum()函数,但它传入的则是this和一个参数数组。

  call()方法与apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于call()方法而言,第一个参数是作用域没有变化,变化的只是其余的参数都是直接传递给函数的。

    function callSum2(num1,num2)
    {
        return sum.call(this,num1,num2);
    }
    alert(callSum2(10,10));                    //20
  事实上,传递参数并非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
  在上面的例子中,当运行sayColor.call(o)时,函数的执行环境就不一样了,因为此时函数体内的this对象指向了o,于是结果显示"blue"。

  注意:每个函数都有一个非标准的caller属性,该属性指向调用当前函数的函数。一般是在一个函数的内部,通过arguments.callee.caller来实现对调用栈的追溯。目前,IE、FireFox、Chrome都支持该属性,但建议将该属性用于调试目的。

内置对象

  JavaScript中有两个内置对象:Global和Math。

 Global对象

  Global(全局)对象可以说是JavaScript中最特别的一个对象了,因为不管你从什么角度上看,这个对象都是不存在的。JavaScript中的Global对象在某种意义上是作为一个终极的“兜底儿对象”来定义的。换句话说,不属于任何其他对象的属性和方法,最终都是它的属性和方法。事实上,没有全局变量或全局函数;所有在全局作用域定义的属性和函数,都是Global对象的属性。诸如isNaN()、parseInt()以及parseFloat(),实际上全都是Global对象的方法,Global对象还包含其他一些方法。

  URI编码方法

  Global对象的encodeURI()和encodeURIComponent()方法可以对URI进行编码,以便发送给浏览器。有效的URI中不能包含某些字符,例如空格。而这两个URI编码方法就可以对URI进行编码,它们用特殊的UTF-8编码替换所有无效的字符,从而让浏览器能够接受和理解。

  其中,encodeURI()主要用于整个URI(例如:http://www.test.com/test value.html),而encodeURIComponent()主要用于对URI中的某一段(例如前面URI中的test value.html)进行编码。它们主要区别在于,encodeURI()不会对本身属于URI的特殊字符进行编码,例如冒号、正斜杠、问好和井号;而encodeURIComponent()则会对它发现的任何非标准字符进行编码。

    var uri = "http://www.test.com/test value.html#start";
    //"http://www.test.com/test%20value.html#start"
    alert(encodeURI(uri));
    //"http%3A%2F%2Fwww.test.com%2Ftest%20value.html%23start"
    alert(encodeURIComponent(uri));
  一般来说,使用encodeURIComponent()方法的时候要比使用encodeURI()更多,因为在实践中更常见的是对查询字符串参数而不是对基础URI进行编码。

  与encodeURI()和encodeURIComponent()方法对应的两个方法分别是decodeURI()和decodeURIComponent()。其中,decodeURI()只能对encodeURI()替换的字符进行解码,同样,decodeURIComponent()只能对encodeURIComponent()替换的字符进行解码。

  eval()方法

  eval()方法大概是JavaScript中最强大的一个方法了,eval()方法就像是一个完整的JavaScript解析器,它只接受一个参数,即要执行的字符串。看下面的例子:

  eval("alert('hi')");
  这行代码的作用等价于下面这行代码:

  alert('hi');
  当解析器发现代码中调用eval()方法时,它会将传入的参数当做实际的JavaScript语句来解析,然后把执行结果插入到原位置。通过eval()执行的代码被认为是包含该次调用的执行环境的一部分,因此被执行的代码具有与该执行环境相同的作用域链。这意味着通过eval()执行的代码可以引用在包含环境中定义的变量,例如:

    var msg = 'hello world';
    eval('alert(msg)');            //hello world
  可见,变量msg是在eval()调用的环境之外定义的,但其中调用的alert()仍然能够显示“hello world”。这是因为上面第二行代码最终被替换成了一行真正的代码。同样地,我们也可以在eval()调用中定义一个函数,然后再在该调用的外部代码中引用这个函数:

    eval("function sayHi(){alert('hi')}");
    sayHi();
  注意:能够解释代码字符串的能力非常强大,但也非常危险。因此在使用eval()时必须极为谨慎,特别是在用它执行用户输入数据的情况下。否则,可能会有恶意用户输入威胁你的站点或应用程序安全的代码(即所谓的代码注入)。

 Math对象

  与我们在JavaScript直接编写的计算功能相比,Math对象提供的计算功能执行起来要快得多。Math对象还提供了辅助完成这些计算的属性。

属性 描述
E 返回算术常量 e,即自然对数的底数(约等于2.718)。
LN2 返回 2 的自然对数(约等于0.693)。
LN10 返回 10 的自然对数(约等于2.302)。
LOG2E 返回以 2 为底的 e 的对数(约等于 1.414)。
LOG10E 返回以 10 为底的 e 的对数(约等于0.434)。
PI 返回圆周率(约等于3.14159)。
SQRT1_2 返回返回 2 的平方根的倒数(约等于 0.707)。
SQRT2 返回 2 的平方根(约等于 1.414)。
  Math对象包含的方法如下:

方法 描述
abs(x) 返回数的绝对值。
acos(x) 返回数的反余弦值。
asin(x) 返回数的反正弦值。
atan(x) 以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。
atan2(y,x) 返回从 x 轴到点 (x,y) 的角度(介于 -PI/2 与 PI/2 弧度之间)。
ceil(x) 对数进行上舍入。
cos(x) 返回数的余弦。
exp(x) 返回 e 的指数。
floor(x) 对数进行下舍入。
log(x) 返回数的自然对数(底为e)。
max(x,y) 返回 x 和 y 中的最高值。
min(x,y) 返回 x 和 y 中的最低值。
pow(x,y) 返回 x 的 y 次幂。
random() 返回 0 ~ 1 之间的随机数。
round(x) 把数四舍五入为最接近的整数。
sin(x) 返回数的正弦。
sqrt(x) 返回数的平方根。
tan(x) 返回角的正切。
toSource() 返回该对象的源代码。
valueOf() 返回 Math 对象的原始值。

一、引用类型
1.ECMAScript从技术上讲是一门面向对象语言,但它不具备传统的面向对象语言所支持的类和接口等基本结构。js中的对象,是某个特定引用类型的实例。新对象通过new操作符构造出来。构造函数本身也是一个普通函数,加new和不加new的运行结果完全不同。ECMAScript有很多原生的引用类型。
2.Object类型
(1)Object的属性,可以用点语法访问,也可以用方括号语法访问。obj.name和obj["name"]是等价的,但后面这种可以用字符串变量去访问,而且有些属性名用点语法是非法的,比如属性名中间有空格,这种时候只能用方括号语法访问。
(2)Object可以用new Object()创建,也可以直接用字面量{}创建。前面提到过。
3.Array类型
(1)Array是Object的一个派生。和其他语言最大不同是,Array的每个元素都可以是不同类型的。注意,只有一种情况是创建固定长度数组。创建数组实例时,可以用new,也可以不用。效果是一样的。可以使用字面量[]创建数组。注意,c语言里用{}初始化数组,这里不要混淆。用字面量时,如果方括号里有多余的逗号,IE8以下会抛错,而其他浏览器不会,其他浏览器会创建null元素。
(2)Array构造函数参数不固定,如果只有一个数值n,作用是创建一个大小为n的数组;如果是很多个,就是创建包含这些元素的数组。引用数组元素下标越界时,返回的都是undefined。
(3)判断一个变量是不是数组,不能用typeof,会返回object,要用instanceof Array;在IE9以上和标准浏览器中,增加了Array.isArray(val),可以判断是不是数组。
(4)转换接口
   <1>arr.valueOf(),返回的还是数组。
   <2>arr.toString(),返回的是每个元素的toString()拼串。
   <3>arr.join(","),自定义分隔符的拼串。
(5)元素接口
   <1>arr.push(val),把元素从尾部添加到数组中
   <2>val=arr.pop(),弹出最后一个元素并返回该元素
   <3>val=arr.shift(),弹出第一个元素并返回该元素
   <4>arr.unshift(val),把元素从头部添加到数组中。
(6)排序接口
   <1>arr.reverse(),元素反序放置。
   <2>arr.sort(),元素升序排列,sort可以带一个函数作为比较原则,这个函数必须返回-1或1或0,这个函数有两个形参输入。
(7)操作接口
   <1>arr2=arr.concat("1",[2,3]),在当前数组基础上添加新元素,返回一个新的数组。
   <2>arr2=arr.slice(a,b),选取当前数组下标区间[a,b)内的元素,返回值这些元素组成的新数组;如果不指定b,b=arr.length;如果传入负数,则加上length在处理;如果a>=b,返回空数组。
   <3>arr.splice(0,2),删除前两个元素;
   <4>splice(2,1,"1","2"),从位置2开始,删除1项,插入两个元素分别是"1"和"2",也就是相当于把arr[2]替换成"1",然后在后面插入"2"。
(8)位置接口
   <1>n=arr.indexOf(val),返回val在数组中的下标,数组中不含有val,返回-1。
   <2>n=arr.lastIndexOf(val),也是下标,不过是从后向前数。
(9)迭代接口
   <1>b=arr.every(function(item,index,array){...}),对数组中每个函数执行同一个函数,如果所有结构都为true,返回true;
   <2>b=arr.some(function(item,index,array){...}),跟every方法一样,区别是只要有一个运行结果为true,就返回true。
   <3>b=arr.filter(function(item,index,array){...}),返回的是结果为true的元素的数组。
   <4>b=arr.forEach(function(item,index,array){...}),没有返回值。
   <5>b=map(function(item,index,array){...}),返回每一项执行结果组成的数组。回调函数有四个形参,分别是pre上一次迭代的结果、cur当前迭代的元素、index和array。
   <6>b=reduce(function(pre,cur,index,array)),从左向右迭代每一项,计算一个最终的返回值,
   <7>b=reduceRight(function(pre,cur,index,array))从右向左迭代,
4.Date类型
(1)Date也是Object的派生类。用UTC存放时间,存放的是1970年1月1日0时依赖的毫秒数。调用构造函数new Date()不传参时,返回的是当前日期。如果传入参数,必须是UTC毫秒时间。
   <1>Date.parse()可以将字符串转换成UTC时间,想把2000年3月1日转换成时间,应该是Date.parse("3/1/2000")。
   <2>Date.UTC()也能起到同样的效果,但这个函数认为第一个月是0月,而且是一独立参数传入,所以想把2000年3月1日转换成时间,应该是Date.UTC(2000,2,1)。另外,可以在new Date()前加一个+,把时间转换成字符串。
(2)格式化结构
   <1>toDateString(),以特定格式返回星期、月、日、年;
   <2>toTimeString(),以特定格式返回时、分、秒、时区;
   <3>toUTCString(),以特定格式返回完整UTC时间。
5.RegExp类型
(1)js用RegExp表示正则表达式。
(2)浏览器对正则表达式的支持差异很大,这里不细展开二楼。
6.Function类型
(1)function实际上也是object。每一个函数,都是Function类型的实例。函数名,实际上是指向某个函数的指针,不会与某个函数绑定。
(2)js没有函数重载。两个函数重名的意义,其实是函数指针变量从一个函数指向另一个函数。
(3)产生一个函数,可以用函数声明的方式function a(){},也可以用函数表达式的方式var a=function(){}。这两种方法的区别是,解析器会率先读取函数声明,让其在执行前可用。而函数表达式,必须在该行执行了之后才可用。
(4)函数名是函数的指针,因此,可以把函数名当作形参传递,也可以当作返回值返回。
(5)内部属性
   <1>arguments。是个类数组对象,但不是数组,用于存放当前函数的形参。arguments没有数组的接口函数。arguments有length属性和callee属性,length表示形参个数,callee是当前函数的指针,通过它可以匿名调用当前函数。
   <2>this。js中的this与c#和java中的this类似,指的是这个函数所在的执行环境。它的值只有在函数执行的时候才能确定。this值的是什么,是个很常见的问题,面试中也常考到。
   <3>funcName.caller。指的是调用该函数的函数。匿名引用时,arguments.callee.caller。
(6)外部属性
   <1>funcName.length。是命名函数希望得到的形参的个数。
   <2>funcName.prototype。是ECMAScript的核心属性,保存这创建实例的原型。这在继承中非常有用。并且这个属性不可枚举,在for-in、for-each中看不见。
(7)外部方法(函数也是Object,可以任意添加方法,而且也有toString,这里说的是function特有的方法)
   <1>funcName1.apply(this,argm)。通过这种方法,可以深度调用函数funcName1。调用funcName1时,给funcName1指定了一个执行环境,同时,传给它几个其他的参数(argm可以是arguments对象,也可以是普通数组)。换句话说,apply能设置被调用者的this。
   <2>funcName1.call(this,argm1,argm2)。用法和apply完全相同,就是传值方式不同。
//小实验
window.color="red";
var obj={color:"blue"};
function getColor(){alert(this.color);}
getColor.call(this);//red
getColor.call(window);//red
getColor.call(o);//blue
   <3>func=funcName1.bind(object)。通过bind方法,创建一个新的函数实体,功能和func1Name相同,但新函数的执行环境,被设定为object。
//小实验
window.color="red";
var obj={color:"blue"};
function getColor(){alert(this.color);}
var getColor2=getColor.bind(o);
getcolor2();//blue
二、基本类型的包装
1.ECMAScript对基础数据类型boolean、string、number进行了一系列包装,使他们拥有了更多接口。我们知道基础类型不是对象,不应该有方法和属性,但为了保证操作的直观性,这种包装还是很有意义的。
2.可以用显示的方法调用Boolean、String、Number来包装对象,但尽量不要这样做。
3.Number类型常用方法
(1)toString(n),数转串,之前提到过。
(2)toFixed(n),小数点取舍。
(3)toExponential(),转科学计数法。
(4)toPrecision(n),保留n位有效数字。
4.String类型常用方法
(1)charAt、charCodeAt、fromCharCode,返回某个位置的字符或ASCII值,将ASCII转换成字符。
(2)slice、substring、substr,切割并返回子串。
(3)indexOf、lastIndexOf,查找字符位置。
(4)trim,去掉前后空格。
(5)toUpperCase、toLowerCase,大小写的转换。
(6)match(RegExp)、search(RegExp),根据正则表达式做匹配,或查找正则出现的位置。
(7)replace(RegExp,str2),replace(str1,str2)把正则匹配替换成str2,或把第一个str1替换成str2。
5.对基础数据进行包装时,使用new返回的是对象,否则返回的是对应类型。
//小实验
var a=Number(10);
var b=new Number(10);
alert(typeof a);//number
alert(typeof b);//object
三、单体内置对象
1.Global对象
(1)这是个兜底对象。换句话说,不属于任何对象的属性或方法,都是它的属性和方法。比如parseInt、parseFloat、isNaN。
(2)Global其他常用方法
   <1>encodeURI,把空格替换成%20。对应的逆运算是decodeURI
   <2>encodeURIComponent,把所有非字母替换成URI编码。对应的逆运算是decodeURIComponent。
   <3>eval,把字符串翻译成代码并执行。一般用于实现json-string互转。这是一个非常危险的命令。
2.window对象,window对象可以看作BOM扩展的总接口。
3.document对象,document对象可以看作DOM扩展的总接口。
4.Math对象,封装了一些数学运算方法、数学比较方法和数学常量。

1 Object 类型
创建Object实例有两种方式

1.       使用new

var person = new Object();

person.name = ‘豪情’;

person.age = 29;

2.       使用对象字面量方式

var person = {

         name: ‘豪情’,

         age:29

}

 

5.2 Array 类型
创建数组有两种

var arr = new Array();

var arr2 = [];

数组的length 不是只读的,是只写的

5.2.1 转换方法
toLocaleString(), toString()和valueOf()

join 方法重现了toString(),不同的分隔符来分隔然后按字符串形式返回数组。

var num = [1 , 2, 3];

alert(num.join(‘--’)); // output 1--2--3

5.2.2 栈方法
数组可以像栈一样,栈是一种可以限制插入和删除项的数据结构。保持后进先出的原则。

数组的插入或移除只发现在栈的顶部。

a)         push() 添加到数组的末尾

b)         pop() 从数组末尾移除最后一项,然后返回移除的项

5.2.3 队列方法
队列的数据结构是先进先出。

         shift() 移除数组中的第一个项并返回该项

         unshift() 能在数组前端添加任意个项并返回新数组的长度

5.2.4 重排序方法
         reverse() 反转数组项的顺序

         sort() 默认按升序排列数组项,也可以接受一个比较函数做为参数

5.2.5 操作方法
a)         concat() 如果传递给concat()方法的是一或多个数组,则该方法会将这些数组中的每一项都添加到结果数据中。如果传递的不是数组这些值会被简单地添加到结果数组的末尾。

b)         slice(a, b) 参数表示返回项的起始和结束位置,如果只有一个参数,则返回指定位置开始到当前数组末尾的所有项。

c)         splice(a, b, c)

                         i.              当有两个参数时:要删除第一项的位置,或删除的项数

                       ii.              当有三个参数时:替换。3个参数分别表示的意思是:起始位置,要删除的项数和要插入的项,  当删除项为0时,只插入不删除。

 

这里在和string的几个方法比较一下,以免记错:

slice 既可用于array,也可用于string

substring,substr只可用于string

substring,slice有两个参数,第二个参数表示位置,其实splice,substr第二个参数都表示长度。

substring,slice,substr,2个参数时,slice,substr 2个可以为负,为负是计算位置(length + value),substring则视为0

 

splice() 方法与 slice() 方法的作用是不同的,splice() 方法会直接对数组进行修改。

slice可用于字符串,splice则不可用于字符串。

这里边也有几个简单的例子:

http://hi.baidu.com/jinwb/blog/item/b6a4ac4b2f7ae2fb83025c38.html

 

5.3 Date类型
Date.parse()

接收一个表示日期的字符串参数,尝试根据这个字符串返回相应日期的毫秒数。

5.3.1 继承的方法
重写了toLocaleString(),toString(),valueOf()

5.3.2 日期格式化方法
toDateString(); //星期几,月日和年

toTimeString(); // 时分秒和时区

toLocaleDateString(); //特定于地区的格式显示星期几,月日和年

toLocaleTimeString(); //特定于时分秒

toUTCString()  //特定于实现的格式完整的UTC日期

5.3.3 日期/时间组件方法
getTime() //日期毫秒数

setTime();//设置毫秒数

getFullYear():// 取得4位数的年份

5.4 RegExp类型
正则的匹配模式:

g—表示全局(global)

i—表示不区分大小写(case-insensitive)

m—表示多行(multiline)

5.4.1 转换方法
global—布尔值,是否设置了g标志

ignoreCase—布尔值,是否设置了i标志

lastIndex—整数,表示开始搜索下一个匹配项的字符位置,从0算起

multiline—布尔值,表示是否设置了m标志

source—正则表达式的字符串表示,按照字面量形式返回

5.4.2 RegExp实例方法
exec(): 返回包含第一个匹配项信息的数组

test(): 在模式与参数匹配的情况下,返回true,否则返回false

5.5 Function类型
函数实际上是对象,每个函数都是Function类型的实例,既然是对象,就会有属性和方法,而且函数名实际上是指向函数对象的一个指针。

function sum(){return arguments[0] + arguments[1]} //第一次预编译检查语法并执行

var sum = function(){return arguments[0] + arguments[1]} //第一次预编译检查语法不执行,只有当调用时才执行

函数的内部属性,

arguments,this

arguments是like array对象,有数组的属性,比如,有长度也可用下标来访问,但是它不是数组。

arguments.callee调用自身

this是指向当前函数,用call,apply动态改变this指向.

5.6 基本包装类型
Boolean, Number和String

5.6.1 Boolean类型
Boolean类型是与布尔值对应的引用类型。

typeof 基本类型返回 Boolean

对引用类型则返回 object

5.6.2 Number类型
number类型是数字值对应的引用类型。

toString(基数) 返回几进制数值的字符串形式

toFixed(num) 返回num位小数

toExponential() 返回以指数表示的数值的字符串形式

5.6.3 String类型
String类型是字符串的对象包装类型

1.      字符方法
charAt()以单字符字符串的形式返回给定位置的那个字符

charCodeAt() 返回字符编码

2.      字符串操作方法
concat() 用于将一或多个字符串拼接起来,返回拼接得到的新字符串

slice,substr,substring在前面已做过比较,不多述

3.      字符串位置方法
indexOf():从一个字符串中搜索给定的子字符串位置,返回子字符串的位置,如果没有找到则返回-1;它从开关后向搜索子字符串,而lastIndexOf()从字符串末尾向前搜索

4.      字符串大小写转换方法:
toLowerCase() 转换为小写

toUpperCase() 转换为大写

5.      字符串模式匹配方法
match() 本质上与exec()方法相同,match只接受一个参数,要么是正则表达式,要么是一个RegExp对象

search()查找模式,返回字符串中第一个匹配项索引,如果没有找到则返回-1

replace()第二个参数还可以是一个函数

6.      localeCompare() 比较两个字符串位置
7.     fromCharCode() 接受多个字符编码然后把它们转换成一个字符串
5.7.1 Global 类型
有isNaN(), isFinite(), parseInt(), parseFloat()

URI编码方式

encode() 不会对本身属于URI的特殊字符进行编码,如冒号,正斜杠

encodeURIComponent() 会对它发现的任何非标准字符进行编码

5.7.2 Math 类型
Math.PI π的值

Math.LN2 2的自然对数

 

Math.ceil(),向上舍入

Math.floor(),向下舍入,

Math.round(),正常舍入

 

Math.random()返回介于0和1之间的随机数

其它:

Math.abs(num); //num绝对值

Math.sin(x);

Math.cos(x);

Math.tan(x);

Math.exp(num); //Math.E的num次幂

Math.log() //num 的自然对数

Math.pow() //num的power次幂

Math.sqrt(num) //num的平方根

Math.acos(x) //返回x的反余弦值

Math.asin(x) //返回x的反正弦值

Math.atan(x) //返回x的反正切值

Math.atan2(y,x) //返回y/x的反正切值

Function类型
   函数实际上是对象,每个函数都是Function类型的实例。而且具有属性和方法。
   函数通常使用函数声明语法定义,function sum() {  }   解析器会率先读取函数声明,确保可在任何地方访问。
   函数表达式定义函数:var sum = function() {  }; 和普通的声明变量一样,末尾需加分号。
   是用不带圆括号的函数名是访问函数指针,而不是调用函数。
   因为函数名是变量,所以一个函数可以当成参数被传递到另一个函数,也可以将一个函数作为另一个函数的结果返回。
   函数的内部属性:函数内部有两个特殊的对象:argumentsments和this,arguments的主要作用是保存函数参数,但这个对象还有一个名叫caller的属性,该属性是一个指针,指向拥有这个arguments的函数。
       函数的另一个特殊对象是this,this引用的是函数据以执行的环境对象,即谁调用指向谁。
    函数的caller属性保存着调用当前函数的函数的引用。
函数的属性和方法: length和prototype。length指函数参数的个数。prototype保存所有实例方法的真正所在,不可枚举。
     每个函数都包含两个非继承来的方法:apply()和 call() 。这两个方法能够扩展函数赖以运行的作用域,即改变函数内的this指向。apply(指定this,参数数组)  call(指定this,列举的参数)。
     ECMAScript韩定义了一个方法:bind(),会创建一个函数的实例,其this值会绑定到传给bind()的值。

2.基本包装类型
   为了便于操作基本类型值,ECMAScript还提供了3个特殊的引用类型:Boolean,Number,String。后台处理过程:1.创建一个引用类型的实例,2在实力上调用方法,3销毁这个实例。
   不建议直接实例化Boolean、Number类型,因为在使用type和instanceof操作符测试通过实例化得到的引用类型值时,得到的是object,会混淆期望的基本类型值类型。
   Number类型提供了一些将数值格式化Wie字符串的方法:toFixed()会按照传入的参数返回相应小数位的字符串表示,能够自动四舍五入。  toExponential()返回指数表示法的字符串表示。  toPrecision()接受一个参数表示所有数值的位数,返回最合适的格式。
   String类型:1.字符方法:charAt()接受字符位置,返回相应位置的字符。   charCodeAt() 返回相应字符的字符编码。  用方括号表示:var str = 'a,b,c'; alert(str[1]);得到‘b',IE8+支持。
       2.字符串操作方法:不改变原字符串。
              contact()拼接字符串,不建议使用,用“+”加号进行字符串的拼接。
              slice(开始位置,结束位置的后一位)。当参数为负数时。将负数与字符串长度相加。
              substring(开始位置,结束位置的后一位)。特点:将较小的数放在前边。当第一个参数为负数时,加上字符串的长度;当第二个参数为负数的时候,将负数转为0;
              substr(开始位置,要截取的字符个数)。当参数为负数时,转为0。
        3.indexOf()查找字符在字符串的位置;
           trim()删除字符前后空格;
           toLowerCase()转换为小写,toUpperCase()转换为大写。
           split()将字符按分隔符分隔,将结果存在数组中。
           localeCompare()比较字符串。
           fromCharCodeAt()将编码转成字符。

访问对象属性使用点表示法,也可以用方括号把属性名字以字符串形式放到方括号中来访问。

2:Array类型的length属性不但可以读取长度,也可以通过设置length,从数组末尾项增加或删除新项。栈方法:push(),pop().队列方法:shift(),unshift().重排序:reverse(),sort(),操作方法:concat(),slice(),splice().

3:每个函数都是Function类型的实例,函数名实际上是指向函数的指针,不会与某个函数绑定。使用不带括号的函数名是访问函数指针,不是调用函数。

4:解析器会率先读取函数声明,并使其可以在执行任何代码之前可以访问,对于函数表达式,则必须等待解析器执行到他所在的代码行才会被解释执行。除此以外,函数声明与函数表达式是等价的。

5:作为值的函数:函数名本身就是变量,所以函数也可以作为值来使用。不仅可以向传递参数一样把一个函数传递给另一个函数,也可以将函数作为另一个函数的结果返回。想要访问函数的指针而不执行函数,去掉圆括号。

6:函数内部有两个特殊对象,arguments和this。arguments主要用于保存函数参数,这个对象还有一个callee属性,这是一个指针,指向拥有这个arguments对象的函数。this引用的是函数据以执行操作的对象。

7:每个函数都包含两个属性,length和prototype。length表示希望接收到的参数的个数。对于引用类型而言,prototype是保存他们所有实例对象的真正所在。

8:每个函数都包含两个非继承而来的方法:apple()和call(),第一个参数是在其中执行函数的作用域,第二个参数是参数数组。apply()的第二个参数可以传数组和arguments对喜爱那个。call()的第二个参数只能把要传递的参数逐个列举。他们的作用是扩充函数赖以执行的作用域。

9:每当读取一个基本类型值的时候,后台会创建一个对应的基本包装类型的对象,从而可以使我们调用一些方法来操作这些数据。(因为基本类型值不是对象,所以他们本不该有方法)基本包转类型有:Boolean类型,Number类型,String类型。

10:在全局作用域中声明的所有变量和函数,都是window对象的属性。

引用类型是一种数据结构,它们描述的是一类对象所具有的属性和方法,常被称为类。
5.1 Object类型
1.创造Object实例方式:第一种使用new操作符后跟Object构造函数——var person = new Object(); 第二种使用对象字面量表示法——var person = {name:”yanglonglong”, age:22}; 常使用第二种。
2.访问对象属性:第一种使用点表示法——person.name; 第二种使用方括号,将要访问的属性以字符串的形式放在方括号中——person[“name”]; 常用第一种。
5.2 Array类型
1.Array数组每一项可以保存任何不同类型的数据,大小可以动态调整。
2.创建数组方式:第一种使用Array构造函数——var colors = newArray(); 括号中可选参数有数组的长度、数据初始化数据项。第二种使用数组字面量表示法——var colors = [“red”,”blue”,”green”];
3.访问数组的值,使用方括号并提供基于0的数字索引——colors[1]; 若设置某个值的索引超过了数组现有的项数,数组会自动增加到该索引值加一的长度。
5.2.1 检测数组
if(value instanceof Array){//对数组进行操作}
当多个框架冲突:if(Array.isArray(value)){//对数组进行操作}
5.2.2 转换方法
toString()返回数组中每个值的字符串形式拼接而成的以逗号分格的字符串。
valueOf()返回数组,为数组每项都调用toString()方法。
toLocaleString()犯法为数组没项都调用toLocaleString()方法。
join()方法使用不同分隔符来构建字符串,接受一个参数——用作分隔的字符串(默认为逗号),返回包含所有项的字符串。
5.2.3 栈方法
栈——插入移除都发生在栈的末尾,后进先出。通过push()和pop()实现。
push()方法接受任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。pop()方法从数组末尾移出最后一项,减少数组的length值,返回移出的项。
5.2.4 队列方法
队列——在列表末尾插入项,在列表前端移除项,先进先出。通过push()和shift()实现。
shift()移除数组第一项并返回该项。
unshift()在数组前端添加任意数量的项,返回新数组的长度。
5.2.5 重排序方法
reserve()会反转数组项中的顺序。
sort()按升序排列数组项——最小值位于最前面。
sort()比较的是ASCII码。sort()接受一个比较函数作为参数,以便指定哪个值位于哪个值前面。比较函数接受两个参数,若第一个参数应该位于第二个参数之前,则返回一个负数,相等返回零。对于数值类型升序排序:function compare(value1,value2){return value1-value2;} ,调用数组的sort(compare);就可以直接改变数组顺序——会影响原来数组。
5.2.6 操作方法
connect()可以基于当前数组中的所有项创建一个新数组,若给connet()传递一个或多个数组,该方法将这些数组中的每一项添加到结果数组中;若传递的值不是数组,这些值被简单地添加到结果数组的末尾,最后返回结果数组。
slice()接受一个或两个参数:只有一个参数——slice()返回从该参数指定位置开始到数组末尾所有项;有两个参数——返回起始位置和结束位置的项,但不包括结束位置项,不会影响原来数组。若参数为负数,则用数组长度加上该负数来确定相应的位置。
splice()方法——向数组中部插入项,三种方式:删除——splice(要删除的第一项位置,要删除的项数)、插入——splice(要删除的第一项位置,要删除的项数0,要插入的项),替换——splice(要删除的第一项位置,要删除的项数,要插入的项),返回包含从原始数组中删除的项组成的数组。
5.2.7 位置方法
indexOf()与lastIndexOf()接受两个参数:(要查找的项,表示查找起点位置的索引(可选的)),indexOf()从数组开头开始向后查找,lastIndexOf()从数组末尾开始向前查找。都返回要查找的项在数组中的位置,在没找到返回-1。
5.2.8 迭代方法
every(): 对数组中的每一项运行给定函数,若函数每一项都返回true,则返回true。
some(): 对数组中的每一项运行给定函数,若函数对任一项返回true,则返回true。
filter(): 对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组。
map(): 对数组中的每一项运行给定函数,返回每次函数每次调用的结果组成的数组。
forEach():对数组中的每一项运行给定函数,没有返回值。
每个方法接受两个参数:(要在每一项上运行的函数,运行该函数的作用域(可选的)),传入这些方法的函数有三个参数:(数组项的值item,该项在数组中的位置index,数组对象本身array)。
5.2.9 缩小数组的方法
reduced()和reduceRight()都会迭代数组中所有项,然后一个最终返回的值。
接受两个参数:(在每一项上运行的函数,作为缩小基础的初始值(可选的)),传入reduced()和reduceRight()的函数接受四个参数(前一个只prev,当前值cur,项的索引index,数组对象array)。函数的返回的任何值都会作为第一个参数自动传给下一项。
5.3 Date类型
Date类型使用来自UTC(Coordinated Universal Time)1970年1月1日零时开始经过的毫秒数来保存日期。
创建一个日期对象newnow = new Date();
Date.parse()接受一个表示日期的字符串参数,返回相应日期的毫秒数/NaN。
Date.UTC()参数分别是:年份、基于0的月份、基于1的日期、基于0的小时数、分钟数、秒数、毫秒数。若省略参数,则设为0。
Date.noew()方法返回调用这个方法时的日期和时间的毫秒数。
5.3.1 继承的方法
toLocateString()方法会按照与浏览器的地区相适应的格式返回日期和时间。
toString()返回带有时区信息的日期和时间。
valueOf()返回日期的毫秒表示。
5.3.2 日期格式化方法
toDateString():以特定格式显示星期几、月、日、年。
toTimeString():以特定格式显示时、分、秒、时区。
toUTCString():以特定格式显示完整的时、分、秒。
5.3.3 日期/时间组件方法
getTime():返回表示日期的毫秒数。
setTime():以毫秒数设置日期,会改变整个日期。
getFullYear():获取四位数的年份。
Month月,Date日,Hours时,Minutes分,Seconds秒,Milliseconds毫秒。
getTimezoneOffset():返回本体时间与UTC时间相差的分钟数。
5.4 RegExp类型
ECMAScript通过RegExp类型支持正则表达式。
创建一个正则表达式
① 以字面量形式定义正则表达式——var expression = / pattern / flags; 其中pattern是正则表达式,可以包括字符类、限定符、分组、向前查找以及反向引用。flags用以标明正则表达式的匹配模式(行为):g——全局模式,表示正则表达式将被用于所有字符串;i——表示不区分大小写;m——表示多行模式,到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。
② 以RegExp构造函数定义正则表达式,它接受两个参数:(要匹配的字符串模式,标志字符串(可选的))——var expression = newRegExp(“/[bc]at”,”i”);匹配第一个“bat”或者“cat”,不区分大小写。RegExp构造函数的模式参数是字符串,所有元字符必须双重转义。
2.正则表达式需要转移的字符:() [] {} + * ^ & | ? . /
5.4.1 RegExp实例属性
global:布尔值,表示是否设置了g标志。
ignoreCase:布尔值,表示是否设置了i标志。
multiline:布尔值,表示是否设置了m表示。
lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0开始。
sourse:正则表达式的字符串表示,按照字面量形式,而非传入构造函数中的字符串模型返回。
5.4.2 RegExp实例方法
exec()专门为捕获组设计,接受一个参数:(要应用模式的字符串),返回包含第一个匹配项信息的数组/null,该数组包括两个额外属性:index——表示匹配项在字符串中的位置,input——表示应用正则表达式的字符串。返回的数组中第一项是与整个模型匹配的字符串,其他项是与模式中捕获组匹配的字符串。
test()方法接受一个字符串参数,该模式与该参数匹配的情况下返回true,否则返回false。常用在if语句中。
toLocaleString()和toString()方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。
valueOf()方法返回正则表达式本身。
5.4.3 RegExp构造函数属性
这些属性适用于作用域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化。
input,$_ 最近一次要匹配的字符串。
lastMatch $& 最近一次的匹配项。
lastParen $+ 最近一次匹配的捕获组。
leftContex $^ input字符串中lastMatch之前的文本
multiline $* 布尔值,表示是否所有表达式都使用多行模式。
rightContext $` input字符串中lastMatch之后的文本。
RegExp.1,RegExp.2,……,RegExp.$9 用于存储第一、第二、……、第九个匹配的捕获组。
这些属性可以从exec()或test()执行的操作中提取出更具体的信息。
5.4.4 模式的局限性
不支持的特性包括:匹配字符串开始和结尾的/A和/Z锚;向后查找lookbehind;并集和交集类;原子组;Unicode支持(单个字符除外,如/uFFFF);命名的捕获组;s单行和x无间隔的匹配模式;条件匹配;正则表达式注释。

猜你喜欢

转载自zhyp29.iteye.com/blog/2304137