js笔记-引用类型

引用类型

Object类型
  • 创建
    创建Object实例有两种方式
    • 使用new操作符后跟Object构造函数
    • 使用对象字面量表示法(不会调用构造函数)
    var person = new Object();
    //同 var person = {};
    
    var person = new Object();
    person.name = "Tom";
    person.age = 18;
    
    var person = {
        name:"Tom",
        // 同 "name":"Tom",
        age:18
    };
    
    :对象字面量也是向函数传递大量可选参数的首先方式,如
    function displayInfo(args) {
        var output = "";
    
        if (typeof args.name == "string"){
            output += "Name: " + args.name + "\n";
        }
    
        if (typeof args.age == "number"){
            output += "Age: " + args.age + "\n";
        }
        console.log(output);
    }
    
    displayInfo({
        name : "Tom",
        age : 18
    });
    
    displayInfo({
       name : "ming"
    });
    
  • 访问
    访问方式有两种
    • 点表示法
    • 方括号表示法
    console.log(person.name);
    console.log(person["name"]);
    
Array类型

ECMAScript数组同其他语言一样都是数据的有序列表,ECMAScript数组的每一项可以保存任何类型的数据,而且ECMAScript数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据

  • 创建
    创建数组有两种方式
    • 使用Array构造函数
    • 使用数组字面量表示法(不会调用构造函数)
    var colors = new Array("red","blue","green");
    var colors = ["red","blue","green"];
    
  • 检测数组
    为了避免多框架所带来的多个不同的执行环境所带来的差异,使用如下方法来检测数组
    if (Array.isArray(value)){
        //对数组执行某些操作
    }
    
  • 打印字符串
    var colors = ["red","blue","green"];        console.log(colors.toString());        console.log(colors);
    console.log(colors.valueOf());
    
  • 栈方法
    ECMAScript数组也提供了栈的方法
    • push()进栈
    • pop()出栈
    var colors = ["red","blue"];
    colors.push("green");
    var item = colors.pop();
    console.log(item);//green
    console.log(colors.length);//2
    
  • 队列方法
    ECMAScript数组也提供了队列的方法
    • push()进队
    • shift()出队
    var colors = ["red","blue"];
    colors.push("green");
    var item = colors.shift();
    console.log(item);//red
    console.log(colors.length);//2
    
  • 反向队列
    即在数组前端添加项,从数组末端移除项
    • unshift()在数组前端添加任意个项并返回长度
    • pop()
    var colors = ["red","blue"];
    colors.unshift("green");
    console.log(colors);//[ 'green', 'red', 'blue' ]
    var item = colors.pop();
    console.log(item);//blue
    console.log(colors.length);//2
    
  • 排序
    使用sort()reverse()进行排序,reverse()会反转数组的顺序,sort()会重小到大进行排序,同时还可以自定义排序方式
    var students = [{name:"stu1",age:12},{name:"stu2",age:13},{name:"stu3",age:15},{name:"stu4",age:10}];
    students.sort((value1, value2) => {
        if (value1.age < value2.age){
            return -1;
        } else if (value1.age > value2.age){
            return 1;
        }else {
            return 0;
        }
    });
    students.sort(function (value1,value2) {
        if (value1.age < value2.age){
            return -1;
        } else if (value1.age > value2.age){
            return 1;
        }else {
            return 0;
        }
    });
    console.log(students);
    //{ name: 'stu4', age: 10 },{ name: 'stu1', age: 12 },{ name: 'stu2', age: 13 },{ name: 'stu3', age: 15 }
    
  • 操作方法
    • concat()
      可以基于当前数组中的所有项创建一个新数组。
      具体来说,这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组
      var colors = ["red","green","blue"];
      var colors2 = colors.concat("yellowd",["black","brown"]);
      console.log(colors);
      //[ 'red', 'green', 'blue' ]
      console.log(colors2);
      //[ 'red', 'green', 'blue', 'yellowd', 'black', 'brown' ]
      
    • slice()
      能够基于当前数组的一个或多个创建一个数组
      在只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。所有有两个参数,该方法返回起始位置和结束位置之间的项-不包括结束位置的项
      var colors = ["red","green","blue","yellow","purple"];
      //[ 'green', 'blue', 'yellow', 'purple' ]
      console.log(colors.slice(1));
      // [ 'green', 'blue', 'yellow' ]
      console.log(colors.slice(1,4));
      
    • splice()
      删除方法
      可以删除任意数量的项,第一个参数为要删除的第一项的位置,第二个参数为要删除的项数
      var colors = ["red","green","blue","yellow","purple"];
      var removed = colors.splice(2,1);
      //[ 'blue' ]
      console.log(removed);
      //[ 'red', 'green', 'yellow', 'purple' ]
      console.log(colors);
      
      插入方法
      可以向指定位置插入任意数量的项,需要提供三个参数:起始位置、0、要插入的项数
      var colors = ["red","green","blue"];
      colors.splice(1,0,"yellow");//返回null
      //[ 'red', 'yellow', 'green', 'blue' ]
      console.log(colors);
      
      替换方法
      可以向指定位置插入任意数量的项,且同时删除任意数量的项。需要提供三个参数:起始位置、要删除的项数和要插入的任意数量的项
      var colors = ["red","green","blue"];
      var removed = colors.splice(1,1,"yellow","black");//返回null
      //[ 'green' ]
      console.log(removed);
      // [ 'red', 'yellow', 'black', 'blue' ]
      console.log(colors);
      
  • 位置方法
    使用indexOf()lastIndexOf()方法查找特定项在数组中的位置
    var colors = ["red","green","blue","yellow","purple"];
    console.log(colors.indexOf("blue"));//2
    console.log(colors.lastIndexOf("yellow"));//3
    
  • 迭代方法
    共有五种迭代方式
    每个方法需要接收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响this值。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。
    • every()
      对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true
    • filter()
      对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
    • forEach()
      对数组中的每一项运行给定函数,这个方法没有返回值
    • map()
      对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
    • some()
      对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true
    var numbers = [1,2,3,4,5,4,3,2,1];
    var result =  numbers.every((value, index, array) => {
        return (value > 2);
    });
    console.log(result);//false
    result = numbers.some((value, index, array) => {
        return (value > 2);//true
    });
    console.log(result);
    result = numbers.filter((value, index, array) => {
        return (value > 2);
    });
    //[ 3, 4, 5, 4, 3 ]
    console.log(result);
    result = numbers.map((value, index, array) => {
        return (value * 2);
    });
    // [ 2, 4, 6, 8, 10, 8, 6, 4, 2 ]
    console.log(result);
    
  • 归并方法
    reduce()reduceRight()这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。reduce()从第一项开始向后遍历,reduceRight()从最后一项开始向前遍历
    这两个方法都接收两个参数:1个在每一项上调用的函数和(可选的)作为归并基础的初始值。传入的函数接收4个参数:前一个值、当前值、项的索引和数组对象,这个函数返回的任何值都会作为第一个参数自动传给下一项。
    var numbers = [1,2,3,4,5];
    var sum = numbers.reduceRight((previousValue, currentValue, currentIndex, array) => {
        return previousValue+currentValue;
    });
    console.log(sum);//15
    
