2. Javscript学习笔记——引用类型

2. 引用类型

2.1 Object类型

Object 是一个基础类型,其他所有类型都从 Object 继承了基本的行为。

对象是一个包含相关数据和方法的集合(通常由一些变量和函数组成,我们称之为对象里面的属性和方法)

 1 ////【创建Object 实例】【用于储存和传输数据】
 2   //使用new操作符,后面跟Object构造函数
 3   var person = new Object(); 
 4   person.name = 'bin';
 5   person.age = 19;
 6   //传参
 7   var s = new Object('string');//s就会变成String基本包装类型
 8   var i = new Object(1);//Number基本包装类型
 9 10   //使用对象字面量
11   var person = {
12       name : 'bin', //属性名也可以用字符串
13       age : 19, 
14       3 : 'three' //属性名数字的话,会被自动转换为字符串
15   }; //然后也可以用 xxx.yy=zz; 的方式来添加属性
16 17   //// 【访问对象的属性】
18   alert(person['name'])
19   alert(person[变量]) //[]可以通过过变量来访问属性
20   不可以:alert(person.变量) //.不可以通过变量来访问属性
21 22   //给对象方法
23   var obj = {};
24   obj.run = function(){alert(1)};
25   obj.run()//alert(1)
26   obj['run'](arg) //也可以这样调用,obj['run']返回函数对象,(arg)传参

 

2.2 Array类型

  1 //【创建数组】【大小可以动态调整,每个位置可以放任何类型的值】
  2   //使用Array构造函数(new 可以省略)
  3   var nums = new Array(); 
  4   var nums = new Array(10); //如果预先知道数组要保存的元素数量,可以给Array构造函数传递数量,length会变为10
  5   var nums = new Array('a', 'b', 'c'); //也可以直接传递数组的元素
  6   7   //字面量法创建
  8   var nums = [1,2,3]
  9   nums[1] = 'two';
 10  11   //length属性
 12   alert(nums.length);//返回数组长度
 13   nums.length = 2;//去除后一位
 14   nums.length = 100;//增加长度,增加的那部分元素,被定为undefined
 15   nums[nums.length] = 4;//在最后一位添加一个元素
 16  17  18  19   //【检测数组】
 20   var a = 1;
 21   var b = [1,2,3];
 22   Array.isArray(a);//false
 23   Array.isArray(b);//true
 24  25   if(a instanceof Array){doSomething();} //只针对一个全局作用于或一个网页而言,如果网页引用多个框架不适合
 26  27  28  29   //【转换方法】
 30   var a = [1,2,3];
 31   a.toString();//'1,2,3',转换成字符串,以逗号为分隔
 32   a.join('-')//'1-2-3' //接收一个参数,即用作分隔符的字符串
 33  34  35  36   //【栈方法】【就是最新添加的项最早被移除。而栈中项的插入和移除,只发生在一个位置——栈的顶部】
 37   //push()  方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。
 38   //pop()  方法则从数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项。
 39   var colors = new Array(); // 创建一个数组 
 40   var count = colors.push("red", "green");// 推入两项 
 41   alert(count);//2 
 42  43   var item = colors.pop(); // 取得最后一项 
 44   alert(item); //"black" 
 45   alert(colors.length);//2 
 46  47  48  49   //【队列方法】【队列在列表的末端添加项,从列表的前端移除项。】
 50   // push() 是向数组末端添加项的方法,因此要模拟队列只需一个从数组前端取得项的方法。
 51   // shift(),它能够移除数组中的第一个项并返回该项,同时将数组长度减 1。
 52   // unshift() 能在数组前端添加任意个项并返回新数组的长度。
 53   var colors = new Array(); //创建一个数组 
 54   var count = colors.push("red", "green"); //推入两项 
 55   alert(count);    //2 
 56  57   var item = colors.shift();//取得第一项 
 58   alert(item); //"red" 
 59   alert(colors.length); //2 
 60  61  62  63   //【重排序方法】
 64   //reverse() 方法
 65   var nums = [1,2,3];
 66   nums.reverse();
 67   alert(nums)// 3,2,1
 68  69   //sort()方法
 70   var nums = [0, 1, 5, 10, 15]; 
 71   nums.sort(); //默认调用每个项的toString()方法,然后比较进行排序
 72   alert(nums);//0,1,10,15,5 
 73  74   //sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。 比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回 0,如果第一个参数应该位于第二个之后则返回一个正数
 75   function campare(value1,value2){
 76       if(value1>value2){//大的放前面,返回1。小的放前面,反过来即可。
 77           return 1;
 78       }else if(value1<value2){
 79           return -1;
 80       }else{
 81           return 0;
 82       }
 83   }
 84   nums.sort(campare);
 85   alert(nums);//'0,1,5,10,15'
 86  87  88  89   //【操作方法】
 90   //a.concat(b)方法【先创建a的副本,再把b连接到a的副本的末尾,不改变原数组;不给参数,就只创建个副本】
 91   var a = [1,2,3]
 92   var b = ['a','b','c']
 93   var c = a.concat(b)//[1,2,3,'a','b','c']
 94  95   //a.slice(start[, end])方法【截取数组,不改变原数组,接受1或2个参数】
 96   var a = [0,1,2,3,4,5]
 97   a.slice(1);//1,2,3,4,5【从数组位置1,取到末尾】
 98   a.slice(1,4)//1,2,3【不包括end】
 99   a.slice(-5,-1)//1,2,3,4
