【javascript高级程序设计】读书摘录2 第五章、引用类型

第五章、引用类型

1、创建Object的方式有两种

第一种是使用new操作符: varperson = new Object();

第二种是使用对象字面量表示法:var person = {name : ‘test’}; (注意最后一个属性后面不要加逗号,否则在某些浏览器中可能会出现错误),在使用字面量创建对象时,属性名也可以使用字符串:var person = {“name”:”test”};

2、访问对象属性时可以使用点表示法,也可以使用方括号表示法来访问对象的属性:

var person = {“name”:”test”};
alert(person.name);
alert(person[“name”]);

这两种方式没有太大区别,但是使用方括号语法可以通过变量来访问属性。

1、  Array类型:

var arr1 = new Array();

var arr2 = Array(1, 2, 3);

var arr3 = [];

2、  栈方法:

ECMAScript提供了一种让数组的行为类似于其他数据结构的方法,例如栈和队列

 var stack = [];

 for( var i = 0; i< 10; i++ ){
     stack.push(i );
 }

 console.log( stack.join("-") );

 for( var i = 0; i < 5; i++ ){
     console.log("pop: " + stack.pop() );
  }

3、  队列方法:

队列方法在队列的末尾添加项,而在队列的前端移除项

var queue = [];

for( var i = 0; i < 10; i++ ){
   queue.push( i );
}

console.log( queue.join("-") );

for( var i = 0; i < 5; i++ ){
   console.log( "shift: " + queue.shift() );
}

unshift的作用与shift相反,能在数组的前端添加任意多个项并返回数组的长度。

4、  数组函数

sort可以完成对数组的排序,reverse会翻转数组项的顺序。

与大多数排序函数类似,sort可以接受一个比较函数,从而实现对数组的自定义排序:

concat(): 基于原来的数组拼接新的数组:

var colors = ["red","green" ];
console.log( colors.concat(["blue","yellow"]) );

slice(): 获取数组的一部分作为新的数组:

var arr = [1, 2, 3, 4, 5];
console.log( arr.slice(2, 4));

         splice数组:数组中插入、删除或者替换项:

(1)、删除

 var colors = ['r', 'g', 'b'];
 var removed = colors.splice(0, 2);
 console.log(removed);

 (2)、添加

var colors = ['r', 'g', 'b'];
var removed = colors.splice(1, 0, "added");
console.log(colors);

 (3)、替换

var colors = ['r', 'g', 'b'];
var removed = colors.splice(1,1 , "redd","blue");
console.log(removed);

8、Date类型

         Date类型的valueOf方法根本不返回字符串,而是返回日期的毫秒表示。因而可以直接用比较操作符直接比较日期值:

var date1 = new Date(2007, 1, 1);
var date2 = new Date(2007, 1, 2);
console.log( date1 < date2 );

         Date的组件方法,参考文档,比较多,不细列出。比较重要的有:

getTime() : 返回表示日期的毫秒数,与valueOf一致。

setTime(): 设置日期

getFullYear(): 取得四位数的年份

getMonth(): 取得月份

getDate(): 返回月份中的天数

……

9、RegExp类型

         ECMAScript通过RegExp类型来支持正则表达式。

         varpattern = /pattern/flags

flags有三种:

         g:表示全局匹配模式,模式被应用于整个字符串,而不是发现第一个匹配项时停止

         i:不区分大小写的匹配

         m:多行模式,到达一行文本结尾时还会继续查找下一行的文本。

另一种创建正则表达式的方式是通过RegExp对象:

var pattern = newRegExp("[bc]at", "i");

传递给RegExp的两个参数都是字符串,不能把正则表达式的字面量直接传递给RegExp。由于RegExp构造函数的模式参数是字符串,因而在某些情况下需要对字符进行双重转义,所有元字符都必须双重转义。

         RegExp的实例都具有如下的一些属性:

(1)      global表明是否启用了g标志

(2)      ignorecase是否启用了i标志

(3)      lastIndex表示搜索下一个匹配项的字符位置,从0开始

(4)      multiline  是否启用了m标志

(5)      source 正则表达式的字符串表示,按照字面量形式返回。

var pattern1 = /\[bc\]at/i;
var pattern2 = newRegExp("\\[bc\\]at", "i");
console.log(pattern1.global);
console.log(pattern1.ignoreCase);
console.log(pattern1.multiline);
console.log(pattern1.lastIndex);
console.log(pattern1.source);
console.log(pattern2.source);

RegExp对象有两个常见实例方法:exec() 和 test();

         exec专为捕获组而设计的,exec接收一个字符串参数,返回包含匹配项的数组:

         test()接收一个字符串参数,在参数与正则表达式匹配时返回true, 否则返回false

