JS面向对象笔记

菜单导航

一、js零散笔记

二、Array数组

三、数值、字符串、布尔三大包装对象

四、Number

五、Math

六、Date

七、正则表达式(Regular Expression)

 

一、js零散笔记

0、匿名函数定以后直接调用:(function(numA, numB) { alert(numA + numB); })(3,4);//弹窗7

1、js中函数就是对象,对象就是函数。arguments表示函数的参数集合

2、js中方法直接调用为函数,用new调用为对象。JavaScript中没有类的语法,是用函数闭包模拟出来的

3、js中给对象动态添加属性示例:

//定义一个函数 
function Person(){

}

//1、直接调用函数名,就只是单纯的表示调用函数
Person();

//2、是用new,表示创建了一个对象,js是动态语言,可以给对象动态添加属性和方法
var per = new Person();
per.name = "大锤";    //给per对象动态添加属性name
per.age = 26;         //给per对象动态添加属性age
per.sayHi = function() { alert("hello"); }//给per对象动态添加方法sayHi

//调用per对象的属性和方法
alert(per.name);//或者alert(per['name']);
per.sayHi();
View Code

4、js中支持this关键字,通过this关键字为对象的属性赋值

function Person(name, age) {
     this.name = name;    //给Person添加name属性,再把参数name的值赋值给该属性
     this.age = age;
     this.sayHi = function () { alert("My name is " + this.name + ", I'm old " + this.age); }
}

//调用
var per = new Person("大锤", 26);
per.sayHi();//弹窗。。。。。
View Code

function Person(name, age)可以看做是声明构造函数,name、age这些属性也是动态添加的,new相当于创建了函数的一个实例

5、String对象方法学习

  String对象是JavaScript原生提供的三个包装对象之一,用来生成字符串的包装对象。

  • length属性:获取字符串的字符个数(无论中文字符还是英文字符都算1个字符)
  • charAt(index)方法:获取指定索引位置的字符(索引从0开始)
  • indexOf('字符串', startIndex)方法:获取指定字符串中第一次出现的位置,startIndex表示从第几个开始搜索
  • split('分隔符', limit): 根据分隔符将一个字符串返回为一个数组。limit表示要返回的数组的最大长度(可自定义)
  • substr(startIndex, len) : 从startIndex开始,截取len个字符
  • substring(startIndex, stopIndex): 从startIndex开始,截取到stopIndex位置(不包括stopIndex所在的字符)
  • toUpperCase(): 转换大写
  • toLowerCase(): 转换小写
  • concat方法用于连接两个字符串,返回一个新字符串,不改变原字符串
  • slice方法用于从原字符串取出子字符串并返回,不改变原字符串。
  • match()、replace()、search()方法和正则表达式有关
  • .....
//1、String对象构造函数使用
console.log(new String('abc'));
//String {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}


//2、String对象作为工具方法使用,将任意类型的值转化为字符串
console.log(String(true)); //将布尔类型true转成字符串"true"
console.log(5);    //将数字5转成字符串"5"


//3、String.fromCharCode(): String对象提供的静态方法(即定义在对象本身,而不是定义在对象实例的方法),该方法的参数是一系列Unicode码点,返回对应的字符串

console.log(String.fromCharCode(104, 101, 108, 108, 111, 97)); //helloa
//另外该方法不支持Unicode码点大于0xFFFF的字符,即传入的参数不能大于0xFFFF
//举例说明Unicode码点0x20BB7实际上只能取到0x0BB7, 因为码点大于0xFFFF的字符占用四个字节,而JavaScript只支持两个字节的字符。这种情况下,需要把0x20BB7拆成两个字符表示
console.log(String.fromCharCode(0x20BB7));  //
console.log(String.fromCharCode(0xD842, 0xDFB7)); //



//String实例对象的属性方法
//4、length属性,返回字符串的长度
console.log('abc'.length);  //3

//5、charAt(); 返回指定位置的字符,参数是从0开始编号的位置
var a = new String('abc');
console.log(a.charAt(1));  //b
console.log(a.charAt(a.length-1)); //c
console.log(a[1]);    //b 

//6、charCodeAt(); //返回给定位置字符的Unicode码点(十进制表示),相当于String.fromCharCode()的你操作
console.log('abc'.charCodeAt(1)); //98
String.fromCharCode(98); //b

//7、concat() : 用于连接两个字符串,返回一个新字符串,不改变原字符串
var s1 = 'abc', s2 = 'efg';
var s3 = s1.concat(s2);
var s4 = s1.concat(s2, '^_^', 'zzz');
console.log(s3);    //abcefg
console.log(s4); //abcefg^_^zzz

//8、slice() : 用于从原字符串取出字符串并返回,不改变原字符串
//它的第一个参数是子字符串的开始位置, 第二个参数是子字符串的结束位置(不含该位置)
var a = 'abcdefgzzzZDG';
console.log(a.slice(1, 3)); //bc
console.log(a.slice(2)); //cdefgzzzZDG  //省略第二个参数,字符串一直到原字符串结束
//如果参数是负数,表示从结尾开始倒数计算的位置,即该负值加上字符串长度
console.log(a.slice(1, -6)); //bcdefg
console.log(a.slice(-2, -5)); //不存在,提取为空
console.log(a.slice(-5, -2)); //zzZ
View Code
//9、substring() : 从原字符串取出子字符串并返回,不改变原字符串。它与slice作用相同,建议优先使用slice
//substring(): 第一个参数表示子字符串的开始位置, 第二个位置表示结束位置
var a = 'abcdefgZABC';
console.log(a.substring(1, 3)); //bc
console.log(a.substring(1));  //bcdefgZABC
//如果第二个参数大于第一个参数,substring方法会自动更换两个参数的位置
console.log(a.substring(6, 3)); //def
//如果参数是负数,substring方法会自动将负数转为0
console.log(a.substring(-1)); //abcdefgZABC
console.log(a.substring(4, -1)); //abcd

//10、substring() : 从原字符串取出子字符串并返回,不改变原字符串
//第一个参数是子字符串的开始位置, 第二个参数是子字符串的长度
console.log(a.substr(1, 3)); //bcd
console.log(a.substr(6)); //gZABC
//如果第一个参数是负数,表示倒数计算的字符位置;第二个参数是负数,将自动转为0
console.log(a.substr(-5)); // gZABC
console.log(a.substr(4, -1)); //提取出空字符串

//11、indexOf(), lastIndexOf()
var a = 'abcabcdf';
console.log(a.indexOf('c')); //2
console.log(a.lastIndexOf('c')); //5

//12、trim() : 去除字符串两端的空格,返回一个新字符串,不改变原字符串
console.log('    hello    '.trim()); //hello

//13、toLowerCase(), toUpperCase()
console.log('ABCDefgHIJ'.toLowerCase()); //abcdefghij
console.log('abcdEFGhijk'.toUpperCase()); //ABCDEFGHIJK

//14、localeCompare() : 用于比较两个字符串。它返回一个整数,如果小于0,表示第一个字符串小于第二个字符串;如果等于0,表示两者相等;如果大于0,表示第一个字符串大于第二个字符串。
console.log('apple'.localeCompare('Appaaa'));  //1
console.log('apple'.localeCompare('apple'));   //0
console.log('apple'.localeCompare('appZZ'));   //-1

//15、match() : match方法用于确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的第一个字符串。如果没有找到匹配,则返回null。
console.log('cat-bat-gat-cat-at-fat'.match('cat')); //["cat", index: 0, input: "cat-bat-gat-cat-at-fat"]

//16、search(): 用法等同于match, 但是返回值为匹配的第一个位置。如果没有找到匹配,则返回-1
console.log('cat, bat, fat, gat'.search('fat')); //10 

//17、replace(): replace方法用于替换匹配的子字符串,一般情况下只替换第一个匹配(除非使用带有g修饰符的正则表达式)。
console.log('aaa'.replace('a', 'BBB')); //BBBaa

//18、split(): 按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。
console.log('a-b-c'.split('-')); //(3) ["a", "b", "c"]
console.log('a-b-c-d'.split('-', 2)); //(2) ["a", "b"]
View Code

 6、扩展方法:通过类对象的prototype设置扩展方法

