《JavaScript高级程序设计》之笔记三

2017-03-04  本文已影响2人  fanyank

第五章 引用类型

引用类型是一种数据结构,用于将数据和功能组合在一起,他也常被称为类(但是并不是类)。

1. 创建对象的两种方法 :

//使用object类型
var person = new Object();//等价于var person = {};
person.name = "Jack";
person.age = 29;
//使用对象字面量表示法(优点是使用大量属性时无需重复写对象名)
var person = {
  name : "Jack",
  age : 29
}//注意属性之间用逗号隔开,最后一个属性后面没有逗号
//另外在使用对象字面量表示法时,属性名也可以使用字符串(这样属性名就变成可读的哦)
var person = {
  "name" : "Jack",
  "age" : 29
}

2. 数组 :

在JavaScript中你可以用数组来表是任何一种数据,甚至在同一个数组中时也是如此,并且JavaScript数组的长度是动态调整的,你可以在任何时候给数组添加值或者删除值。

//创建数组的方法
var colors = new Array();
var colors = new Array(20);
var colors = new Array("Blue","Green","Red");
//利用上述方法new操作符可以省略
//更为常见的是使用字面量表示法
var colors = ["Blue","Green","Red"];
//数组的length属性并不是只读的,你可以用它来删除数组项或新增数组项
var colors = ["Blue","Green","Red"];
colors.length = 2;       //删除了Red项
colors[colors.length] = "Red";
colors[colors.length] = "Yellow";   //随时为数组增添项

3. 栈方法 :

//push
var colors = new Array();
var count = colors.push("Red","Blue");
alert(count);      //2
//pop
var colors = new Array();
var count = colors.push("Red","Blue");
var item = colors.pop();
alert(item);       //Blue
alert(colors.length);    //1

4. 队列方法 :

//shift     
var colors = new Array();
var count = colors.push("Red","Blue");
var item = colors.shift();
alert(item);       //Red
alert(colors.length);     //1
//unshift
var colors = new Array();
var count = colors.push("Red","Blue");
var counts = colors.unshift("Black");
alert(colors.counts);      //3

5. 重排序方法 :

//reverse
var number = [1,2,3,4,5];
number.reverse();
alert(number);     //5,4,3,2,1
//sort
var number = [0,1,5,10,15];
number.sort();
alert(number);      //0,1,10,15,5(字符串比较规则嘛)
//那么如何按照从小到大来比排列呢?
function compare(a,b){
  if(a < b){
    return -1;
  }
  else if(a > b){
    return 1;
  }
  else{
    return  0;
  }
}
var number = [0,1,5,10,15];
number.sort(compare);
alert(number);       //0,1,5,10,15
//要想从大到小只需将compare倒过来即可
//看到这里你可能想说,好麻烦啊,compare就不能简单点吗?
//答案是可以,但是只能对数值类型或者valueOf()方法返回数值类型的对象使用,函数定义如下:
function compare(a,b){
  return a - b;
}

6. 操作方法 :

//concat
var colors = ["Green"];
var colors2 = colors.concat("Yellow",["Blue","Red"]);
alert(colors2);   //Green,Yellow,Blue,Red
//slice
var colors = ["Green","Red","Blue","Yellow"];
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,3);
alert(colors2);     //Red,Blue,Yellow
alert(colors3);     //Red,Blue
//splice
var colors = ["Red","Green","Blue"];
var removed = colors.splice(0,1);   //删除第一项
alert(colors);    //Green,blue
alert(removed);    //Red        
removed = colors.splice(1,0,"Yellow","Orange"); //从位置一开始插入两项
alert(colors);    //Green,Yellow,Orange,Blue
alert(removed);   //返回的是空数组
removed = colors.splice(1,1,"Red","Purple"); //插入两项,删除一项
alert(colors);   //Green,Red,Purple,Orange,Blue
alert(removed);  //Yellow
//join
var names = new Array("Tom","John","Marry");
alert(names.join("|"));   //Tom|John|Marry
alert(names);             //Tom,John,Marry