ECMAScript正则表达式不支持的特性:

         (1)、匹配字符串开始和结束的\A和\Z锚点

         (2)、向后查找lookbehind

         (3)、并集和交集类

         (4)、原子组

         (5)、Unicode支持(单个字符除外)

         (6)、命名的捕获组

         (7)、s和x匹配模式

         (8)、条件匹配

         (9)、正则表达式注释

10、Function类型

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

         由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没有什么不同,一个函数可以有多个名字:

function sum(a, b){
         returna + b;
}
 
var antSum = sum;
console.log( antSum(1, 2) );
sum = null;
console.log( antSum(1, 2) );

将函数名想象成指针,也就解释了为什么ECMAScript中没有函数重载的概念。

解析器在加载数据时,对于函数声明和函数表达式并非一视同仁:解析器会率先读取函数声明,并使其在执行任何代码之前可用;而对于函数表达式,则必须等到解析器执行到它所在的代码行时才会真正被解释执行,如下的方式在执行期会导致错误:

console.log( sum(1, 2) );

var sum = function(a, b){
         returna + b;
}

由于ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样吧一个函数传递给另一个函数,而且可以把一个函数作为另一个函数的结果返回。从这个意义上说,函数是ECMAScript中的一等公民。

         可以从一个函数中返回函数,例如创建一个根据属性名进行比较的函数(用于排序):

function createCompare( prop ){

   return function( obj1, obj2 ){

       var v1 = obj1[ prop ];
       var v2 = obj2[ prop ];

       if( v1 < v2 ){
           return -1;
       }else if( v1 > v2 ){
           return 1;
       }else{
           return 0;
       }  
   }; 

}   

注意这里如果使用return v1 – v2;则是错误的,因为对于字符串而言, 字符串相减返回的结果是NaN。

         函数内部,有两个特殊的属性:this和arguments。其中arguments是一个类数组对象,其中包含了传入函数的所有参数:

functiontest(){
         console.log( arguments );
         console.log(arguments.length );
}

test(1,2, 3, 4, 5);

虽然arguments的主要作用是保存函数参数,但是这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对

象的函数:

function factor( num ){
   if( num <= 1 ){
       return 1;
    }
   return num * arguments.callee( num - 1 );

}

使用arguments.callee可以保证无论函数使用什么名字,都能正确完成递归(解除耦合)。

         函数内部另一个特殊对象是this,this是函数在执行时所处的作用域(当前网页的全局作用域中调用函数时,this对象引用的就是window)

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

function sum(a, b){
     return a + b;
}
console.log(sum.length);

prototype可以说是ECMAScript中最重要的属性了(详见第六章)

每个函数都包含两个继承而来的方法:apply和call,这两个方法的用途是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值:

function sum(a, b){
   return a + b;
}

function callSum(a, b){
         //函数是在全局作用域被调用的,因此this == window
   return sum.apply(this, arguments);
}
function callSum2(a, b){
   return sum.apply( this, [a, b] );
}

console.log(callSum(1, 2));
console.log(callSum2(2, 3));

call方法和apply方法作用相同,它们的区别在于接收参数的方式不同:

function callSum(a, b){
         return sum.call(this, a, b);
}

console.log(callSum(1, 3));

实际上,传递参数并非call和apply真正的用武之地,它们真正强大的地方在于能够扩充函数赖以运行的作用域。:

var color = "red";
var o = {color : "blue"};

function sayColor(){
   console.log(this + " this.color: " + this.color);
}

sayColor();
sayColor.call(this);
sayColor.call( o );

用call和apply来扩从作用域的最大好处,就是对象不需要与方法有任何耦合关系

11、基本包装类型

         为了便于操作基本类型值,ECMAScript还提供了3个特殊的引用类型:Boolean、Number和String.

         引用类型和基本包装类型的区别在于对象的生存期,使用New操作符创建的引用类型的实例,在执行流离开当前作用域之前一直都保存在内存中,而自动创建的自动包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。这意味着不能为基本类型值添加属性和方法:

vars = "some test";
s.color= "red";
console.log(s.color );//undefined

 不建议显式地创建基本包装类型的对象。

         toFixed和 toExponential,toPrecision 两个用于格式化数值的方法。

         使用typeof操作符测试基本类型数值时,始终会返回"number",而在测试Number对象时,则会返回object. Number对象是Number类型的实例,而基本类型的则不是。

String类型:

         String类型的每个实例都含有一个length属性,表示字符串包含多少个字符(多字节字符依然算一个字符):

var s = "some test好";
console.log( s.length );