100 101   //splice(start,length[, 欲添加的值])【改变原数组】
102   //删除
103   var a = [0,1,2,3,4,5];
104   var b = a.splice(0,2);//从第零个截取两个元素,[添加值]为空,则替换为空,即删除
105   alert(a);//2,3,4,5 返回删除后的内容
106   alert(b);//0,1 返回删除的内容
107   //插入
108   var a = [1,2,3];
109   a.splice(0,0,0);//从第一个位置,截取零个元素,添加0,即插入
110   alert(a);//0,1,2,3
111   //替换
112   var a = [1,2,3];
113   a.splice(0,1,'a','b');//从第0个开始删除1个,插入两个
114   alert(a);//'a','b',2,3
115 116 117 118 119   //【位置方法】【相当于===,严格匹配】
120   //indexOf(xxx[, start])【从头开始查找,找不到返回-1,找到返回数组里位置】
121   var nums = [1,2,3,4,5,4,3,2,1];
122   nums.indexOf(4);//3
123   nums.indexOf(4,4)//5【从元素5开始找】
124   //lastIndexOf(xxx[, start])【从末尾开始找】
125   nums.lastIndexOf(4);//5【从左数】
126   nums.lastIndexOf(4,4);//3【从倒数第四个开始找】  
127 128 129 130 //【迭代方法】  
131 //every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。  
132 //some():对数组中的每一项运行给定函数,如果该函数对任一项有一个返回 true,则返回 true。  
133 //filter():对数组中的每一项运行给定函数,返回该函数【会返回 true 的项组成的数组】。   
134 //forEach():对数组中的【每一项运行给定函数。这个方法没有返回值】。   
135 //map():对数组中的每一项运行给定函数,返回【每次函数调用的结果组成的数组】。    
136 //以上方法都不会修改数组中的包含的值。   
137 //EG:  
138 var l = [1,2,3];  
139 var ll = l.map(function($x){  
140     return $x*2;  
141 });  
142 alert(ll)//2,4,6

 

 

 

2.3 Date类型

 1 //【创建日期对象】
 2   var now = new Date();//不传参的话,新建的对象获取的是当前日期
 3   console.log(now);//"Thu Jun 21 2018 13:55:36 GMT+0800 (中国标准时间)"
 4   //Date()给定毫秒。为简化使用Date.parse(),接收一个表示日期的字符串参数,然后返回毫秒。
 5   var now = new Date(Date.parse('6/13/2004'))//格式:'月/日/年'
 6   var now = new Date('6/13/2004');//自动调用Date.parse()方法
 7   //Date.UTC(year,month[从0开始],day(从1),hour,min,sec) 返回标准时间,东八区hour+8【只有年、月必须】
 8   var now = new Date(2008,8,8,10,11)//也可省略
 9 10   Date.now()//返回时间戳,毫秒级别

 

 

 

2.4 RegExp类型(正则表达式)

 1 ///【创建正则表达式】
 2   //用new RegExp(pattern[, flag])【第一个参数是模式字符串;第二个参数可选,模式修饰符】
 3   var box = new RegExp('box','ig');//【i:忽略大小写,g:全局匹配,m:多行匹配 】
 4   //用字面量方式创建,(常用)
 5   var box = /box/ig;
 6  7  8  9 10   ///【测试正则表达式的方法(RegExp提供)】