Function类型

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

//函数声明
function sum(num1,num2) {
    return num1+num2;
}
console.log(sum(1,2));//3
//函数表达式
var sum = function (num1,num2) {
    return num1+num2;
}
console.log(sum(1,2));//3
var sum = new Function("num1","num2","return num1+num2");
console.log(sum(1,2));//3

由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没有什么不同。换句话说,一个函数可能会有多个名字

function sum(num1,num2) {
    return num1+num2;
}
console.log(sum(1,2));
var sum1 = sum;
console.log(sum1(1,2));
sum = null;
console.log(sum1(1,2));
  • 函数声明与函数表达式
    实际上,解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。
    解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问)
    至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行

    console.log(sum(1,2));
    function sum(num1,num2) {
        return num1+num2;
    }
    

    以上代码可以完全运行

    console.log(sum(1,2));
    var sum = function (num1,num2) {
        return num1+num2;
    }
    

    以上代码不能运行

  • 函数的内部属性
    在函数内部,有两个特殊的对象:argumentsthis

    • arguments
      虽然arguments的主要用途是保存函数参数,但这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数
      function factorial(num) {
          if (num<=1){
              return 1;
          }
          return num * factorial(num-1);
      }
      
      console.log(factorial(5));//120
      
      //解耦
      function factorial(num) {
          if (num<=1){
              return 1;
          }
          return num * arguments.callee(num-1);
      }
      console.log(factorial(5));//120
      
    • this
      this引用的是函数执行的环境对象——或者也可以说是this值(当前网页的全局作用域中调用函数时,this对象引用的就是window)
    • caller
      这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,他的值为null
      function outer() {
          inner();
      }
      function inner() {
          console.log(arguments.callee.caller);
          //同 console.log(inner.caller);
      }
      outer();
      
  • 函数属性和方法
    函数也有属性和方法。每个函数都包含两个属性:lengthprototype

    • length
      length属性表示函数希望接收的命名参数的个数
      function f1() {
      }
      function f2(arg) {
      }
      function f3(arg1,arg2) {
      }
      console.log(f1.length);//0
      console.log(f2.length);//1
      console.log(f3.length);//2
      
    • prototype
      是保存它们所有实例方法的真正所在

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

    • apply()
      apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中第二个参数可以是Array的实例,也可以是arguments对象
      function sum(num1,num2) {
         return num1+num2;
      }
      function callSum1(num1,num2) {
         return sum.apply(this,arguments);
      }
      function callSum2(num1,num2) {
         return sum.apply(this,[num1,num2]);
      }
      
      console.log(callSum1(10,20));//30
      console.log(callSum2(10,20));//30
      
    • call()
      call()apply()基本相同,call()的第一个没有变化,变化的是其余参数都直接传递给函数
      function callSum(num1,num2) {
         return sum.call(this,num1,num2);
      }
      console.log(callSum(10,20));//30
      

    :call()apply()真正强大的地方是能够扩展函数赖以运行的作用域

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

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

    • bind()
      这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值
      color = "red";
      var o = {color : "blue"};
      function sayColor() {
          console.log(this.color);
      }
      var objectSayColor = sayColor.bind(o);
      objectSayColor();//blue
      