charAtcharCodeAt用于访问字符串中的特定字符。其中charAt返回给定位置的单个字符,而charCodeAt则返回的是指定位置的字符编码:

vars = "hello";
console.log(s.charAt(2));//l
console.log(s.charCodeAt(2));//108

concat用于将一个或者多个字符串拼接起来,返回拼接到的新字符串。

slice, substr, substring: 基于子字符串创建新的字符串(它们都不修改原始字符串的值,而只是返回一个基本类型的字符串值):

string.slice(start, end);

string.substring(start, end);

string.substr(start, len);

indexOf返回子字符串的位置,如果没有找到,返回-1(向后搜索)

lastIndexOf返回子字符串最后一次出现的位置(向前搜索)

可以通过循环查找,找出所有子串在字符串中的所有位置:

字符串匹配:match和search

容易搞混的地方: test()和exec()是正则表达式的方法,RegExp.test(str), RegExp.exec(str);

而match和search是字符串的操作方法,str.match(RegExp), str.search(RegExp)

replace用于替换,第一个参数可以是RegExp正则表达式或者字符串,如果是字符串,那么只会替换第一个子字符串,如果要替换所有的字符串,可以提供一个正则表达式,而且指定全局标志(g).第二个参数可以将正则表达式操作得到的值插入到结果字符串中:

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

console.log( result );

replace的第二个参数也可以是一个函数:在只有一个匹配项的情况下,会向这个函数传入3个参数:模式的匹配项、模式匹配项的起始位置和原始的字符串:

function htmlEscape( str ){

   return str.replace(/[<>"&]/g, function( match, pos, orig){
       switch( match ){
           case "<":
                return "<";
                break;
           case ">":
                return ">";
                break;
           case "&":
                return "&";
                break;
           case "\"":
                return """;
                break;
       }
   });
}

split用于模式分割:

var colorStr = "red, blue, green,red";
console.log( colorStr.split(","));
console.log( colorStr.split(",",2) );

fromCharCode接收一个或者多个字符编码,然后将他们转换为一个字符串:

var str = String.fromCharCode( 104, 101,108, 108, 111 );
console.log( str );

12、内置对象

         Global对象:不属于任何其他对象的属性和方法,最终都是Global对象的属性和方法。实际上,没有全局变量或者全局函数,所有在全局作用域中定义的属性和函数,都是Global对象的属性。

         URL编码方法:

Global对象的encodeURI和encodeURIComponent()方法可以对URI进行编码。

encodeURI主要用于对整个URI进行编码,而encodeURIComponent主要用于对URI的某一段进行编码。它们的主要区别在于,encodeURI不会对本身属于URI的特殊字符进行编码,例如冒号:,正斜杠/,问号?和井号#; 而encodeURIComponent则会对它发现的任何非标准的字符进行编码:

var uri = "http://www.prox.com/illvalue#start";

//http://www.prox.com/ill%20value#start
console.log( encodeURI(uri) );

//http%3A%2F%2Fwww.prox.com%2Fill%20value%23start
console.log( encodeURIComponent(uri) );

与encodeURI和encodeURIComponent对应的两个方法分别是decodeURI和decodeURIComponent,它们是一一对应的,decodeURI只能对使用encodeURI编码的字符进行解码,同样,decodeURIComponent只能对使用encodeURIComponent编码的字符进行解码。

eval:

eval中可以定义函数,这个函数可以被外部调用

eval(" functionsayHi(){console.log('hi');} ");

sayHi();

window对象: ECMAScript虽然没有指出如何直接访问Global对象,但Web浏览器都是将这个全局变量作为Window对象的一部分加以实现的。因此,在全局作用域中声明的所有变量和函数,都成了window对象的属性.

var color = "red";

function sayColor( ){
   console.log(window.color);
}

window.sayColor();

Math对象

         Math对象的属性包括:

Math.E

Math.LN10               

Math.LN2

Math.LOG2E

Math.LOG10E

Math.PI

Math.SQRT1_2

Math.SQRT2

         Math对象的方法:

(1)      min和max方法,用于确定一组数值中的最大和最小值。

(2)      舍入方法: Math.ceil(), Math.floor(), Math.round

(3)      random()方法。返回0-1之间的随机数,不包含0和1,套用公式:

         val = Math.floor(Math.random()* 可能的值总数 + 第一个可能的值)可以实现在一个range中选择一个值。

functionselectFrom(low, high){
     var nums = high – low + 1;
     return Math.floor( nums * Math.random() + low );
}

console.log(selectFrom(2,10));

(4)       abs(num), exp(num), log(num),pow(num, power)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值