//给string对象扩展一个方法addSign(sign);
String.prototype.addSign = function (sign) {

        if (!sign) {//如果sign是空
              sign = "^_^";
        }
        return sign + this + sign;
}

//调用测试
var str = "chui";
alert(str.addSign());  //弹出内容:^_^chui^_^
alert(str.addSign("***"));//弹出内容:***chui***
View Code

 7、运算符的优先级:
  7.1、关系操作符:>,   <,  >=,  <=,  ====,  ==,  !=,   !==
     条件操作符:a?b:c
    赋值运算符:+=,   -=,   *=,   /= ,  %=
    逗号运算符: ,
  7.2、运算符的优先级:
    第一位: ()
    第二位:!、-+、++、--
    第三位:*、/、%
    第四位:+、-
    第五位:<、<=、>、>=
    第六位:==、!=、===、!==
    第七位:&&
    第八位: ||
    第九位:?:
    第十位:=、+=、-=、*=、/=、%=

/*  num>0: num&&0==0(true&&false==false), 0&&num==0, num1&&num2 == num2(最后一个)
num||0==num, 0||num==num(true||false==true), num1||num2 == num1(最开始一个不为0的)
0&&num1&&num2(false&&true&&true==false),
num1&&num2&&num3 == num3 (最后一个),
num1||0||num2==num1, 0||num1||num2 == num1, num1||num2||num3 == num1,
0||num1&&num2 == num2, num1||0&&num2 == num1, num1||num2&&0 == num1,
0&&num1||num2 == num2(false&&true||true==true), 
*/
console.log(1&&0, 2&&0, 0&&1, 0&&2, 4&&5); //0 0 0 0 5
console.log(1||0, 2||0, 0||1, 0||2, 4||5); //1 2 1 2 4
console.log(1&&0&&2, 0&&2&&3, 1&&2&&3);    //0 0 3
console.log(1||0||2, 0||1||2, 1||2||3);    //1 1 1
console.log(0||1&&2, 1||0&&2, 1||2&&0, 0||1&&2&&3&&4, 0||1&&2&&3||0&&5&&6); //2 1 1 4 3
console.log(0&&1||2, 1&&0||2, 1&&2||0);    //2 2 2
console.log(false&&true||true)             //true
console.log(2+8&&5, 8&&5+2, 10-8&&1, 8&&1-10) //5 7 1 -9  (+-优先级大于&&)
console.log(2+8||5, 8||5+2, 10-8||1, 8||1-10) //10 8 2 8  (+-优先级大于||, &&优先级大于||)
View Code

 

二、Array数组

 Array常用方法

  a、添加元素到第一个:unshift() 

  b、添加元素到最后一个:push()

  c、删除第一个元素:shift()

  d、删除最后一个元素:pop()

  e、删除指定元素:splice()

    举例:var aa = [11, ‘aa’, 518, ‘cc’];  aa.splice(1, 1); //删除第二个元素

  f、添加元素到指定位置

    举例:var aa = [‘aa’, ‘cc’, 55];  aa.splice(1, 0, ‘dd’, ‘ee’); //将元素’dd’, ‘ee添加到索引1位置

  g、遍历元素:map(), forEach();

  h、数组元素连接成字符串:join(),   数组之间的合并:concat()

  i、查找元素索引:indexOf(),  lastIndexOf()

  j、部分元素提取:slice()

  k、元素反转: reverse()

  l、元素排序: sort()

  m、元素遍历累计:reduce() ,  rightReduce() 

  n、数组元素过滤: filter()

 

 Array.isArray方法用来判断一个值是否为数组。它可以弥补typeof运算符的不足。

var a = [1, 2, 3];
console.log(typeof a) 
console.log(Array.isArray(a))

/** 打印结果:
object
true
*/
View Code

Array的实例方法:

1、valueOf(),toString()

   valueOf() : 返回数组本身;

 toString() : 返回数组的字符串形式

var a = [1, 2, 3];
console.log(a.valueOf());
console.log(a.toString());

/** 日志
[1, 2, 3]
1,2,3
*/
View Code

 

2、push()

     用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。该方法会改变原数组。

var a = []; 
a.push("one");
console.log(a);

a.push("two", 222, true, {});
console.log(a);

a.push([3, 8]);
console.log(a);

/** 日志 : 
["one"]
["one", "two", 222, true, Object]
["one", "two", 222, true, Object, Array(2)]
*/
View Code

合并两个数组:

var a = [1, 2, 3];
var b = [4, 5, 6];

Array.prototype.push.apply(a, b);
// 或者 a.push.apply(a, b)
// 上面两种写法等同于
//a.push(4, 5, 6)

console.log(a);   // [1, 2, 3, 4, 5, 6]
View Code

 

3 、pop()

  用于删除数组的最后一个元素,并返回该元素。该方法会改变原数组

var a = ['a', 'b', 'c'];
console.log(a);  // ["a", "b", "c"]

a.pop(); 
console.log(a);   // ["a", "b"]

a.pop();
a.pop();
console.log(a);  // []

a.pop();  //空数组使用pop方法,不会报错,返回undefined。
console.log(a);  // []
View Code

 

4、join()

  方法以参数作为分隔符,将所有数组成员组成一个字符串返回。如果不提供参数,默认用逗号分隔

var a = [1, 'aaa', 33, 88, {"name":"大锤"}];
console.log(a.join());        //1,aaa,33,88,[object Object]
console.log(a.join(' | '));  // 1 | aaa | 33 | 88 | [object Object]
console.log(a.join('^_^'));  // 1^_^aaa^_^33^_^88^_^[object Object]

 

5、concat()

  用于多个数组的合并。它将新数组的成员,添加到原数组的尾部,然后返回一个新数组,原数组不变。

var a = [1, 2, 3];
var b = [4, 5, 6];
var c = a.concat(b);

console.log(a);   //[1, 2, 3]
console.log(b);  //[4, 5, 6]
console.log(c);  //[1, 2, 3, 4, 5, 6]
 
c = c.concat(7, 8, 'hello');
console.log(c);   //[1, 2, 3, 4, 5, 6, 7, 8, "hello"]
c = c.concat(9, ['大锤', 88]);
console.log(c);   //[1, 2, 3, 4, 5, 6, 7, 8, "hello", 9, "大锤", 88]
View Code

6  shift()

  用于删除数组的第一个元素,并返回该元素。该方法会改变原数组

var a = [1, 2, [1,2], {}];
console.log(a);  //[1, 2, Array(2), Object]

a.shift();
a.shift();
console.log(a);   // [Array(2), Object]

a.shift();
a.shift();
a.shift();
console.log(a);  // []
View Code

  pushshift结合使用,就构成了“先进先出”的队列结构(queue)。

7 unshift()

  用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。该方法会改变原数组  

var a = ['a', 'b', 'c'];
console.log(a);    //["a", "b", "c"]

a.unshift('xxx');
console.log(a);     // ["xxx", "a", "b", "c"]

a.unshift('zzz', 'yyy');
console.log(a);    //["zzz", "yyy", "xxx", "a", "b", "c"]
View Code

8 reverse()

  用于颠倒数组中元素的顺序,返回改变后的数组。该方法将改变原数组。

var a = ['a', 'b', 'd'];
a.reverse();
console.log(a);   //["d", "b", "a"]
View Code

slice()

  方法用于提取原数组的一部分,返回一个新数组,原数组不变。

var a = ['a', 88, 'b', 'zz', 22];

console.log(a.slice(1,3));   //[88, "b"]
console.log(a.slice(2, 1));   // []
console.log(a.slice(2, 4));  // ["b", "zz"]
console.log(a.slice(2));   //["b", "zz", 22]
console.log(a.slice());   //['a', 88, 'b', 'zz', 22]
View Code

  slice方法的一个重要应用,是将类似数组的对象转为真正的数组:

var a = Array.prototype.slice.call({0:1, 1:2, 2:'aaa', length:3});
console.log(a);  //[1, 2, "aaa"]
View Code