7. 位置方法 :

var number = [1,2,3,4,5,4,3,2,1];
alert(number.indexOf(4));          //3
alert(number.lastIndexOf(4));      //5
//还可以从你指定的位置开始查找,只需传入两个参数即可
alert(number.indexOf(4,4));                //5(别犯蒙)
alert(number.lastIndexOf(4,4));            //3(别犯蒙)

8. 迭代方法 :

简而言之就是对数组的每一个元素进行操作。

var number = [1,2,3,4,5,4,3,2,1];
//every
var everyResult = number.every(function(item,index,array){
  return(item > 2);
});
alert(everyResult);        //false
//some
var someResult = number.some(function(item,index,array){
  return(item > 2);
});
alert(someResult);         //true
//filter
var filterResult = number.filter(function(item,index,array){
  return(item > 2);
});
alert(filterResult);       //[3,4,5,4,3]
//map
var mapResult = number.map(function(item,index,array){
  return item * 2;
});
alert(mapResult);          //[2,4,6,8,10,8,6,4,2]
//forEach
number.forEach(function(item,index,array){
//执行某些操作
});

9. 缩小方法 :

//利用reduce累加求和
var number = [1,2,3,4,5];
var sum = number.reduce(function(x,y){
  return x + y;
});
alert(sum);         //15
var sum2 = number.reduceRight(function(x,y){
return x + y;
});
alert(sum2);        //15

10. Date类型 :

//创建一个日期对象
var now = new Date();

在没有给 Date() 构造函数传入任何参数的情况下,Date() 函数会自动调用当前的日期和时间。如果人为的控制时间,则需用到以下方法...

Date.parse() : 该方法接受字符串参数,事实上,如果给 Date() 函数传入字符串参数,Date() 会在后台默认调用 parse() 方法,如果传入的参数不能表示日期,则会返回 NAN

Date.UTC() : 该方法传入的参数是数值,按顺序传入年,月,日,时,分,秒参数,其中,只有前两个参数是必须要传的(年和月),其他的在不传的情况下默认为0,月份使用偏移量的方法来表示(即一月是0)。

//不给Date传入参数调用当前时间
var now = new Date();
alert(now);    //Sat, 16 Apr 2016 07:50:35 GMT
//Data.parse()
var someDate = new Date(Date.parse("May 25,2004"));  //创建了一个2004年5月24号的日期对象
var someDate = new Date(Date.UTC(2005,4,5,17,55,55));  //创建了一个2005年5月5号17点55分55秒的日期对象               
//事实上我们完全可以根据Date()函数的特点省略Date.parse()和Date.UTC(),因为Date()会根据参数的类型自动在后台调用。
var someDate = new Date("May 25,2004");  //创建了一个2004年5月24号的日期对象
var someDate = new Date(2005,4,5,17,55,55);  //创建了一个2005年5月5号17点55分55秒的日期对象

另外JavaScript添加了 Date.now() 方法,表示调用这个方法时的日期和时间的毫秒数。

var start = Date.now();     //取得开始时间
doSomething();              //调用函数
var stop = Date.now();      //取得结束时间
result = stop - start;
//使用+操作符把Date()对象转换成字符串也可以达到同样的目的(+操作符在遇见对象时会自动调用toString()方法,取得对象的字符串值)
var start = +new Date();
doSomething();
var stop = +new Date();
result = stop - start;
//使用Date.now()方法返回的只是一个时间戳(一堆表示毫秒的数字),直接输出是看不懂的,所以我们需要将时间戳转换成给正常人看的日期
var now = Date.now();
alert(now);                 //1460792002349(时间戳)
var nowTime = new Date(now);
alert(nowTime.toLocaleString());   //2016/4/16 下午3:35:50
//还有很多转换时间戳的方法
alert(nowTime.toDateString());    //Sat Apr 16 2016
alert(nowTime.toTimeString());    //15:45:43 GMT+0800 (CST)
alert(nowTime.toLocaleDateString());      //2016/4/16
alert(nowTime.toLocaleTimeString());      //下午3:47:53
alert(nowTime.toUTCString());  //Sat, 16 Apr 2016 07:50:35 GMT

