[JavaScript高级程序设计]引用类型

引用类型

引用类型是一种数据结构,用于将数据和功能组织在一起。有时候也被称为对象定义,因为描述的是一类对象所具有的属性和方法。

对象是某个特定引用类型的实例。

1.Object类型

创建方法:

1.使用new操作符后跟Object构造函数

var person = new Object();
person.name = 'Nicjolas';
person.age = 29;

2.使用对象字面量

var person = {
    name:'Nicholas',
    age:29
}

2.Array类型

3.Date类型

(坑爹的没有保存,之后有时间再补)

4.RegExp类型

正则表达式是使用单个字符串来描述,匹配一系列符合某种句法规则的字符串。

在线图形化工具:https://regexper.com/#.%0A

ECMAScript通过RegExp类型来支持正则表达式。创建正则表达式语法:

1.字面量形式

var expression = / pattern / flags;

其中,pattern可以是任何简单或复杂的正则表达式,可以包含字符类,限定符,分组,向前查找和反向引用;
          flags用以标明正则表达式的行为。

  • g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项之后立即停止
  • i:表示不区分大小写模式,即在确定匹配项时忽略模式与字符串的大小写
  • m: 表示多行模式,即在到达一行文本末未时还会继续查找下一行中是否存在与模式匹配的项

故,一个正则表达式就是一个模式与上诉三个标志的组合。

在模式中使用元字符需要转义,元字符包括:
       ( { [ ^ $ ? + * \ . | ] } )

//匹配第一个bat或者cat,不区分大小写
var pattern1 = /[bc]at/i;

//匹配第一个[bc]at,不区分大小写
var pattern2 = /\[bc\]at/i;

2.使用RegExp构造函数

接受两个参数:一个是要匹配的字符串,一个是可选的标志字符串。可以使用字面量定义的任何表达式都可以使用构造函数来定义。

var pattern3 = new RegExp("[bc]at","i");

在某些情况下要对字符进行双重转移

字面量模式 等价的字符串
/\[ bc \] at/ \\[bc\\]at
/\.at/ \\.at
/name\/age/ name\\/age
/\d.\d{1,2}/ \\d.\\d{1,2}
/\w\\hello\\123/ \\w\\\\hello\\\\123

每次使用正则表达式字面量或构造函数都会创建一个新的RegExp实例。

4.1 RegExp实例属性

  • global:布尔值,表示是否设定了g标志
  • ignoreCase:布尔值,表示是否设定了i标志
  • lastIndex:整数,表示开始设置下一匹配字符的位置,从0算起(非全局时无效,始终为0)
  • multiline:布尔值,表示是否设定了i标志
  • source:正则表达式的字符串表示,按照字面量形式返回
var pattern = /\[bc\]at/i;
console.log(pattern.global);        //false
console.log(pattern.ignoreCase);    //true
console.log(pattern.multiline);     //false
console.log(pattern.lastIndex);     //0
console.log(pattern.source);        //"\[bc\]at"

4.2 RegExp实例方法

1.exec()方法

该方法是专门为捕获组设计的。接收一个参数--要应用模式的字符串。返回包含第一个匹配项的数组;或在没有匹配项的情况下返回null。且该数组包含两个属性:index(表示匹配项在字符串中的位置)和input(表示应用正则表达式的字符串)。

var text ="mom and dad and baby";
var pattern = /mom (and dad(and baby)?)?/gi;

var matches = pattern.exec(text);
console.log(index);         //0
console.log(input);         //mom and dad and baby
console.log(matches[0]);    //mom and dad and baby
console.log(matches[1]);    //and dad and baby
console.log(matches[2]);    //and baby

对于exec()而言,即使设置了全局标志g,每次也只会返回一个匹配项。区别:不设置全局标志时,在同一个字符串上多次调用exec(),将会始终返回第一个匹配项;在设置了全局标志后,每次调用exec()则会在字符串中继续查找新匹配项。

var text = "cat, bat, sat, fat";

var pattern1 = /.at/;
var matches = pattern1.exec(text);
console.log(index);                 //0    
console.log(matches[0]);            //cat
console.log(pattern1.lastIndex);    //0

matches = pattern1.exec(text);
console.log(index);                 //0    
console.log(matches[0]);            //cat
console.log(pattern1.lastIndex);    //0

var pattern2 = /.at/g;
var matches = pattern2.exec(text);
console.log(index);                 //0    
console.log(matches[0]);            //cat
console.log(pattern1.lastIndex);    //3