10 splice()

  用于删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员,返回值是被删除的元素。该方法会改变原数组。

  splice的第一个参数是删除的起始位置,第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素

var a = [1, 'a', 'b', 'c', 'zzz', 88];
a.splice(2, 3);
console.log(a);   //[1, "a", 88]

//只传入一个参数,表示从这个索引开始,后面所有删除
a.splice(1);
console.log(a);  //[1]

//删除的同时增加其他元素
a.splice(1, 0, 'aaa', 'bbb', 888);
console.log(a);  //[1, "aaa", "bbb", 888]
View Code

 

11  sort()

  对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变

var a = ['aaa', 'abc', 'kkk', 'eee', 'acc', 'bbb'];
console.log(a);  //["aaa", "abc", "kkk", "eee", "acc", "bbb"]

a.sort();
console.log(a);  //["aaa", "abc", "acc", "bbb", "eee", "kkk"]
View Code

sort方法不是按照大小排序,而是按照对应字符串的字典顺序排序; 

可以自定义排序方式:

var a = [1, 2, 88, 33, 999, 666];
a.sort(function(v1, v2){
    return v1 - v2;
});
console.log(a);  //[1, 2, 33, 88, 666, 999]

a.sort(function(v1, v2){
    return v2 - v1;
});
console.log(a);  //[999, 666, 88, 33, 2, 1]



//对象自定义排序
var a = [
    {name:"大锤", age:30},
    {name:"张三", age:20},
    {name:"李四", age:40},
    {name:"王二", age:50},
    {name:"赵六", age:18},
];
a.sort(function(v1, v2){
    return v1.age - v2.age;
});

for (var i = 0; i < a.length; i++){
    console.log(a[i].name + ": " + a[i].age);
}
/** 日志:
赵六: 18
张三: 20
大锤: 30
李四: 40
王二: 50
*/
View Code

 

12   map()

  对数组的所有成员依次调用一个函数,根据函数结果返回一个新数组。

var a = [1, 2, 3];

var b = a.map(function(n){
    return n*n;
});
console.log(a);  //[1, 2, 3]
console.log(b);  //[1, 4, 9]


//方法接受一个函数作为参数。该函数调用时,map方法会将其传入三个参数,分别是当前成员、当前位置和数组本身。

var c = a.map(function(ele, index, arr){
    return ele * index;
});
console.log(c);  //[0, 2, 6]
View Code

  map方法不仅可以用于数组,还可以用于字符串,用来遍历字符串的每个字符。但是,不能直接使用,而要通过函数的call方法间接使用,或者先将字符串转为数组,然后使用。

//第一个中写法
var a = Array.prototype.map.call('abc', function(x){
    return x.toUpperCase();
});
console.log(a);   //["A", "B", "C"]

//第二种写法
var a = [].map.call('abc', function(x){
    return x.toUpperCase();
});
console.log(a);    //["A", "B", "C"]

//第三种写法
var upper = function(x){
    return x.toUpperCase();
}
var a = Array.prototype.map.call('abc', upper);
console.log(a);   //["A", "B", "C"]
View Code

 

13   forEach()

  forEach方法与map方法很相似,也是遍历数组的所有成员,执行某种操作,但是forEach方法一般不返回值,只用来操作数据。如果需要有返回值,一般使用map方法。

  forEach方法的参数与map方法一致,也是一个函数,数组的所有成员会依次执行该函数。它接受三个参数,分别是当前位置的值、当前位置的编号和整个数组。 

var a = [22, 33, 11, 88, 66];

//第一种写法
a.forEach(function(ele, index, arr){
    console.log('a[' + index + '] = ' + ele + '; //' + arr[index]);
});


//第二种写法
console.log('......第二种写法.....');
function log(ele, index, arr){
    console.log('a[' + index + '] = ' + ele + '; //' + arr[index]);
}
a.forEach(log);

/** 打印日志:
a[0] = 22; //22
a[1] = 33; //33
a[2] = 11; //11
a[3] = 88; //88
a[4] = 66; //66
......第二种写法.....
a[0] = 22; //22
a[1] = 33; //33
a[2] = 11; //11
a[3] = 88; //88
a[4] = 66; //66
*/
View Code

 

  forEach方法也可以接受第二个参数,用来绑定回调函数的this关键字; 

  这个参数对于多层this非常有用,因为多层this通常指向是不一致的。

var out = [];

[1, 2, 3].forEach(function(elem) {
  this.push(elem * elem);
}, out);

console.log(out);  //[1, 4, 9]
View Code
var obj = {
  name: '张三',
  times: [1, 2, 3],
  print: function () {
    //第一个this指的是obj对象
    this.times.forEach(function (n) {
      console.log(this.name + ': ' + n);  //这个this指的是obj对象
    }, this);
  },
  print2: function(){
     this.times.forEach(function(n){
        console.log(this.name + ': ' + n);  //这个this指的是指向顶层对象window
      });
  }
};

/** 打印日志:
.....print....
张三: 1
张三: 2
张三: 3
....print2....
: 1
: 2
: 3
*/
View Code

 

  关于数组的for循环和forEach 对于关键字continue、break、return的支持

  for循环里支持continue、break、return关键字,continue进入下一个循环;break跳出循环;return直接返回不再往下执行代码;

  forEach不支持continue和break(使用会运行报错), 支持return关键字;碰到return表示跳出当前循环,执行下一个循环; map同forEach

function testOne(){
    var a = [1, 2, 3, 4, 5];

    console.log('... for -- continue ...');
    for (var i = 0; i < a.length; i++){

        if (i > 1 && i<3){
            continue;
        }
        console.log(a[i]);
    }

    console.log('... for -- break ...');
    for (var i = 0; i < a.length; i++){
        if (i > 1 && i<3){
            break;
        }
        console.log(a[i]);
    }

    console.log('... for -- return ...');
    for (var i = 0; i < a.length; i++){
        if (i > 1 && i<3){
            return;  //返回,后面的代码不再执行
        }
        console.log(a[i]);
    }

    console.log('.....testOne end.....');
}

function testTwo(){
    var a = [1, 2, 3, 4, 5];

    console.log('... forEach -- return ...');
    a.forEach(function(el, i){
        if (i > 1 && i<3){
            return;  //跳出当前循环,执行下一个循环,相当于for循环中的continue关键字效果
        }
        console.log(a[i]);
    });

    console.log('.....testTwo end.....');
}

testOne();
testTwo();

/** 打印日志:
... for -- continue ...
2
5
.. for -- break ...
2
... for -- return ...
2
... forEach -- return ...
2
5
.....testTwo end.....
*/
View Code

 

14  filter()

  filter方法的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。

var a = [1, 2, 3, 4, 5];
var b = a.filter(function(ele){
    return ele > 3;
});

console.log(a);   // [1, 2, 3, 4, 5]
console.log(b);  //[4, 5]
View Code

 

15  some(),every()

  这两个方法类似“断言”(assert),用来判断数组成员是否符合某种条件。

  它们接受一个函数作为参数,所有数组成员依次执行该函数,返回一个布尔值。该函数接受三个参数,依次是当前位置的成员、当前位置的序号和整个数组。

  some方法是只要有一个数组成员的返回值是true,则整个some方法的返回值就是true,否则false

var a = [1, 2, 3, 4, 5];
var b = a.some(function(ele, index, arr){
    return ele >= 3;
});
console.log(b);  //true

var c = a.every(function(ele, index, arr){
    return ele >= 3;
});
console.log(c);  //false
View Code

 

16   reduce(),reduceRight()

  reduce方法和reduceRight方法依次处理数组的每个成员,最终累计为一个值。

  它们的差别是,reduce是从左到右处理(从第一个成员到最后一个成员),reduceRight则是从右到左(从最后一个成员到第一个成员),其他完全一样。 

  

  这两个方法的第一个参数都是一个函数。该函数接受以下四个参数。

  1) 累积变量,默认为数组的第一个成员

  2)当前变量,默认为数组的第二个成员

  3)当前位置(从0开始)

  4)原数组

  这四个参数之中,只有前两个是必须的,后两个则是可选的。