11. RegExp类型 :

内容太多,主要用于验证一些字符串。具体内容可以参考廖雪峰的正则表达式教程

12. Function类型 :

//定义函数的两种方法,两种方式完全一样
function sum(num1,num2){
  return sum1 + sum2;
}      //第一种
var sum = function(num1,num2){
return sum1 + sum2;
}       //第二种

在JavaScript中,函数名只起到一个指针的作用,故可以像其他变量一样使用函数名来赋值等操作。

function sum(sum1,sum2){
  return sum1 + sum2;
}
var anotherSum = sum;
alert(anotherSum(10,10));      //20
sum = null;
alert(another(10,10));         //20

JavaScript函数也没有重载的概念,还是因为函数名只起到了一个指针的作用,一旦函数名一样,那么后定义的函数将覆盖前面所定义的函数。

var sum = function(sum1,sum2){
  return sum1 + sum2;
}
var sum = function(sum1,sum2){
  return sum1 - sum2;
}     //将覆盖前面所定义的函数
alert(sum(10,2));      //8
//函数的声明与函数表达式:
//JavaScript引擎会在代码执行前将函数的声明放在源代码树的顶部,所以即使后声明函数也不会有什么问题
alert(sum(10,10));      //20
function sum(num1,num2){
  return sum1 + sum2;
}
//但是如果这样做就不对了
var sum = function(num1,num2){
  return sum1 + sum2;
}      //这样做会发生错误,原因是这是一个对sum初始化语句,而不是函数的声明,开头讲的两个函数的定义方法也仅有这一种区别

继续深入理解函数名是指针的作用,函数名还可以被当做另一个函数的参数来传递,也可以作为另一函数的返回值。

//用作函数的参数       
function callSomeFunction(someFunction,someArgument){
  return SomeFunction(someArgument)
}      //接受函数的函数
function add10(num){
  return num + 10;
}      //被传递的函数
var result = callSomeFunction(add10,10);
alert(result);      //20
function getGreeting(name){
  return "Hello," + "name";
}
var hello = callSomeFunction(getGreeting,"Jack");
alert(hello);      //Jack

//用作函数的返回值
function creatComparisonFunction(propertyName){
  return function(object1,object2){
    var value1 = object1[property];
    var value2 = object2[property]; //使用方括号取得property值
    if(value1 < value2){
      return -1;
    }
    else if(value1 > value2){
      return 1;
    }
    else{
      return 0;
    }
  }
}
var data = [{name:"Jack",age:28},{name:"Sam",age:29}];
data.sort(creatComparisonFunction("name"));
alert(data[0].name);     //Jack
data.sort(creatComparisonFunction("age"));
alert(data[0].name);      //Sam

在函数的内部,有两个特殊的 对象 ,一个是 arguments ,一个是 this

//callee
//来看一个阶乘函数
function factorial(num){
  if(num <= 1)
    return 1;
    else
    {
      return num * factorial(num - 1);
    }
}//我如果修改了函数名还得修改函数内部的代码(factorial),现在我不想这么做,能不能用一个东西来代替函数内部的函数名(factorial)
//这就需要用到了arguments的callee属性了
function factorial(num){
  if(num <= 1)
    return 1;
    else
    {
      return num * arguments.callee(num - 1);
    }
}     //使用arguments.callee代替了原函数名,这样便保证了无论引用函数时是什么名字,都可以正常的进行递归调用啦
var trueFactorial = factorial;
factorial = null;
alert(trueFactorial(5));    //120
alert(trueFactorial(5));    //错误
//this
window.color = "Blue";
var o = {color:"Red"};
function sayColor(){
  alert(this.color);
}
sayColor();      //Blue
o.sayColor = sayColor;
o.sayColor();    //Red
//caller
function outer(){
  inner();
}
function inner(){
  alert(arguments.callee.caller);
}
outer();   //因为outer()调用了inner,所以arguments.callee.caller就指向了outer()