11   //【test()方法】,在字符串中测试模式匹配,返回true或false
12   var pattern = new RegExp('Box');
13   var str = 'box';
14   alert(pattern.test(str));//false,大小写不一致
15   alert(/Box/i.test(str));//true,一句话匹配
16   //【exec()方法】
17   // 匹配不到返回null,匹配的话返回包含第一个匹配项信息的数组。数组中第一项是与整个模式匹配的字符串,其他项是,子表达式匹配到的字符串(如果有的话)
18   // 对于exec()方法而言,即使在模式中设置了全局标志(g),它每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用 exec()将始终返回第一个匹配项的信息。而在设置全局标志的情况下,每次调用 exec()则都会在字符串中继续查找新匹配项(最后会出现null,test也这样出现false)
19 20 21 22   //【字符串的正则表达式方法(String对象提供)】
23   //【match(pattern)】 返回pattern匹配到的数组或null
24   var pattern1 = /Box/i;
25   var pattern2 = /Box/ig;
26   var str = 'This is a box,box.';
27   alert(str.match(pattern1));//[box]
28   alert(str.match(pattern2));//全局模式[box,box],数组还有个length项
29   //【search(pattern)】 返回字符串中pattern开始位置,只要找到立即返回,g无效,找不到返回-1
30 31   //【replace(pattern,replacement)】 用replacement替换pattern,不改变源字符串
32   var pattern1 = /Box/i;
33   var pattern2 = /Box/ig;
34   var str = 'This is a box,box.';
35   alert(str.replace(pattern1,'xxx'));//This is a xxx,box.
36   alert(str.replace(pattern2,'xxx'));//全局模式,This is a xxx,xxx.
37 38   //【split(pattern)】 返回字符串按指定 pattern拆分的数组,不改变原字符串
39   var pattern = /-/;
40   var str = '1-2-3';
41   alert(str.split(pattern));//['1','2','3']
42 43 44   //【分组模式匹配】
45   var pattern = /(bin){2,3}/;//【每组看成一个元素】
46   alert(pattern.test('bin'));//false
47   alert(pattern.test('binbin'));//true
48   //分组 $1 $2 或 \1 \2  取出内容
49   var pattern = /8(.*)8\s7(.*)7/;
50   var str = '8binbin8 7jin7';
51   pattern.test(str);
52   alert(RegExp.$1);//binbin
53 54   var pattern = /(.*)\s(.*)/;
55   var str = 'google baidu';
56   alert(str.replace(pattern,'$2 $1'));//'baidu google'
57 58 59   //【贪婪匹配用 ?】

 

 

 

 

2.5 Function类型(函数)

函数是对象,函数名只是个引用函数对象的指针

///【函数的参数】
  //ECMAScript函数不介意传进来多少个函数(和形参无关),也不介意传进来的参数是什么数据类型。
  //【可选形参】
  //当调用函数的时候传入的实参数目比函数声明的时候指定的形参数目少,则剩下的形参都将被设置为undefined
  function test(a=1){
      alert(a); //默认输出1
  }
  function test2(a){
      a = a || 1; //当没给定a的值时,a = undefined; a = undefined || 1;则返回 1
      alert(a);
  }
  ​
  ​
  //【arguments对象】【函数里的对象,包含了传入函数的所有参数,不是数组,但类似数组】
  // 可以实现可变长度传参
  function sum(){
      var s = 0;
      for(var i=0; i<arguments.length; i++){
          s += arguments[i]; 
      }
      console.log(s);
      console.log(arguments.length);//返回实参的个数
      console.log(sum.length);//返回形参的个数
  }
  sum(1,2,3);
  ​
  ​
  //【将对象属性用做实参】
  // 当函数参数过多时,就不容易记住那么多的参数;可以用Object的映射关系解决这个问题
  function test(arg){
      console.log(arg.a)
      console.log(arg.b || 9);//设置了默认值
      console.log(arg.c)
  }
  test({a:1,c:3}) //输出 1 9 3
  ​
  ​
  //【作为值得函数】【把函数的指针作为参数(做为值)传给另一个函数,这个指针被用来调用指向函数】
  function add(a,b){
      alert(a+b);
  }
  function exec(a,b,func){
      func(a,b);
  }
  exec(1,2,add);
  ​
  ​
  //【给添加属性】
  // Function 是引用类型,可以添加属性而不被销毁。当函数需要一个“静态”变量来在调用时保持某个值不变,最方便的方式就是给函数定义属性,而不是全局变量。
  function test(){/* code... */}
  test.NUM = 100;
  console.log(test.NUM)
  ​
  ​
  ///【匿名函数】
  //将Function对象赋值给变量
  var box = function(){return 'test';};
  alert(box);//返回函数代码
  alert(box());//返回test