var a = [1, 2, 3, 4, 5];
var b = a.reduce(function(x, y){
    console.log(x, y);
    return x + y;
});

console.log(b);

/** 日志:
1 2
3 3
6 4
10 5
15
*/
View Code

  利用reduce方法,可以写一个数组求和的sum方法。

Array.prototype.sum = function(){
    
    var tmp = this.reduce(function(partial, value){
        var num = partial + value;
        console.log(String(partial) + '+' + String(value) + '=' + num);
        return num;
    });
    
    console.log('tmp = ' + tmp);
    console.log(this);  //this指当前数组对象
    return tmp;
}

var result = [1, 2, 4, 8, 16, 32].sum();
console.log('result = ' + result);

/** 打印日志:
1+2=3
3+4=7
7+8=15
15+16=31
31+32=63
tmp = 63
(6) [1, 2, 4, 8, 16, 32]
result = 63
*/
View Code

  如果要对累积变量指定初值,可以把它放在reduce方法和reduceRight方法的第二个参数。

[1, 2, 3, 4, 5].reduce(function(x, y){
  return x + y;
}, 10);
//25  //10+1+2+3+4+5=25
View Code

 

17   indexOf(),lastIndexOf()

  indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1;

  lastIndexOf方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1;

var a = ['aaa', 'bbb', 'ccc', 'ddd', 'ccc', 'aaa'];
console.log(a.indexOf('aaa'));    //0
console.log(a.indexOf(2));        // -1
console.log(a.lastIndexOf('aaa'));    // 5
View Code

18  数组的链式使用

  上面这些数组方法之中,有不少返回的还是数组,所以可以链式使用。

var users = [
  {name: 'tom', email: 'tom@example.com'},
  {name: 'peter', email: 'ttpeter@example.com'}
];

users
.map(function (user) {
  return user.email;
})
.filter(function (email) {
  return /^tt/.test(email);  //正则匹配出tt开头的字符串
})
.forEach(alert);
//最后弹出ttpeter@example.com
View Code

 

 

三、数值、字符串、布尔值三大包装对象

  1、数组和函数本质上都是对象,就连三种原始类型的值——数值、字符串、布尔值——在一定条件下,也会自动转为对象,也就是原始类型的“包装对象”。

  2、所谓“包装对象”,就是分别与数值、字符串、布尔值相对应的NumberStringBoolean三个原生对象。这三个原生对象可以把原始类型的值变成(包装成)对象。

var a = 123, b = 'abc', c = true;
console.log(typeof a);  //number
console.log(typeof b);    //string
console.log(typeof c);  //boolean

console.log(".............");

var v1 = new Number(a);
var v2 = new String(b);
var v3 = new Boolean(c);
console.log(typeof v1);   //object
console.log(typeof v2);   //object
console.log(typeof v3);      //object

console.log("*************");
console.log((v1===a) + ', ' + (v1==a));  //false, true
console.log((v2===b) + ', ' + (v2==b));  //false, true
console.log((v3===c) + ', ' + (v3==c));  //false, true
View Code

  3、包装对象实例可以使用Object对象提供的原生方法,主要是valueOf方法和toString方法。

      valueOf()方法返回包装对象实例对应的原始类型的值;

    toString()方法返回实例对应的字符串形式。

new Number(123).valueOf()  // 123
new String("abc").valueOf() // "abc"
new Boolean("true").valueOf() // true

new Number(123).toString() // "123"
new String("abc").toString() // "abc"
new Boolean("true").toString() // "true"
View Code

  4、原始类型的值,可以自动当作对象调用,即调用各种对象的方法和参数。这时,JavaScript引擎会自动将原始类型的值转为包装对象,在使用后立刻销毁

    比如,字符串可以调用length属性,返回字符串的长度

var str = 'abc';
str.length // 3

// 等同于
var strObj = new String(str)
// String {
//   0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"
// }
strObj.length // 3

/**
上面代码中,字符串abc的包装对象有每个位置的值、有length属性、还有一个内部属性[[PrimitiveValue]]保存字符串的原始值。这个[[PrimitiveValue]]内部属性,外部是无法调用,仅供ValueOf或toString这样的方法内部调用。

这个临时对象是只读的,无法修改。所以,字符串无法添加新属性。
*/
str.x = 123;
str.x  //undefined
View Code

  5、三种包装对象还可以在原型上添加自定义方法和属性,供原始类型的值直接调用。

    但是,这种自定义方法和属性的机制,只能定义在包装对象的原型上,如果直接对原始类型的变量添加属性,则无效。

//比如,我们可以新增一个double方法,使得字符串和数字翻倍。
String.prototype.double = function () {
  return this.valueOf() + this.valueOf();
};

console.log('abc'.double()); //abcabc


Number.prototype.double = function () {
  return this.valueOf() + this.valueOf();
};

console.log((123).double()); //246
View Code

 

 

四、Number对象

  1、Number对象是数值对应的包装对象,可以作为构造函数使用,也可以作为工具函数使用  

//1、Number构造函数
var a = new Number(1);
console.log(typeof a);  //object

//2、作为工具函数,它可以将任何类型的值转为数值
Number(true);  //1
Number('a');  //NaN
View Code

  2、Number对象属性

/**
Number.POSITIVE_INFINITY:正的无限,指向Infinity。
Number.NEGATIVE_INFINITY:负的无限,指向-Infinity。
Number.NaN:表示非数值,指向NaN。
Number.MAX_VALUE:表示最大的正数,相应的,最小的负数为-Number.MAX_VALUE。
Number.MIN_VALUE:表示最小的正数(即最接近0的正数,在64位浮点数体系中为5e-324),相应的,最接近0的负数为-Number.MIN_VALUE。
Number.MAX_SAFE_INTEGER:表示能够精确表示的最大整数,即9007199254740991。
Number.MIN_SAFE_INTEGER:表示能够精确表示的最小整数,即-9007199254740991。
*/

console.log(Number.POSITIVE_INFINITY); // Infinity
console.log(Number.NEGATIVE_INFINITY); // -Infinity
console.log(Number.NaN) // NaN

console.log(Number.MAX_VALUE)  // 1.7976931348623157e+308
console.log(Number.MAX_VALUE < Infinity)  // true

console.log(Number.MIN_VALUE)   // 5e-324
console.log(Number.MIN_VALUE > 0)  // true

console.log(Number.MAX_SAFE_INTEGER) // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER) // -9007199254740991
View Code

  3、Number 对象实例的方法

    Number对象部署了自己的toString方法,用来将一个数值转为字符串形式;

    toString方法可以接受一个参数,表示输出的进制。如果省略这个参数,默认将数值先转为十进制,再输出字符串;

    否则,就根据参数指定的进制,将一个数字转化成某个进制的字符串。

console.log((10).toString());  //"10" 默认输出十进制字符串
console.log((10).toString(2));  //"1010" 输出二进制字符串
console.log((10).toString(8));  //“12” 输出八进制字符串
console.log((10).toString(16)); //“a" 输出十六进制字符串
console.log((0b1111).toString()); //二进制0b1111输出十进制字符串 15
console.log((0xff).toString());  //十六进制输出十进制字符串255
View Code

  Number.prototype.toFixed(): toFixed方法用于将一个数转为指定位数的小数,返回这个小数对应的字符串。

console.log((10).toFixed(2)); //"10.00"
console.log((10.005).toFixed(2)); //"10.01"
View Code

  Number.prototype.toExponential(): toExponential方法用于将一个数转为科学计数法形式。

console.log((10).toExponential());  // "1e+1"
console.log((10).toExponential(1)); // "1.0e+1"
console.log((10).toExponential(2)); // "1.00e+1"

console.log((1234).toExponential());  // "1.234e+3"
console.log((1234).toExponential(1)); // "1.2e+3"
console.log((1234).toExponential(2)); // "1.23e+3"
View Code

  Number.prototype.toPrecision(): toPrecision方法用于将一个数转为指定位数的有效数字。