函数属性和方法 :
前面曾经提到过,函数 也是对象,既然是对象,那么函数也有着自己的属性和方法,每个函数包含两个属性:lengthprototype

每个函数都包括两个非继承而来的方法,apply()call(),这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内的 this 值。

function sum(num1,num2){
  return sum1 + sum2;
}
//apply
function callSum1(num1,num2){
  return sum.apply(this,arguments);  //传入arguments
}
function callSum2(num1,num2){
  return sum.apply(this,[num1,num2]);   //传入数组
}
alert(callSum1(10,10));     //20
alert(callSum2(10,10));     //20
//call
function callSum(num1,num2){
  return sum.call(this,num1,num2);
}
alert(callSum(10,10));      //20
//改变函数的运行域
var o = {color:"Blue"};
window.color = "Red";
function sayColor(){
  alert(this.color);
}
sayColor.call(this);     //Red
sayColor.call(window);   //Red
sayColor.call(o);        //Blue
//bind
window.color = "Red";
var o = {color:"Blue"};
function sayColor(){
  alert(this.color);
}
var anotherColor = sayColor.bind(o);
anotherColor();   //Blue

13. 基本包装类型 :

为了便于操作基本类型值,JavaScript提供了3个特殊的引用类型:Boolean,Number,String.这些类型同时具有与各自基本类型相应的特殊行为。
实际上,每当读取一个基本类型的时候,后台就会自动创建一个与其对应的基本包装类型的对象,从而让我们调用一些方法来操作这些数据

var s1 = "some text";
var s2 = s1.subString(2);    //"me text"
//在后台跑的程序为
var s1 = new String("some text");
var s2 = s1.subString(2);
s1 = null;
//经过上述步骤处理,字符串就变得和对象一样了,也就意味可以像对象那样去调用方法了,上述步骤同样适用于Boolean,Number类型
//同时需要指明的是,我们不能自己给Boolean,Number,String添加属性,只能调用自带的方法

那么怎样来检测到底是 基本包装类型,还是 基本类型 呢?

var s1 = "abc";
var s2 = new String("abc");
alert(typeof s1);    //"string"
alert(typeof s2);    //"object"
alert(s1 instanceof String);    //true
alert(s2 instanceof String);    //false

接下来开始介绍 Boolean,Number,String