//自我调用
  (function(a){alert(a);})(1);
  (function(a){alert(a);}(1)); //两种方式都可
  ​
  ​
  ​
  ​
  //【函数内部的两个属性】
  //arguments.callee【该属性是一个,他的函数的指针;在ECMAscript5的严格模式中,访问会出错】
  function factorial(num){
      if(num <= 1){
          return 1;
      } else {
          return num*arguments.callee(num-1);//相当于 num*factorial(num-1);解耦合
      }
  }
  ​
  ​
  ///【this属性】【this引用的是它的作用域的对象】 
  alert(widow);//[object Window] window是最顶层的对象
  alert(this);//[object Window] 表示同一个对象
  var n = 1;
  alert(this.n);//1
  aelrt(window.n);//1
var n = 'outter';
  var box = {
      n : 'inner';
      run : function(){alert(this.n);}
  }
  alert(this.n);//outter
  box.run()//inner
  ​
  ​
  window.n = 'outter';
  var box = {
      var n = 'inner'
  }
  function say(){//全局作用域内定义的
      alert(this.n);
  }
  say();// outter【this指向的是全局对象window】
  box.say = say;
  box.say();//inner【this指向的是box对象】
  //函数的名字仅仅是一个包含指针的变量而已。因此,即使是在不同的环境中执行,全局的 say()函数与 box.say() 指向的仍是同一个函数
  ​
  ​
  ​
  ​
  ///【apply()】
  //apply()方法接收两个参数:一个是函数在哪个作用域执行,另一个是参数数组。其中,第二个参数可以是 Array 的实例,也可以是arguments 对象。
  function box(n1, n2){
      return n1+n2;
  }
  function sum(a,b){
      return box.apply(this,[a,b])//【相当于把box函数内的this设置为window作用域】
  }
  ​
  ​
  ///【call()】
  //call()方法与 apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。
  function box(n1, n2){
      return n1+n2;
  }
  function sum(a,b){
      return box.call(this,a,b)//【相当于把box函数内的this设置为window作用域,
  }
  alert(sum(1,2));//3
  ​
  ​
  //【传递参数并非 apply()和 call()真正的用武之地;它们真正强大的地方是【能够扩充函数赖以运行的作域】
  //【使用 call()(或 apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。】
  var n = 'outter';
  var box = {
      n:'inner'
  };
  function say(){
      alert(this.n);
  }
  say();//outter  全局作用域
  say.call(window);//outter
  say.call(this);//outter
  say.call(box);//inner
 

 

2.6 基本包装类型

  • 介绍:

    • 为了便于操作基本类型值,ECMAScript 还提供了 3 个特殊的引用类型:Boolean、Number 和 String。这些类型与本章介绍的其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。

    • var s = 'abc'; s2=s.substr(1);//bc 但基本类型没有方法,相当于内部var s =new String('abc'); s.substr(1); 然后销毁s,s2不销毁。 添加属性也相当与这样,离开后会销毁。

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

      var s1 = "some text"; s1.color = "red"; alert(s1.color); //undefined

      在此,第二行代码试图为字符串 s1 添加一个 color 属性。但是,当第三行代码再次访问 s1 时, 其 color 属性不见了。问题的原因就是第二行创建的 String 对象在执行第三行代码时已经被销毁了。 第三行代码又创建自己的 String 对象,而该对象没有 color 属性。 当然,可以显式地调用 Boolean、Number 和 String 来创建基本包装类型的对象。不过,应该在 绝对必要的情况下再这样做,因为这种做法很容易让人分不清自己是在处理基本类型还是引用类型的值。对基本包装类型的实例调用 typeof 会返回"object",而且所有基本包装类型的对象都会被转换 为布尔值 true。 Object 构造函数也会像工厂方法一样,根据传入值的类型返回相应基本包装类型的实例。例如:

      var obj = new Object("some text"); alert(obj instanceof String); //true

      把字符串传给 Object 构造函数,就会创建 String 的实例