console.log((12.34).toPrecision(1)); // "1e+1"
console.log((12.34).toPrecision(2)); // "12"
console.log((12.34).toPrecision(3)); // "12.3"
console.log((12.34).toPrecision(4)); // "12.34"
console.log((12.34).toPrecision(5)); // "12.340"

//toPrecision方法的参数为有效数字的位数,范围是1到21,超出这个范围会抛出RangeError错误。
//toPrecision方法用于四舍五入时不太可靠,跟浮点数不是精确储存有关。

console.log((12.35).toPrecision(3)); // "12.3"
console.log((12.25).toPrecision(3)); // "12.3"
console.log((12.15).toPrecision(3)); // "12.2"
console.log((12.45).toPrecision(3)); // "12.4"
View Code

 

 

五、Math对象

  Math是JavaScript的内置对象,提供一系列数学常数和数学方法。该对象不是构造函数,不能生成实例,所有的属性和方法都必须在Math对象上调用

  1、Math对象提供以下一些只读的数学常数。

  • Math.E:常数e。
  • Math.LN2:2的自然对数。
  • Math.LN10:10的自然对数。
  • Math.LOG2E:以2为底的e的对数。
  • Math.LOG10E:以10为底的e的对数。
  • Math.PI:常数Pi。
  • Math.SQRT1_2:0.5的平方根。
  • Math.SQRT2:2的平方根。
console.log(Math.E); // 2.718281828459045
console.log(Math.LN2); // 0.6931471805599453
console.log(Math.LN10); // 2.302585092994046
console.log(Math.LOG2E); // 1.4426950408889634
console.log(Math.LOG10E); // 0.4342944819032518
console.log(Math.PI); // 3.141592653589793
console.log(Math.SQRT1_2); // 0.7071067811865476
console.log(Math.SQRT2); // 1.4142135623730951
View Code

  2、方法

  • Math.abs():绝对值
  • Math.ceil():向上取整
  • Math.floor():向下取整
  • Math.max():最大值
  • Math.min():最小值
  • Math.pow():指数运算
  • Math.sqrt():平方根
  • Math.log():自然对数
  • Math.exp():e的指数
  • Math.round():四舍五入
  • Math.random():随机数
//1、绝对值
console.log(Math.abs(1));  //1
console.log(Math.abs(-1)); //1

//2、最大值,最小值
console.log(Math.max(88, 11, -9)); //88
console.log(Math.min(88, 11, -9)); //-9

//3、Math.floor方法接收一个参数,返回小于该参数的最大整数
console.log(Math.floor(3.2)); //3
console.log(Math.floor(-3.2)); //-4

//4、Math.ceil方法接收一个参数,返回大于该参数的最小整数
console.log(Math.ceil(3.2)); //4
console.log(Math.ceil(-3.2)); //-3

//5、Math.round 四舍五入
console.log(Math.round(3.2)); //3
console.log(Math.round(3.8)); //4
console.log(Math.round(-8.9)); //-9
console.log(Math.round(-8.2)); //-8

//6、Math.pow 返回第一个参数为底数,第二个参数为幂的指数值
console.log(Math.pow(2, 2)); //4
console.log(Math.pow(2, 4)); //16

//7、Math.sqrt 返回参数值的平方根。如果参数
console.log(Math.sqrt(4)); //2
console.log(Math.sqrt(-4)); //NaN
console.log(Math.sqrt(10)); //3.1622776601683795

//8、Math.log 返回以e为底的自然对数值
console.log(Math.log(Math.E)); //1
console.log(Math.log(10));    //2.302585092994046

//9、Math.exp 返回常数e的参数次方
console.log(Math.exp(1)); //2.718281828459045
console.log(Math.exp(3)); //20.085536923187668

//10、Math.random()  : 返回0到1的一个伪随机数,可能等于0,但是一定小于1
console.log(Math.random()); //0.3902195410235101
console.log(Math.round(Math.random()*100));//53

  3、三角函数方法

  • Math.sin():返回参数的正弦
  • Math.cos():返回参数的余弦
  • Math.tan():返回参数的正切
  • Math.asin():返回参数的反正弦(弧度值)
  • Math.acos():返回参数的反余弦(弧度值)
  • Math.atan():返回参数的反正切(弧度值)
console.log(Math.sin(0)); // 0
console.log(Math.cos(0)); // 1
console.log(Math.tan(0)); // 0
console.log(Math.asin(1)); // 1.5707963267948966
console.log(Math.acos(1)); // 0
View Code

 

 

六、Date

  1、new Date(milliseconds)

  Date对象接受从1970年1月1日00:00:00 UTC开始计算的毫秒数作为参数。这意味着如果将Unix时间戳(单位为秒)作为参数,必须将Unix时间戳乘以1000。

console.log(new Date(1885128188000)); //Wed Sep 26 2029 22:43:08 GMT+0800 (CST)
console.log(new Date(3600 * 24 * 1000));//Fri Jan 02 1970 08:00:00 GMT+0800 (CST)
console.log(new Date(3600*24*1000 + 3600*24*365*47*1000));//Wed Dec 21 2016 08:00:00 GMT+0800 (CST)
View Code

  2、new Date(datestring)

  Date对象还接受一个日期字符串作为参数,返回所对应的时间。

console.log(new Date('2013-2-15'));
console.log(new Date('2013/2/15'));
console.log(new Date('02/15/2013'));
console.log(new Date('2013-FEB-15'));
console.log(new Date('FEB, 15, 2013'));
console.log(new Date('FEB 15, 2013'));
console.log(new Date('Feberuary, 15, 2013'));
console.log(new Date('Feberuary 15, 2013'));
console.log(new Date('15 Feb 2013'));
console.log(new Date('15, Feberuary, 2013'));
/** 打印结果:
Wed Sep 26 2029 22:43:08 GMT+0800 (CST)
Fri Jan 02 1970 08:00:00 GMT+0800 (CST)
Wed Dec 21 2016 08:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
Fri Feb 15 2013 00:00:00 GMT+0800 (CST)
*/
View Code

  3、new Date(year, month [, day, hours, minutes, seconds, ms])

  Date对象还可以接受多个整数作为参数,依次表示年、月、日、小时、分钟、秒和毫秒。如果采用这种格式,最少需要提供两个参数(年和月),其他参数都是可选的,默认等于0。

  因为如果只使用“年”这一个参数,Date对象会将其解释为毫秒数。

  各个参数的取值范围如下。

  • year:四位年份,如果写成两位数,则加上1900
  • month:表示月份,0表示一月,11表示12月
  • date:表示日期,1到31
  • hour:表示小时,0到23
  • minute:表示分钟,0到59
  • second:表示秒钟,0到59
  • ms:表示毫秒,0到999
console.log(new Date(2013, 0)); //Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
console.log(new Date(2013, 0, 0));//Mon Dec 31 2012 00:00:00 GMT+0800 (CST)
console.log(new Date(2013, 15, 0));//Mon Mar 31 2014 00:00:00 GMT+0800 (CST)
console.log(new Date(2013, 11, 32, 0, 18));//Wed Jan 01 2014 00:18:00 GMT+0800 (CST)
//2014年1月1号零点18分: 2013年12月份31天  + 1
console.log(new Date(2013, 13, 32, 0, 18)); //Tue Mar 04 2014 00:18:00 GMT+0800 (CST)
View Code

  

  4、Date.parse()

  Date.parse方法用来解析日期字符串,返回距离1970年1月1日 00:00:00的毫秒数。

console.log(Date.parse('January 26, 2011 13:51:50')); //1296021110000
console.log(Date.parse('Mon, 25 Dec 1995 13:30:00 GMT'));//819898200000
console.log(Date.parse('Mon, 25 Dec 1995 13:30:00 +0430'));//819882000000
console.log(Date.parse('2011-10-10'));//1318204800000
console.log(Date.parse('2011-10-10T14:48:00'));//1318229280000
View Code

  

  5、get类方法

  Date对象提供了一系列get*方法,用来获取实例对象某个方面的值。

  • getTime():返回距离1970年1月1日00:00:00的毫秒数,等同于valueOf方法。
  • getDate():返回实例对象对应每个月的几号(从1开始)。
  • getDay():返回星期几,星期日为0,星期一为1,以此类推。
  • getYear():返回距离1900的年数。
  • getFullYear():返回四位的年份。
  • getMonth():返回月份(0表示1月,11表示12月)。
  • getHours():返回小时(0-23)。
  • getMilliseconds():返回毫秒(0-999)。
  • getMinutes():返回分钟(0-59)。
  • getSeconds():返回秒(0-59)。
  • getTimezoneOffset():返回当前时间与UTC的时区差异,以分钟表示,返回结果考虑到了夏令时因素。
