js之引用类型

  来自《javascript高级程序设计 第三版:作者Nicholas C. Zakas》的学习笔记(五)

  

  博文内容:

  • 使用对象(Object、Array、Date、RegExp)
  • 创建并操作数组
  • 基本的js类型
  • 基本类型和基本包装类型(Boolean、Number、String)

  引用类型描述的是一类对象所具有的属性和方法。

  

  Oject类型:

  创建Object实例有两种方式:

  • 使用new操作符
    var person = new Object();
    person.name = "hello";
    person.age = 29;
  • 对象字面量表示法
    var person = {
         name : "hello",
         age: 29
    };

    注:用对象字面量封装可选的参数值进行函数参数的传递会是一种很好的方式。

   Array类型:

   ECMAScript数组的大小是可以动态调整的,即可以随数据的添加自动增长以容纳新增数据。

   数组创建有两种方式:

  • 使用new:
    var colors = new Array();
    var colors = new Array(3);
    var colors = new Array("red","blue");
    var colors = Array(3);
    var colors = Array("gren");
  • 使用对象字面量:
    var colors = ["red","blue"];

    数组length的属性有一个特点——并非是只读,就是说你可以通过设置这个属性,从数组的末尾移除项或添加项:

    var colors = ["red","blue","green"];
    colors.length = 3;
    alert(colors[2]);      //undefined

    很明显,利用length属性可以很方便地在数组末尾添加新项:

    var colors = ["red","blue","green"];
    colors[colors.length] = "black";
    colors[colors.length] = "brown";

    检测数组:我们可以使用instanceof Array,但是问题在于,instanceof假定单一的全局执行环境。如果页面中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。为了解决这个问题,新增了Array.isArray()方法。

    所有对象都具有toLocalString()、toString()、valueOf()方法。

  • toString()方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串
  • valueOf()返回的还是数组
  • 使用join()可以创建不同分隔符分隔的字符串

   栈的方法:

  • push()逐个添加到数组末尾,并返回修改后数组的长度
  • pop()从数组末尾移除最后一项,减少数组的length长度,然后返回移除的项  

   队列方法:(对应的还有unshift()和pop())

  • shift()移除数组中第一个项并返回该项,数组长度减1
  • push同上 

     重排序方法:

   sort()方法按升序排列数组项。但是sort也会根据测试字符串结果改变原来的顺序:

  • var value = {0,1,5,10,15};
    value.sort();
    alert(value);   ///0,1,10,15,5

    给一个通用的方法:

    function compare(value1,value2) {
        if(value1 < value2) {
              return -1; 
        }  else if (value1 > value2) {
              return 1;  
      } else {
               return 0;
      }
    }
    
    
    
    //使用
    var value = {0,1,5,10,15};
    value.sort(compare);
    alert(value);              //0,1,5,10,15

    reverse()反转数组。

  

   操作方法:

  • concat():复制
    var color = ["red","green","blue"];
    var color2 = color.concat("yellow",["black","brown"]);
    alert(color);    //red,green,blue
    alert(colors);   //red,green,blue,yellow,black,brown
  • slice():截取功能。如果slice()中有负数,这负数加上数组长度进行转换
    var colors = ["red", "green", "blue", "yellow", "purple"];
    var colors2 = colors.slice(1);
    var colors3 = colors.slice(1,4);
            
    alert(colors2);   //green,blue,yellow,purple
    alert(colors3);   //green,blue,yellow
  • splice:

   删除:如splice(0,2)会删除数组中前两项

        插入:splice(2,0,"red","green")会从数组的位置2开始插入字符串“red"和"green"

        替换:splice(2,0,"red","green")会删除当前数组位置2的项,然后再从位置2开始插入字符串"red"和"green"

  

   位置方法:indexOf()---从数组开头向后--和lastIndecOf()---从数组末尾向前

   迭代方法:

  • every()
  • filter()
  • foreach()
  • map()
  • some()
    var numbers = [1,2,3,4,5,4,3,2,1];
    var everyResult = numbers.every(function(item, index,array{
      return (item > 2);
     });  
    alert(everyResult);       //false
            
    var someResult = numbers.some(function(item, index, array){
      return (item > 2);
     });
            
    alert(someResult);       //true
    
    var numbers = [1,2,3,4,5,4,3,2,1];
    var filterResult = numbers.filter(function(item, index, array){
      return (item > 2);
    });
    alert(filterResult);   //[3,4,5,4,3]
    
    var numbers = [1,2,3,4,5,4,3,2,1]; 
    var mapResult = numbers.map(function(item, index, array){
      return item * 2;
    });
    alert(mapResult);   //[2,4,6,8,10,8,6,4,2]

   Date类型:

   要为2004年5月25日创建一个日期对象,可以使用如下代码:

  • var someDate1 = new Date(Date.parse("May 25 ,2004"));    
    var someDate2 = new Date("May 25,2004");   //两者是等价的,后台调用Date.parse()函数,如果Date.parse()的方法不能表示日期,那么它会返回NaN
    //本地时间2000年1月1日午夜零时
    var kk = new Date(2000,0);
     //本地时间2005年5月5日下午5:55:55    不要怀疑这是错的,月份是从0开始的
    var tt = new Date(2005,4,5,17,55,55);    

    注:Date类型的valueOf()方法,根本不返回字符串,而是返回日期的毫秒表示。还有相关的日期的格式化方法。

   RegExp类型:正则表达式的知识,这里完全可以当做一门研究的对象。

  • 以对象字面量形式来定义正则表达式
  • 使用RegExp构造函数,它接受两个参数:一个是要匹配的字符串模式,另一个是可选的标志串。
    var pattern1 = /[bc]at/i;
    
    var pattern2 = new RegExp("[bc]at","i");

    正则表达式字面量始终会共享一个RegExp实例,而使用构造函数创建的每一个新RegExp实例都是一个新实例

  • var re = null,i;
    
    for( i = 0;i < 10;i++){
      re = /cat/g;
      re.test("catast");   //是实例创建的正则表达式,实例属性不会被重置,所以在循环中再次调用test()方法会失败。这是因为第一次调用test找到"cat",但是第二次调用是从索引3的字符开始的。
    }
    
    for(i = 0; i < 10;i++){
      re = new RegExp("cat","g");
      re.test("catastro);   //使用RegExp构造函数在每次循环中创建正则表达式。因为每次迭代都会创建一个新的RegExg实例,所以每次调用test()都会返回true
    }

    RegExp对象的主要方法是exec(),该方法主要是专门为捕获组而设计的。

  • var text = "mom and dad and baby";
    var pattern = /mom( and dad( and baby)?)?/gi;
    
    var matches = pattern.exec(text);
    alert(matches.index);   //0  匹配项在字符串中位置
    alert(matches.input);    // ”mom and dad and bady" input表示正则表达式的字符串
    alert(matches[0]);       // "mom and dad and bady"
    alert(match[1]);          // " and dad and bady"
    alert(match[2]);         // " and bady"

    对于exec()而言,设置全局标志的情况下,每次调用exec()则都会在字符串中继续查找新匹配项,而在不设置全局标志的情况下(即使是在模式中设置了全局标志也一样),在同一个字符串上多次调用exec()将始终返回一个匹配项的信息。

   test()方法。在模式与参数匹配的情况下返回true;否则,返回false。所以if语句中经常使用,进行逻辑判断。

   Function类型:函数实际上是对象。每个函数都是Function类型的实例,而且都与其它类型应用一样具有属性和方法。常用的函数定义:

  • function sum (num1,num2) {
      return num1 + num2;
    }
    
    var sum = function (num1,num2) {
      return num1 + num2;
    };            //别忘了分号

    函数名其实是一个指针。使用不带圆括号的函数名是访问函数指针,而非调用函数。

  • 函数名是指针有助于理解为什么没有重载
  • 解析器会率先读取函数声明,并使其在执行任何代码之前可用(可访问);至于函数表达式必须等到解析器执行到它所在的代码执行,才会真正被解释执行。
  • alert(sum(10,10));             //正确
    function sum(num1,num2) {
      return num1+num2;
    }
    
    alert(sub(20,10));      //错误
    var sub = function(num1,num2) {
      return num1-num2;
    }

    call和apply的区别。传给函数传递参数的方式不同。如果是arguments对象,或者是一个数组,则使用apply,否则可能call更合适。但是apply和call的强大之处在于扩充函数赖以运行的作用域。

  • window.color = "red";
    var o = {color: "blue"};
    
    function sayColor() {
      alert(this.color);
    }
    
    sayColor();    //red
    
    sayColor.call(this);   //red
    sayColor.call(window);   //red
    sayColor.call(o);    //blue

  三种基本包装类:Boolean、Number、string。

  在所有代码执行之前,作用域中就已经存在两个内置对象:Global和Math

原文地址:https://www.cnblogs.com/Iwillknow/p/3597702.html