///【Boolean 类型】//建议永远不要使用这种方法
  var b = new Boolean(false);
  alert(b && true)=>true; //因为b是个对象,转换为bool值就会是true
  //可以通过重写了的:`valueOf()` 方法返回基本类型的值(true、false),`toString()`方法返回字符串形式的'true false'
  ​
  ​
  ///【Number 类型】不建议使用
  // Number 是与数字值对应的引用类型var n = new Number(10);   
  // 重写后的 valueOf方法返回对象表示的基本类型的数值,toString() toLocaleString()方法,返回字符串形式的数值
  var n = 10.666; n.toFixed(2);=>10.67  
  ​
  ​
  ​
  ///【String 类型】
  String 类型是字符串的对象包装类型:var s = new String('haha');  
  length 属性返回字符串长度,双字节字符当做一个字符
    
  //【字符方法】
  charAt(n) //方法返回第n+1个字符([]访问也可以)
  charCodeAt(n) //方法返回第n+1个字符的ASCII码
//【字符串操作方法】
  str2.concat(str1,...) //将str1,...与str2连接在一起,返回一个新的字符串,不改变原字符串
              
  slice(start[,end]) substring() 
  substr(start[,length])//这三个都不会修改原字符串值,第二个参数无的话,截取到字符串末尾
  ​
  trim()//去掉首尾空格,返回字符串副本,不修改原
  ​
  String.fromCharCode() //这个方法的接收一或多个字符编码,然后将它们转换成一个字符串
  alert(String.fromCharCode(104,101,108,108,111))   //hello 
  ​
  str.toLowerCase();
  str.toUpperCase(); //分别转换成小写、大写  
//【字符串位置方法】
  indexOf()   lastIndexOf() 
  '12321'.indexOf('2') //1  
  '12321'.lastIndexOf('2')//3 
  ​
  str.endsWith(searchStr);//判断是否以某个字符串结尾
  str.startsWith(searchStr);//判断是否以某个字符串开始
//【字符串模式匹配】  见RegExp
//【字符串比较方法】
  //使用 > < = 也可以,'abc'>'abb' => true 
  var str = "bde";        
  alert(str.localeCompare("aaa"));       //1 
  alert(str.localeCompare("bde"));      //0 
  alert(str.localeCompare("qqq"));         //-1 

 


2.7 单体内置对象

由 ECMAScript 实现提供的、不依赖于宿主环境的对象,这些对象在 ECMAScript 程序执行之前就已经存在了。意思就是说,开发人员不必显式地实例化内置对象,因为它们已经实例化了。

  • Global 对象:

    • 不属于任何其他对象的属性和方法(可以直接调用的方法,例如下面的),最终都是它的属性和方法。事实上,没有全局变量或全局函数;所有在全局作用域中定义的属性和函数,都是 Global 对象的属性。诸如 isNaN()、isFinite()、parseInt()以及parseFloat(),实际上全都是 Global对象的方法。除此之外,Global 对象还包含其他一些方法。Global对象还有一些属性,例如:undefined NaN 和 各种构造函数 等

    • 【URL编码方法】:

      • encodeURI()不会对本身属于 URI 的特殊字符进行编码,例如冒号、正斜杠、问号和井字号;而 encodeURIComponent() (更常用,因为编码的通常是查询参数)则会对它发现的任何非标准字符进行编码。

      • encodeURI('http://baidu.com/+ +') //http://baidu.com/+%2B+

      • encodeURIComponet('http://baidu.com/+ +') //http%3A%2F%2Fbaidu.com%3A%2B%20%2B

      • 还有 decodeURI() 和 decodeURIComponent()方法

    • eval('code') 执行代码

  • Math 对象:

    • Math.max(1,2,3)//3 Math.min(1,2,3)//1

    • Math.max.apply(Math,[1,2,3,4])//求数组中最大值

    • Math.ceil() 向上舍入 Math.floor()向下舍入 Math.round() 四舍五入

    • random()方法:

      • 随机值=Math.floor(Math.random()*m +n) 生成 nm-1+n 的随机值

      • var n=Math.floor(Math.random()*10+1) //1-10随机数

      • var n=Math.floor(Math.random()*10+2) //2-11随机数

      •  

 

posted @ 2018-09-25 21:47  yuanyb  阅读(307)  评论(0编辑  收藏  举报