var time = new Date(2013, 05, 18, 12, 32, 58);
console.log(time);//Tue Jun 18 2013 12:32:58 GMT+0800 (CST)
console.log(time.getTime()); //1371529978000
console.log(time.getDate());//18
console.log(time.getDay());//2
console.log(time.getYear());//113
console.log(time.getFullYear());//2013
console.log(time.getMonth());//5
console.log(time.getHours());//12
console.log(time.getMilliseconds());//0
console.log(time.getMinutes());//32
console.log(time.getSeconds());//58
console.log(time.getTimezoneOffset());//-480
View Code

 

  6、set类方法

  Date对象提供了一系列set*方法,用来设置实例对象的各个方面。

  • setDate(date):设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳。
  • setYear(year): 设置距离1900年的年数。
  • setFullYear(year [, month, date]):设置四位年份。
  • setHours(hour [, min, sec, ms]):设置小时(0-23)。
  • setMilliseconds():设置毫秒(0-999)。
  • setMinutes(min [, sec, ms]):设置分钟(0-59)。
  • setMonth(month [, date]):设置月份(0-11)。
  • setSeconds(sec [, ms]):设置秒(0-59)。
  • setTime(milliseconds):设置毫秒时间戳。

  这些方法基本是跟get*方法一一对应的,但是没有setDay方法,因为星期几是计算出来的,而不是设置的。

  另外,需要注意的是,凡是涉及到设置月份,都是从0开始算的,即0是1月,11是12月。

var time = new Date(2013, 05, 18, 12, 32, 58);
console.log(time);//Tue Jun 18 2013 12:32:58 GMT+0800 (CST)

//将日期往后推1000天
time.setDate(time.getDate() + 1000);
console.log(time);//Mon Mar 14 2016 12:32:58 GMT+0800 (CST)


//设置月份为11月
time.setMonth(10);
console.log(time); //Mon Nov 14 2016 12:32:58 GMT+0800 (CST)

//将时间设置6小时后
time.setHours(time.getHours() + 6);
console.log(time);//Mon Nov 14 2016 18:32:58 GMT+0800 (CST)
View Code

 

 

七、正则表达式(Regular Expression)

1、正则匹配规则:字面量字符和元字符

  大部分字符在正则表达式中,就是字面的含义,比如/a/匹配a/b/匹配b。那么它们就叫做“字面量字符”(literal characters);

  还有一部分字符具有特殊作用,这种字符叫元字符(metacharacters),主要有:

  • 位置字符^和$   -->   ^表示字符串开始位置;$表示字符串结束位置
  • 方括号[]  --> 一系列字符只需要匹配一个就ok, 这一系列字符可以放在方括号内
  • 连字符-  -->  连字符号主要和方括号一起使用,连续字符选择供选择的字符简写,主要有a-z, A-Z, 0-9, 表示小写字母a到z, 大写字母A到Z, 数字0到9区间字符供选择
  • 脱字符^  --> 如果方括号内的第一个字符是[^],则表示除了字符类之中的字符,其他字符都可以匹配。比如,[^xyz]表示除了xyz之外都可以匹配
  • 点字符.   -->  点字符(.)匹配除回车(\r)、换行(\n) 、行分隔符(\u2028)和段分隔符(\u2029)以外的所有字符;
  • 小括号()  -->  小括号里面表示一个整体,需要整体匹配,一般用来分组匹配,和选择符号|配合使用;
  • 选择符号|  -->  竖线符号表示或关系
  • ------------- 空格字符  -----------
  • \n 匹配换行键
  • \r 匹配回车键
  • \t 匹配制表符tab(U+0009)
  • \v 匹配垂直制表符(U+000B)
  • \f 匹配换页符(U+000C)
  • ----------- 预定义模式: 某些常见模式的简写方式 ---------
  • \d 匹配0-9之间的任一数字,相当于[0-9]
  • \D 匹配所有0-9以外的字符,相当于[^0-9]
  • \w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
  • \W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
  • \s 匹配空格(包括制表符、空格符、断行符等),相等于[\t\r\n\v\f]
  • \S 匹配非空格的字符,相当于[^\t\r\n\v\f], [\S\s]指代一切字符
  • \b 匹配词的边界
  • \B 匹配非词边界,即在词的内部
  • ------ 重复类,使用到{}和量词符号 -----
  • {} 模式的精确匹配次数,{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。
  • 量词符用来设定某个模式出现的次数
  • ? 问号表示某个模式出现0次或1次,等同于{0,1}
  • * 星号表示某个模式出现0次或多次,等同于{0,}
  • + 加号表示某个模式出现1次或多次,等同于{1,}
  • -------  特殊字符 --------
  • \cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符
  • [\b] 匹配退格键(U+0008),不要与\b混淆
  • \0 匹配null字符(U+0000)
  • \xhh 匹配一个以两位十六进制数(\x00-\xFF)表示的字符
  • \uhhhh 匹配一个以四位十六进制数(\u0000-\uFFFF)表示的unicode字符

 2、创建正则表达式的两种方法:字面创建和构造方法

var regex = /xyz/i;
var regex2 = new RegExp('xyz', 'i');

console.log(regex.test('xyz'));  //true
console.log(regex2.test('xyz'));  //true
console.log(regex.test('xxx'));  //false
console.log(regex2.test('xxx')); //false
View Code

2.1、正则对象的属性:

  • ignoreCase:返回一个布尔值,表示是否设置了i修饰符,该属性只读。
  • global:返回一个布尔值,表示是否设置了g修饰符,该属性只读。
  • multiline:返回一个布尔值,表示是否设置了m修饰符,该属性只读。
  • lastIndex:返回下一次开始搜索的位置。该属性可读写,但是只在设置了g修饰符时有意义。
  • source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。
var reg = /xyz/g;

console.log(reg.ignoreCase + ", " + reg.global + ", " + reg.multiline); //false, true, false
console.log(reg.lastIndex + ", " + reg.source);  //0, xyz

reg.test('abcxyzabcxyz');
console.log(reg.ignoreCase + ", " + reg.global + ", " + reg.multiline); //false, true, false
console.log(reg.lastIndex + ", " + reg.source);  //6, xyz
View Code

 

2.2、正则对象的方法:test() 和 exec()

正则对象的test方法返回一个布尔值,表示当前模式是否能匹配参数字符串

var r = /x/g;
var s = '_x_y_x_y';

console.log(r.lastIndex); //0

console.log(r.test(s)); //true
console.log(r.lastIndex); //2

console.log(r.test(s)); //true
console.log(r.lastIndex); //6

console.log(r.test(s)); //false
console.log(r.lastIndex); //0
View Code

正则对象的exec方法,可以返回匹配结果。如果发现匹配,就返回一个数组,成员是每一个匹配成功的子字符串,否则返回null

var s = '_x_x';
var r1 = /x/;
var r2 = /y/;

console.log(r1.exec(s)); //["x", index: 1, input: "_x_x"]
console.log(r2.exec(s)); //null
View Code

exec方法的返回数组还包含以下两个属性:

  • input:整个原字符串
  • index:整个模式匹配成功的开始位置(从0开始计数)

如果正则表示式包含圆括号(即含有“组匹配”),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。整个数组的length属性等于组匹配的数量再加1。

var r = /a(b+)a/;
var arr = r.exec('_abba_aba_');

console.log(arr); //["abba", "bb", index: 1, input: "_abba_aba_"]
console.log(arr.index + ", " + arr.input);//1, _abba_aba_


var arr2 = r.exec('Y_Yabba_aba_Y');
console.log(arr2); //["abba", "bb", index: 3, input: "Y_Yabba_aba_Y"]
console.log(arr2.index + ", " + arr2.input);//3, Y_Yabba_aba_Y



//多个组匹配演示(多个括号)
var r = /a(b+)(c+)a/g;
var s = '_abca_abbca_abbcca_';
var arr = r.exec(s);

console.log(arr); //["abca", "b", "c", index: 1, input: "_abca_abbca_abbcca_"]

var arr2 = r.exec(s);
console.log(arr2); //["abbca", "bb", "c", index: 6, input: "_abca_abbca_abbcca_"]

var arr3 = r.exec(s);
console.log(arr3); //["abbcca", "bb", "cc", index: 12, input: "_abca_abbca_abbcca_"]

var arr4 = r.exec(s);
console.log(arr4); //null
View Code

 

2.3、字符串对象的方法之中,有4种与正则对象有关

  • match():返回一个数组,成员是所有匹配的子字符串。
  • search():按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。
  • replace():按照给定的正则表达式进行替换,返回替换后的字符串。
  • split():按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。
//1、String.prototype.match(): 字符串对象的match方法对字符串进行正则匹配,和正则对象的exec方法类似:匹配成功则返回一个数组,匹配失败则返回null。 match()方法使得正则表达式的lastIndex无效(正则的lastIndex都是在g修饰符下才有效果)
var s = '_x_x';
var r1 = /x/;
var r2 = /y/;
var r3 = /x/g;

console.log(s.match(r1)); //["x", index: 1, input: "_x_x"]
console.log(s.match(r2));// null
console.log(s.match(r3));//["x", "x"]
console.log(r1.exec(s)); //["x", index: 1, input: "_x_x"]
console.log(r2.exec(s)); //null
console.log(r3.exec(s)); //["x", index: 1, input: "_x_x"]


s = '_x_xx_';
console.log(s.match(r1)); //["x", index: 1, input: "_x_xx_"]
console.log("r1.lastIndex: " + r1.lastIndex); //r1.lastIndex: 0
console.log(r1.exec(s)); //["x", index: 1, input: "_x_xx_"]
console.log(r1.lastIndex); //0
console.log(s.match(r3)); //["x", "x", "x"]
console.log("r3.lastIndex: " + r3.lastIndex); //r3.lastIndex: 0
console.log(r3.exec(s)); //["x", index: 1, input: "_x_xx_"]
console.log(r3.lastIndex); //2
View Code
//2、String.prototype.search(): 字符串对象的search方法,返回第一个满足条件的匹配结果在整个字符串中的位置。如果没有匹配到,则返回-1
console.log('_x_x'.search(/x/)); //1
console.log('_x_x'.search(/y/)); //-1

//search方法会忽略g修饰符
var r = /x/g;
console.log('_x_x'.search(r)); //1
console.log(r.lastIndex); // 0


//3、String.prototype.replace(): 字符串对象的replace()方法可以替换匹配的值。它接受两个参数,第一个是搜索模式,第二个是替换的内容
//3.1、搜索模式如果不加g修饰符,就替换第一个匹配成功的值,否则替换所有匹配成功的值
console.log('aaa'.replace('a', 'b')); //baa
console.log('aaa'.replace(/a/, 'b')); //baa
console.log('aaa'.replace(/a/g, 'b'));//bbb

//3.2、replace方法的一个应用,就是消除字符串首尾两端的空格
var str = '  dajiahao div.hao  ';
console.log(str); //  dajiahao div.hao  
console.log(str.replace(/^\s+|\s+$/g, ''));  //dajiahao div.hao
View Code

replace方法的第二个参数可以使用美元符号$,用来指代所替换的内容

  • $& 指代匹配的子字符串
  • $` 指代匹配结果前面的文本
  • $' 指代匹配结果后面的文本
  • $n 指代匹配成功的第n组内容,n是从1开始的自然数
  • $$ 指代美元符号$
//3.3、replace方法的第二个参数可以使用美元符号$, 用来指代所替换的内容
/*
$& 指代匹配的子字符串。
$` 指代匹配结果前面的文本。
$' 指代匹配结果后面的文本。
$n 指代匹配成功的第n组内容,n是从1开始的自然数。
$$ 指代美元符号$。
*/

//$1对应匹配的hello, $2对应匹配的world
console.log('hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')); //world hello