基本包装类型

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

var s1 = "some text";
var s2 = s1.substring(2);

当第二行代码访问s1时,访问过程处于一种读取模式,也就是要从内存中读取这个字符串的值,而在读取模式中访问字符串时,后台都会自动完成下列处理

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

相当于解释器完成了如下代码

var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;

:引用类型与基本包装类型的主要区别就是对象的生存期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁

  • Number
    Number类型也重写了valueOf()toLocaleString()toString()方法
    重写后的valueOf()方法返回对象表示的基本类型的数值,另外两个方法则返回字符串形式的数值
    • toString()
      可以传递一个表示基数的参数,告诉它返回进制数值的字符串形式
      var num = 10;
      console.log(num.toString());//10
      console.log(num.toString(2));//1010
      console.log(num.toString(8));//12
      console.log(num.toString(10));//10
      console.log(num.toString(16));//a
      
    • toFixed()
      该方法会按照指定的小数位返回数值的字符串表示
      var num = 10;
      console.log(num.toFixed(2));//10.00
      
    • toExponential()
      该方法返回以指数表示法表示的数值的字符串形式
      var num = 10;
      console.log(num.toExponential(1));//1.0e+1
      
    • toPrecision()
      该方法可能会返回固定大小(fixed)格式,也有可能返回指数(exponential)格式
      var num = 99;
      console.log(num.toPrecision(1));//1e+2
      console.log(num.toPrecision(2));//99
      console.log(num.toPrecision(3));//99.0
      
  • String类型
    String类型是字符串的对象包装类型,可以按照如下方式创建
    var str1 = "hello world";
    var str2 = new String("hello world");
    
    • length属性
      该属性用于表示字符串中包含多个字符串
    • 字符方法
      两个用于访问字符串中特定字符的方法是charAt()charCodeAt()。这两个方法都接收一个参数,基于0的字符位置
      var str = "hello world";
      console.log(str.charAt(1));//e
      console.log(str.charCodeAt(1));//101
      
    • 字符串操作方法
      • concat()
        用于将一个或多个字符串拼接起来,返回拼接得到的新字符串
        var str = "hello".concat(" world","!","!");
        console.log(str);//hello world!!
        
      还提供了三个基于子字符串创建新字符串的方法:slice()substr()substring()。这三个方法都会返回被操作字符串的一个子字符串
      • slice()
        第一个参数指定字符串开始的位置,第二个参数指定子字符串最后一个字符后面的位置
        var str = "hello world";
        console.log(str.slice(3));//lo world
        console.log(str.slice(3,7));//lo w
        
      • substring()
        第一个参数指定字符串开始的位置,第二个参数指定子字符串最后一个字符后面的位置
        var str = "hello world";
        console.log(str.substring(3));//lo world
        console.log(str.substring(3,7));//lo w
        
      • substr()
        第一个参数指定字符串开始的位置,第二个参数指定返回字符的个数
        var str = "hello world";
        console.log(str.substr(3));//lo world
        console.log(str.substr(3,7));//lo worl
        
    • 字符串位置方法
      indexOf()lastIndexOf()。这两个方法都是从一个字符串中搜素给定的子字符串,然后返回子字符串的位置(如果没有返回-1)
      • indexOf()
        从头开始搜索
        var str = "hello world";
        console.log(str.indexOf("o"));//4
        
      • lastIndexOf()
        从末尾开始搜索
        var str = "hello world";
        console.log(str.lastIndexOf("o"));//7
        
    • trim()方法
      该方法会创建一个字符串的副本,删除前置及后缀的所有空格,然后返回结果
      var str = "   hello world   ";
      console.log(str.trim());//hello world
      console.log(str);//"   hello world   "
      
    • 字符串大小写转换方法
      toUpperCase()toLowerCase()是两个经典的方法,而toLocaleUpperCase()toLocaleLowerCase()方法则是针对特定地区的实现,一些地区可能会不同
      var str = "Hello World";
      console.log(str.toUpperCase());//HELLO WORLD
      console.log(str.toLocaleUpperCase());//HELLO WORLD
      console.log(str.toLowerCase());//hello world
      console.log(str.toLocaleLowerCase());//hello world
      
    • 字符串正则表达式方法
      • match()
        var text = "cat, bat, sat, fat";
        var matchs = text.match(/.at/);
        console.log(matchs.index);//0
        
      • search()
        search()方法返回字符串第一个匹配项的索引,如果没有返回-1,该方法始终是从开头查找
        var text = "cat, bat, sat, fat";
        var pos = text.search(/.at/);
        console.log(pos);//0
        
    • localeCompare()
      该方法用于比较字符串
      var str = "yellow";
      console.log(str.localeCompare("yellow"));//0
      console.log(str.localeCompare("brick"));//1
      console.log(str.localeCompare("zoo"));//-1
      