var num = 10;
alert(num.toFixed(2));  //10.00
//charAt()
var stringValue = "hello,world";
alert(stringValue.charAt(1));     //"e"
//charCodeAt()
var stringValue = "hello,world";
alert(stringValue.charCodeAt);    //"101"
//JavaScript还定义了一种更简单的访问个别字符的方法
var stringValue = "hello,world";
alert(stringValue[1]);     //"e"
//concat()
var stringValue = "hello ";
var result = stringValue("world");
alert(result);     //"hello world",其实更多情况下用的是加号操作符来拼接字符串
//JavaScript还提供了三个创建新字符串的方法,即 slice() substr() substring()
var stringValue = "hello world";
alert(stringValue.slice(3));     //"lo world"
alert(stringValue.substr(3));    //"lo world"
alert(stringValue.substring(3)); //"lo world"
alert(stringValue.slice(3,7));   //"lo w"
alert(stringValue.substr(3,7));  //"lo w"
alert(stringValue.substring(3,7)); //"lo worl"
//indexOf() lastIndexOf()
var stringValue = "hello world";
alert(stringValue.indexOf("o"));     //4,从前往后
alert(stringValue.lastIndexOf("o"));  //7,从后往前
//传递两个参数
alert(stringValue.indexOf("o",6));    //7,从位置6开始查找
alert(stringValue.lastIndexOf("o",6)); //4,同上
//可以通过循环调用的方法来找到字符串中所用匹配到的字符
var stringValue = "hello world";
var positions = new Array();
var pos = stringValue.indexOf("o");
while(pos > -1)
{
  positions.push(pos);
  pos = string.indexOf("o",pos + 1);
}
alert(positions);  //"4,7"
//tirm()
var stringValue = "   hello world   ";
alert(stringValue.tirm());  //"hello world"
//toLowerCase() toUpperCase()
var stringValue = "Hello world";
alert(stringValue.toLowerCase());    //"hello world"
alert(stringValue.toUpperCase());    //"HELLO WORLD"
//match()
var text = "cat,bat,sat,fat";
var partten = /.at/g;
var matches = text.match(partten); //传入一个正则表达式
alert(matches); //"at,at,at,at"
//search()
var text = "cat,bat,sat,fat";
var pos = text.search(/at/g);
alert(pos);     //1,5,9,13
//replace()
var text = "cat,bat,sat,fat";
var result = text.replace(/at/g,"ond");
alert(result);   //"cond,bond,sond,fond"
//如果第二个参数是字符串,那么还可以使用一些特殊字符序列,将正则表达式操作得到的值插入到结果字符串中。下表列出了JavaScript提供的特殊字符序列
特殊字符序列表特殊字符序列表
//通过上表特殊的字符序列,可以使用最近一次匹配结果的内容
var text = "cat,bat,sat,fat";
result = text.replace(/.at/g,"word($1)");
alert(result);   //"word(cat),word(bat),word(sat),word(fat)"
//split()
var text = "cat,bat,sat,fat";
var result = text.split(",");
alert(result);    //["cat","bat""sat""fat"]
var result1 = text.split(",",2);
alert(result1);    //["cat","bat"]
var result2 = text.split(/[^/,]+/);
alert(result2);    //["",",",",",""]
//localCompare()
var stringValue = "yellow";
alert(stringValue.localCompare("brown"));    //1
alert(stringValue.localCompare("yellow"));   //0
alert(stringValue.localCompare("zoo"));      //-1

14. 单体内置对象 :

单体内置对象的定义是 : 由JavaScript实现提供的,不依赖于宿主环境的对象,这些对象在JavaScript程序执行之前就已经存在了

Global对象 有自己的方法

这几种方法都用于对URI进行编码或者解码,这里不再一一介绍。

//eval()
eval("alert('hi')");     //hi
//上面的代码等价于下面这行代码
alert("hi");             //hi
//包含环境中的变量
var msg = "Hello world";
eval("alert(msg)");      //Hello world
//min()
var min = Math.min(3,23,44,78);
alert(min);     //3
//max()
var max = Math.max(3,23,44,78);
alert(max);      //78
//这里介绍一种求数组里面最值得方法
var arr = [1,2,3,4,5,6,7,8];
min = Math.min.apply(Math,arr); //注意这里apply方法的参数
alert(min);      //1
//ceil()
alert(ceil(25.9));     //26
alert(ceil(25.5));     //26
alert(ceil(25.1));     //26
//floor()
alert(floor(25.9));     //25
alert(floor(25.5));     //25
alert(floor(25.1));     //25
//round()
alert(round(25.9));      //26
alert(round(25.5));      //26
alert(round(25.1));      //25
//random()
//返回一个1到10的整数
var num = Math.floor(Math.random() * 10 + 1);
//返回一个2到10的整数
var num = Math.floor(Math.random() * 9 + 2);
//实际上,这样做不是特别的直观,我们可以自己写一个函数来令它更直观一些
function selectFrom(lowerValue,upperValue){
  var choices = upperValue - lowerValue + 1;
  return Math.floor(Math.random() * choices + lowValue);
}       
var num = selectFrom(2,10);
alert(num);   //介于2到10之间的一个随机数
//具体应用
var colors = ["green","blue","red"];
var color = colors[selectFrom(0,colors.length - 1)];
alert(color);    //返回一个随机的颜色
上一篇 下一篇

猜你喜欢

热点阅读