//$&对应匹配结果bbb, $`对应匹配结果前面的文本Aa, $'对应匹配结果后面的文本CDF
console.log('AabbbCDF'.replace('bbb', '[$\'-$&-$`]')); //Aa[CDF-bbb-Aa]CDF

//replace方法的第二个参数还可以是一个函数
var result = '3 and 5'.replace(/[0-9]+/g, function(match){
    return 2 * match;
});
console.log(result); //6 and 10

result = 'I like basketball, football, swimming... yes, I do'.replace(/basketball|football|swimming/ig, function(match){
    return match.toUpperCase();
});
console.log(result); //I like BASKETBALL, FOOTBALL, SWIMMING... yes, I do
View Code
//String.prototype.split(): 字符串对象split方法按照正则规则分割字符串,返回一个由分割后的各个部分组成的数组

var str = 'a, b,c, d,e';
//非正则分割
console.log(str.split(',')); //["a", " b", "c", " d", "e"]
//正则分割,去除多余的空格
console.log(str.split(/, */));//["a", "b", "c", "d", "e"]
//指定返回数组的最大成员
console.log(str.split(/, */, 2)); //["a", "b"]


//正则默认是贪婪匹配
console.log('aaa*a*'.split(/a*/));//["", "*", "*"]
console.log('aaa**a*'.split(/a*/));//["", "*", "*", "*"]
//如果正则表达式带有括号,则括号匹配的部分也会作为数组成员返回
console.log('aaa*a*'.split(/(a*)/));//["", "aaa", "*", "a", "*"]
View Code

 

2.4、正则规则的测试代码

//正则规则
//1、字面量字符: 大部分字符在正则表达式中,就是字面的含义
console.log(/dog/.test('my dog')); //true

//2、点字符. : 匹配除回车\r、换行\n、行分隔符\u2028、段分隔符\u2029以外的所有字符
console.log(/a.b/.test('afb')); //true
console.log(/a.b/.test('afab')); //false
console.log(/a.b/.test('a\rb')); //false


//3、位置字符^和$
//     ^ 表示字符串的开始位置
//   $ 表示字符串的结束位置
console.log(/^test/.test('test12...')); //true
console.log(/^test/.test('12test')); //false
console.log(/test$/.test('12test')); //true
console.log(/test$/.test('test12')); //false


//4、选择符| :表示’或关系’,例cat|dog表示cat或dog
console.log(/11|22/.test('911'))//true
console.log(/11|22/.test('922'));//true
console.log(/11|22/.test('912')); //false

//选择符会包括它前后的多个字符,比如/ab|cd/指的是匹配ab或cd, 而不是指匹配b或者c。如果想修改这个行为,可以使用圆括号
console.log(/a( |\t)b/.test('a\tb')); //true
console.log(/a |\tb/.test(' b')); //false
console.log(/a |\tb/.test('\tb')); //true


//5、转义符:正则表达式中那些有特殊含义的字符,如果要匹配他们本身,需要在他们前面加上反斜杠。比如匹配加号,就要写成\+
console.log(/1+1/.test('1+1')); // false
console.log(/1\+1/.test('1+1')); //true
View Code
//6、方括号[]和脱字符^, 和连字符-
//有一系列字符可供选择,只要匹配其中一个就可以。所有可供选择的字符放在方括号内,配合-和^使用
console.log(/[abc]/.test('hello, world')); //false
console.log(/[abc]/.test('apple')); //true

//脱字符^ 一般用在方括号内的第一个字符[^], 表示除了方括号中的字符,其他字符都可以匹配,比如[^xyz]表示除了x、y、z之外都可以匹配
console.log(/[^xyz]/.test('hello world')); //true
console.log(/[^xyz]/.test('yellow')); //true
console.log(/[^xyz]/.test('xyzxxxyyz'));//false