单体内置对象
  • global对象
    不属于任何对象的属性和方法,最终都是它的属性和方法。事实上,也没有全局变量或者全局函数;所有在全局定义的属性和函数,都是global对象的属性
    1. URL编码
      encodeURI()encodeURIComponent()方法可以对URI进行编码,以便发送给浏览器。对整个URI使用encodeURI()。而对附加在现有URI后面的字符串使用encodeURIComponent()
      //http://www.baidu.com/index%20mm.html
      console.log(encodeURI("http://www.baidu.com/index mm.html"));
      //http%3A%2F%2Fwww.baidu.com%2Findex%20mm.html%2F%E9%92%A2%E9%93%81
      console.log(encodeURIComponent("http://www.baidu.com/index mm.html/钢铁"));
      
      与这两个方法对应的是decodeURI()decodeURIComponent()
      decodeURI()只能对使用encodeURI()替换的字符进行解码,同样decodeURIComponent()能够解码使用encodeURIComponent()编码的所有字符
      //http%3A%2F%2Fwww.baidu.com%2Findex mm.html%2F钢铁
      console.log(decodeURI("http%3A%2F%2Fwww.baidu.com%2Findex%20mm.html%2F%E9%92%A2%E9%93%81"));
      //http://www.baidu.com/index mm.html/钢铁
      console.log(decodeURIComponent("http%3A%2F%2Fwww.baidu.com%2Findex%20mm.html%2F%E9%92%A2%E9%93%81"));
      
    2. eval()方法
      该方法就像是一个完整的ECMAScript解析器,它只接受一个参数,即要执行的ECMAScript(或JS)字符串
      eval("console.log(\"hello world\");");
      console.log("hello world");
      
      通过eval()执行的代码被认为是包含该次调用的执行环境一部分,因此被执行的代码具有与该执行环境相同的作用域链。
      :严格模式下,在外部访问不到eval()中创建的任何变量或者函数,而且为eval赋值也会导致错误
  • Math对象
    Math对象提供的计算功能执行起来要快得多
    • min()max()
      min()max()用于确定一组数值里面的最大和最小值。这两个方法都可以接收任意多个数值的参数
      console.log(Math.max(3,52,32,16));//52
      console.log(Math.min(3,52,32,16));//3
      
    • 舍入方法
      将小数值舍入整数有几个方法Math.ceil()Math.floor()Math.round()
      • Math.ceil()
        执行向上舍入
      • Math.floor()
        执行向下舍入
      • Math.round()
        执行标准舍入,四舍五入
      console.log(Math.ceil(29.4));//30
      console.log(Math.floor(29.4));//29
      console.log(Math.round(29.4));//29
      
    • random()方法
      Math.random()方法返回大于等于0小于1的一个随机数
      可以套用下面的公式,获得随机值
      值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值)
      
      例如获得2到9则为:
      num = Math.floor(Math.random() * 9 + 2);
      

你可能感兴趣的:(js笔记-引用类型)