matches = pattern1.exec(text);
console.log(index);                 //5    
console.log(matches[0]);            //bat
console.log(pattern1.lastIndex);    //8
... ...

在全局模式下,每次调用exec()后,lastIndex值都会增加,而在非全局模式下不会。

2.test()方法

接收一个参数--要应用模式的字符串。在模式与该字符串匹配时返回true,否则返回false。

3.toLocalString(),toString()和valueOf()

RegExp实例继承的toLocalString()和toString()方法返回正则表达式字面量,与创建方式无关。valueOf()方法返回正则表达式本身。

4.3 RegExp构造函数属性

长属性名 短属性名 说明
input $_ 最近一次要匹配的字符串
lastMatch $& 最近一次的匹配项
lastParen $+ 最近一次匹配项的捕获组
leftContext $` input中lastMatch之前的文本
rightContext $' input中lastMatch之后的文本
multiline $* 布尔值,表示是否所有表达式都是用多行模式

除以上表格中的几个属性外,还有9个用于存储捕获组的构造函数属性。访问这些属性的语法是:RegExp.$1 ··· RegExp.$9,分别用于存储第一... ... 第九个匹配的捕获组。

var text = "this has been a short summer";
var pattern = /(..)or(.)/g;

if(pattern.test(text)){
    consolr.log(RegExp.$1);    //sh
    console.log(RegExp.$2);    //t
}

4.4 基础知识

1.字符类

  • 可以使用元字符[]构建一个简单的类。所谓类是指符合某些特性的对象,一个泛指。
    例:[abc],就是将a,b,c归为一类,匹配到a或b或c
  • 在[]中使用^表示匹配除方括号中内容之外的内容。(创建反向类)[^abc]:匹配除a,b,c之外的字符

2.范围类

  • 使用-表示范围。[a-z]:匹配a到z内的任意字符
  • 在[]内部可以连写。[a-zA-Z]:匹配a-z和A-Z内的任意字符
  • 若在范围类中还相匹配横线则[0-9-]

3.预定义类

字符 等价类 含义
. [^\r\n] 除回车符和换行符之外的所有字符
\d [0-9] 数字字符
\D [^0-9] 非数字字符
\s [\t\n\xDB\f\r] 空白符
\S [^\t\b\xDB\f\r] 非空白符
\w [a-zA-Z0-9_] 字母,数字,下划线
\W [^a-zA-Z0-9_] 非单词字符

4.边界

/^xxx/  以xxx开头
/xxx$/  以xxx结束

5.量词

字符 含义
出现0次或1次
+ 出现一次或多次
* 出现任意多次
{n} 出现n次
{n,m}

出现n到m次

{n,} 至少出现n次

6.贪婪模式

\d{3,6}\   12345678 对其进行匹配时会尽可能多的匹配。

"12345678".replace(/\d{3,6}/g,'X');   //X78

7.非贪婪模式

让正则表达式尽可能少的匹配,也就是说一旦匹配成功就不在继续匹配。

'123456789'.match(/\d{3,6}?/g);    //["123", "456", "789"]

8.分组

使用()可以达到分组的功能。
Byron{3}  --  n重复出现3次
(Byron){3}  --  Byron重复出现3次

9.或

使用|可以达到或的效果

10.反向引用

//实现将2018-7-27转换成7/27/2018
'2016-7-27'.replace(/(\d{4})-(\d{1,2})-(\d{2}/g),'$2/$3/$1');

11.忽略分组

不想要不活分组是只需要在分组内加上?:即可

12.前瞻

正则表达式从文本头部向尾部解析,故文本尾部称为“前”,文本头部成为“后”。前瞻就是在正则表达式匹配到规则,向前检查是否符合断言,后顾方向相反(JS不支持后顾)。

  • 正向前瞻 exp(?=assert)
    \w(?=\d):匹配到单词字符后要检查后面是数字,才算匹配成功
  • 负向前瞻 exp(?!assert)
    \w(?!\d):匹配到单词字符后要检查后面不是数字,才算匹配成功

5.function类型

函数实际上是对象。每个函数都是Function类型的实例,与其他引用类型一样,都具有属性和方法。函数名实际上是一个指向函数对象的指针。

函数的定义方法:

1.函数声明法:

function sum(num1,num2){
    return num1 + num2;
}

2.函数表达式定义:

var sum = function(num1,num2){
    return num1 + num2;
}

由于函数名是指向函数的指针,因此函数名与包含对象指针的其他变量没什么不同。使用不带圆括号的函数名是访问函数指针,而非调用函数。

5.1 没有重载

因为函数名是指针,故没有重载

5.2 函数声明变量提升

解析器会率先读取函数声明,并使其在执行任何代码之前可用;至于函数表达式,必须等到解析器执行到他所在的代码行,才会真正的被解析执行。

5.3 作为值得函数

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

1.作为参数

function callSomeFunction(someFunction,someArgument){
    return someFuntion(someArgument);
}
function add(num){
    return num + 10;
}

var result = callSomeFunction(add,10);
console.log(result);    //20

2.作为值返回

function createComparisionFunction(propertyName){
    return function(obj1,obj2){
        var val1 = obj1[propertyName];
        var val2 = obj2[propertyName];
        if(val1 < val2){
            return -1;
        }else if(val1 > val2){
            return 1;
        }else{
            return 0;
        }
    };
}

var data=[{name:'Zachary',age:28},{name:'Nicholas',age:29}];
data.sort(createComparisionFunction('name'));
console.log(data[0].name);    //Nicholas

5.4 函数的内部属性

1.this -- 引用的是函数执行的环境变量(this指向该函数被调用的对象)

var obj={
    a:'a',
    b:function(){
            console.log(this.a);
       } ,
    c:{
        a:'-a',
        b:function(){
            console.log(this.a);
       }   
    }
}

obj.b();        //a
obj.c.b();      //-a

2.arguments

主要用途是保存函数参数。arguments有一个名叫callee的内部属性,指向拥有这个arguments对象的函数。

在递归中使用这个内部属性可以消除紧密耦合现象。

//阶乘
function factorial(num){
    if(num <= 1){
        return 1;
    }else{
        return num * arguments.callee(num-1);
    }
}

注:严格模式下运行时,访问arguments.callee会导致错误。

5.5 函数属性和方法

属性:

1.length -- 表示函数希望接收到的命名参数的个数

2.prototype -- 保存他们所有实例方法的真正所在

方法:

1.apply() -- 接收两个参数,一个是在其中运行函数的作用域,另一个是参数数组

function sum(num1,num2){
    return num1 + num2;
}
function callSum(num1,num2){
    return sum.apply(this,arguments);
}

console.log(callSum(10,20));    //30

2.call() -- 接收多个参数,一个是在其中运行函数的作用域,其余参数直接传给函数

function sum(num1,num2){
    return num1 + num2;
}
function callSum(num1,num2){
    return sum.call(this,num1,num2);
}

console.log(callSum(10,20));    //30
var color = 'red';
var o = {color:'blue'};
function sayColor(){
    console.log(this.color);
}

//使用call()和apply()效果一样
sayColor.call(window);    //red
sayColor.call(this);      //red
sayColor.call(o);         //blue

这两个方法都是用来在特定作用域中调用函数,实际上等于设置函数体内this对象的值

3.bind() -- 这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

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

var objectSayColor = sayColor.bind(o);
objectSayColor();    //blue

4.toLocalString(),toString()和valueOf() -- 该方法始终会返回函数的代码

6.基本包装类型

3个特殊的引用类型:Boolean,Number和String。这些类型与其他引用类型相似,但同时又具有与各自的基本类型相应的特殊行为。实际上每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象。

在读取模式中访问字符串时,后台会自动完成以下处理:

  1. 创建String类型的一个实例
  2. 在实力上调用指定的方法
  3. 销毁实例

以上三个步骤也适用于Number和Boolean类型。

引用类型与基本包装类型的主要区别就是对象的生存期。使用new操作符创建的引用类型的对象,在执行刘离开当前作用域之前都一直保存在内存之中。而自动创建的基本包装类型的对象,只存在于一行代码的执行瞬间,然后立即被销毁,故不能在运行时为基本类型值添加属性和方法。

对基本包装类型的实例调用typeof会返回"object",且所有基本包装类型的对象在转换成布尔值时都为true

以上三种基本包装类型,不建议使用new 操作符创建。

6.1 Boolean类型

var falseObject = new Boolean(false);
var result = falseObject && true;
console.log(result);        //true

var falseValue = false;
var result = falseValue && true;
console.log(result);        //false

6.2 Number类型

3个方法:

  • toFixed()方法 -- 会按照传入的小数位返回数值的字符串表示。
  • toExponential()方法 -- 会按照传人的小数位返回数值的指数形式的字符串表示
  • toPrecision() -- 可以找到表示某个数值的最合适的格式,接收一个参数,即表示的数值的所有数字的位数
/**
* toFiexed()具有自动舍入的特性
**/
var num = 10.005;
console.log(num.toFixed(2));    //10.01

var num = 10.5;
console.log(num.toExponential(1));    //1.1e+1

var num = 99;
console.log(num.toPrecision(1));    //1e+1
console.log(num.toPrecision(2));    //99
console.log(num.toPrecision(3));    //99.0

6.3 String类型

String对象的方法可以在所有基本的字符串值中访问到。其中,继承的valueOf(),toString()和toLocalString()方法,都返回对象所表示的基本字符串值。

属性:length,表示字符串中包含的字符个数。

6.3.1 字符方法

charAt()和charCodeAt()。这两个方法都接收一个参数,即基于0的字符位置。其中,charAt()方法以单字符字符串的形式返回给定位置的那个字符串。而charCodeAt()方法返回指定位置的字符编码。

var stringValue = "hello world";
console.log(stringValue.charAt(1));        //'e'
console.log(stringValue.charCodeAt(1));    //"101"

在JavaScript中,可以使用方括号加数字索引来访问字符串中的特定字符。

6.3.2 字符串操作方法

1. concat() -- 用于将一或多个字符串拼接起来,返回拼接得到的新字符串。在实践中用的最多的还是加号操作符(+).

2.三格基于子字符串创建新字符串的方法:slice(),substrig()和substr()。这三个方法都接收两个参数,第一个参数都是子字符串的起始位置。slice()和substring()的第二个参数都是子字符串最后一个字符后面的位置,而substr()的第二个参数是返回字符的个数。若没有给这三个方法传递第二个参数,则将字符串的末尾作为结束位置。

var str = "hello world";
console.log(str.slice(3));            //"lo world"
console.log(str.substring(3));        //"lo world"
console.log(str.substr(3));           //"lo world"
console.log(str.slice(3,7));          //"lo w"
console.log(str.substring(3,7));      //"lo w"
console.log(str.substr(3,7));         //"lo worl"

再传递给这些方法的参数是负值的情况下,他们的行为就不尽相同了。

  1. slice()方法会将传入的负值与字符串的长度相加
  2. substring()方法将负的第一个参数加上字符串的长度,负的第二个参数转换为0
  3. substr()方法会把所有的负值均转换为0
var str = "hello world";
console.log(str.slice(3,-4));            //"lo w"
console.log(str.substring(3,-4));        //"hel"
console.log(str.substr(3,-4));           //""

6.3.3 字符串的位置方法

indexOf()和lastIndexOf(),从一个字符串中共搜索子字符串,返回子字符串的位置。indexOf()方法从字符串的开头向后搜索字符串,lastIndexOf()方法从末尾向前搜索字符串。两个方法均可一接受两个参数:要查找的子字符串和(可选的)字符串搜索起始位置

6.3.4 trim()方法

这个方法回床子字符串的一个副本,删除前置和后缀所有的空格,然后返回结果。

6.3.5 字符串大小写转换方法

转换成小写:toLowerCase(),toLocaleLowerCase()

转换成大写:toUpperCase(),toLocaleUpperCase()

6.3.6 字符串的模式匹配方法

1.match() :在字符串上调用这个方法,本质上与调用ExpReg的exec()方法相同。match()方法只接收一个参数,要么是一个正则表达式,要么是一个RegExp对象。返回一个数组:数组的第一项是与整个模式匹配的字符串,之后的每一项(如果有)保存着与正则表达式中的捕获组匹配的字符串。

2.search():一个参数:由字符串或者RegExp对象指定的一个正则表达式。返回字符串中第一个匹配项的索引,若无,则返回-1

3.replace():接受两个参数,第一个参数是一个RegExp对象或者一个字符串,第二个参数可以是一个字符串或者一个函数。
    1)第二个参数是字符串

var text = "cat,bat,sat,fat";
var result = text.replace(/(.at)/g,"word($1)");
console.log(result);        //word(cat),word(bat),word(sat),word(fat)

    2)第二个参数是函数。在只有一个匹配项的情况下会想这个函数传入3个参数:模式的匹配项,模式匹配项在字符串中的位置和原始字符串。

4.split():基于指定的分隔符将一个字符串分割成多个子字符串,并将结果放在数组中。分隔符可以是字符串,也可以是一个RegExp对象。split()方法可以接受第二个参数,用来指定返回数组的大小。

6.6.7 localeCompare()方法

这个方法比较两个字符串,并返回下列值中的一个:

  • 如果字符串在字母表中的位置应该排在字符参数之前,则返回一个负数
  • 如果字符串等于字符串参数,则返回0
  • 如果字符串在字母表中应该排在字符参数之后,则返回一个整数

6.6.8 fromCharCode()方法

接收一或多个字符编码,将其转换成字符串。

7.单体内置对象

两个:Global和Math

7.1 Global对象

不属于任何其他对象的属性和方法,最终都是Global对象的属性和方法,例如isNaN(),isFinite(),parseInt()以及parseFloat(),都是Global对象的方法。Global对象还有一些其他的方法。

7.1.1 URI编码方法

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

encodeURI()用于整个URI(例如:http://www.wrox.xom/illegal value.htm),而encodeURIComponent()用于URI中的某一段(例前面URI中的illegal value.htm)进行编码。

区别:

  • encodeURI()不会对本身属于URI的特殊字符进行编码,例如冒号,正斜杠,问好和井字号
  • encodeURIComponent()则会对他发现的任何非标准字符进行编码。
var uri = "http://www.wrox.com/illegal value.htm#start";

console.log(encodeURI(uri));    
//"http://www.wrox.com/illegal%20value.htm#start"

console.log(encodeURIComponent(uri));
//"http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start"

与之对应的两个方法分别是decodeURI()和decodeURIComponent()。他们都只会对使用对应编码方法替换的字符进行码

var uri = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start";

console.log(decodeURI(uri));    
//"http%3A%2F%2Fwww.wrox.com%2Fillegal value.htm%23start"

console.log(decodeURIComponent(uri));
//"http://www.wrox.com/illegal value.htm#start"

7.1.2 eval()方法

eval()就像一个完整的ECMAScript解析器,他只接收一个参数,即要执行的ECMAScript字符串。当解析器发现代码中调用eval()方法时,他会将传入的参数当做实际的ECMAScript来解析,然后把执行结果插入原来的位置。通过eval()执行的代码可以引用在包含环境中定义的变量。

在eval()中创建的任何变量或函数都不会被提升,他们只在eval()执行的时候创建。

7.1.3 window对象

Web浏览器将全局对象作为window对象的一部分来加以实现,因此,在全局作用域中声明的变量和方法都成了window对象的属性。

7.2 Math对象

7.2.1 属性

属性 说明
Math.E 自然对数的底数
Math.LN10 10的自然对数
Math.LN2 2的自然对数
Math.LOG2E 以2为底E的对数
Math.LOG10E 以10为底E的对数
Math.PI 圆周率的值
Matn.SQRT1_2 1/2的平方根
Math.SQRT2 2的平方根

7.2.2 min()和max()方法

用于确定一组数之中的最小最大值,接收多个参数。若想接受数组,则使用apply()方法

var value = [1,2,3,4,5,6];
var max = Math.max.apply(Math,value);
console.log(max);    //6

7.2.3 舍入方法

  • Math.ceil()执行向上舍入,即总是将数值向上舍入位最接近的整数
  • Math.floor()执行向下舍入,即总是将数值向下舍入为最接近的整数
  • Math.round()执行标准舍入,即总是将数值四舍五入为最接近的整数

7.2.4 random()方法

Math.random()方法返回一个大于等于0小于1的随机数[0,1)。

利用Math.random()从某个证书范围内随机选择一个值的语法:

var value = Math.floor(Math.random() * num + first);
//其中,num是可能值得总数,first是整数范围的最小值

var random = Math.floor(Math.random()*9+2);
//取2到10中一个随机整数

7.2.5 其他方法

方法 说明 方法 说明
Math.abs(num) 返回num值得绝对值 Math.asin(x) 返回x的反正弦值
Math.exp(num) 返回Math.E的num次幂 Math.atan(x) 返回x的反正切值
Math.log(num) 返回num的自然对数 Math.atan2(y,x) 返回y/x的反正切值
Math.sqrt(num) 返回num的平方根 Math.sin(x) 返回x的正弦值
Math.acos(x) 返回x的反余弦值 Math.tan(x) 返回x的正切值

猜你喜欢

转载自blog.csdn.net/Liwen_Ye/article/details/81223684