//^注意1:如果方括号内没有其他字符,即只有[^],就表示匹配一切字符,其中包括换行符,而点号.是不包含换行符的
var s = 'I love \n you';
console.log( /love.*you/.test(s) ); //false
console.log( /love[^]*you/.test(s) );//true

//^注意2:脱字符只有在字符类的[]第一个位置才有特殊含义,否则就是字面含义
console.log(/[a^b]/.test('hello')); //false
console.log(/[a^b]/.test('hello^'));//true

//连字符-: 对于连续序列的字符,连字符-用来提供简写形式,表示字符的连续范围,比如[abc]可以写成[a-c], [0123456789]可以简写成[0-9], [A-Z]表示26个大写字母
console.log(/a-z/.test('b')); //false
console.log(/[a-z]/.test('b')); //true
console.log(/[a-z]/.test('B')); //false
console.log(/[a-g]/.test('m')); //false


//7、预定义模式:某些常见模式的简写方式
/*
\d 匹配0-9之间的任一数字,相当于[0-9]。
\D 匹配所有0-9以外的字符,相当于[^0-9]。
\w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]。
\W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]。
\s 匹配空格(包括制表符、空格符、断行符等),相等于[\t\r\n\v\f]。
\S 匹配非空格的字符,相当于[^\t\r\n\v\f]。
\b 匹配词的边界。
\B 匹配非词边界,即在词的内部。
*/
console.log( /\d/.test('a') ); //false
console.log( /\d/.test('8') ); //true
console.log( /\D/.test('8') ); //false
console.log( /\D/.test('a') ); //true
console.log( /\D/.test('\n') ); //true
console.log( /\w/.test('<_>') ); //true
console.log( /\w/.test('<>') ); //false
console.log( /\W/.test('abc') ); //false
console.log( /\W/.test('_') ); //false
console.log( /\W/.test('\n') ); //true
console.log( /\W/.test('^123') ); //true
console.log( /\W/.test('123') );//false
console.log( /\s/.test('\n\r') ); //true
console.log( /\s/.test('aa') );//false
console.log( /\S/.test('aa') );//true
console.log( /\S/.test('\n\r') );//false


//8、重复类:模式的精确匹配次数,使用大括号{}表示。{n}表示恰好重复n次, {n, }表示至少重复n次, {n,m}表示重复不少于n次,不多于m次
console.log( /lo{2}k/.test('look') ); //true
console.log( /lo{2}k/.test('lok') ); //false
console.log( /lo{2,5}k/.test('loook') );//true


//9、量词符:量词符用来设定某个模式出现的次数
/*
? 问号表示某个模式出现0次或1次,等同于{0, 1}。
* 星号表示某个模式出现0次或多次,等同于{0,}。
+ 加号表示某个模式出现1次或多次,等同于{1,}。
*/
console.log( /lo?k/.test('lk') ); //true
console.log( /lo?k/.test('look') );//false
console.log( /lo*k/.test('lk') ); //true
console.log( /lo*k/.test('looooook') ); //true
console.log( /lo+k/.test('lk') );//false
console.log( /lo+k/.test('loooook') );//true
View Code
//10、贪婪模式:正则模式匹配的时候,默认情况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规则为止。这被称为贪婪模式。主要指量词符+/*
console.log( 'aaabaa'.match(/a+/) ); //["aaa", index: 0, input: "aaabaa"]
console.log( 'aaabbcc'.match(/a+/) ); //["aaa", index: 0, input: "aaabbcc"]

//非贪婪模式:在正则模式结尾添加一个问号?,就把默认的贪婪模式改成非贪婪模式:表示一旦条件满足,就不在往下匹配
console.log( 'aaabaa'.match(/a+?/) ); //["a", index: 0, input: "aaabaa"]


//11、修饰符:修饰符(modifier)表示模式的附加规则,放在正则模式的最尾部。修饰符可以单个使用,也可以多个一起使用
//g修饰符:表示全局匹配,加上它以后,正则对象匹配全部符合条件的结果,主要用于搜索和替换
var r = /b/;
var s = 'abba';
console.log( r.test(s) ); //true
console.log( r.test(s) ); //true
console.log( r.test(s) ); //true
//上面的正则模式不含g修饰符,每次都是从字符串头部开始匹配。所以,连续做了三次匹配,都返回true

r = /b/g;
console.log( r.test(s) ); //true
console.log( r.test(s) ); //true
console.log( r.test(s) ); //false

//i修饰符:表示忽略大小写
console.log( /abc/.test('ABC') ); //false
console.log( /abc/i.test('ABC') ); //true

//m修饰符:m修饰符表示多行模式,会修改^和$的行为。默认情况下(即不加m修饰符时),^和$匹配字符串的开始处和结尾处,加上m后,^和$还会匹配行首和行尾,即^和$会识别换行符\n
console.log( /world$/.test('hello world\n') ); // false
console.log( /world$/m.test('hello world\n') ); // true
console.log( /^b/m.test('a\nb') ); // true
View Code

组匹配测试

捕获组

//组匹配
//1、正则表达式的括号表示分组匹配,括号中的模式可以用来匹配分组的内容

console.log( /fred+/.test('fredd') ); //true
console.log( /(fred)+/.test('fredfred') ); //true
//fred+是匹配d字符{1,}, (fred)+是匹配字符串fred整体有多个

var arr = 'abcabc'.match(/(.)b(.)/);
console.log( arr ); //["abc", "a", "c", index: 0, input: "abcabc"]
//正则表达式/(.)b(.)/一共使用两个括号,第一个括号捕获a, 第二个括号捕获c。 使用组匹配时,不宜同时使用g修饰符,否则match方法不会捕获分组的内容
//在正则表达式内部,可以用\n引用括号匹配的内容,n是从1开始的自然数,表示对应顺序的括号

console.log( /y(..)(.)\2\1/.test('yabccab') );//true
//\2指第二个括号匹配的内容c, \1指第一个括号匹配的内容ab

console.log( /y((..)\2)\1/.test('yabababab') );//true
//\1指向外层括号,\2指向内层括号

//匹配网页标签
var tagName = /<([^>]+)>[^<]*<\/\1>/;
console.log( tagName.exec("<h1>Element</h1>") );//["<h1>Element</h1>", "h1", index: 0, input: "<h1>Element</h1>"]
//圆括号匹配尖括号之中的标签,而\1就表示对应的闭合标签

//匹配带有属性的标签
var html = '<b class="hello">Hello</b><i>world</i>';
var tag = /<(\w+)([^>]*)>(.*?)<\/\1>/g;

var match = tag.exec(html);
console.log( match ); //["<b class="hello">Hello</b>", "b", " class="hello"", "Hello", index: 0, input: "<b class="hello">Hello</b><i>world</i>"]

match = tag.exec(html);
console.log( match );//["<i>world</i>", "i", "", "world", index: 26, input: "<b class="hello">Hello</b><i>world</i>"]
View Code

非捕获组

//2、非捕获组
// (?:x)称为非捕获组(Non-capturing group), 表示不返回该组匹配的内容,即匹配的结果中不计入这个括号
//查看捕获组和非捕获组的区别
console.log( 'abc'.match(/(.)b(.)/) ); //["abc", "a", "c", index: 0, input: "abc"]
console.log( 'abc'.match(/(?:.)b(.)/) ); //["abc", "c", index: 0, input: "abc"]


console.log( /y((..)\2)\1/.test('yabababab') );//true
console.log( /y((?:..)\2)\1/.test('yabababab') );//false
//使用了非捕获组,则\2组不存在了

//分解网址的正则表达式
// 正常匹配
var url = /(http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
console.log( url.exec('http://google.com/') );
// ["http://google.com/", "http", "google.com", "/", index: 0, input: "http://google.com/"]

// 非捕获组匹配
var url = /(?:http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
console.log( url.exec('http://google.com/') );
// ["http://google.com/", "google.com", "/", index: 0, input: "http://google.com/"]
View Code

 

参考书籍:阮一峰之《JavaScript标准参考教程》

posted @ 2015-04-02 00:11  谈晓鸣  阅读(667)  评论(0编辑  收藏  举报