引用类型总结

引用类型的值(对象)是引用类型的一个实例

  • Object类型
  • Array类型
  • Date类型
  • RegExp类型
  • Function类型
  • 基本包装类型
  • 单体内置对象

Object

    // new操作符后跟Object构造函数
    var person = new Object();
    person.name='zs';
    person.age = 18;

    // 对象字面量表示法
    var person1 = {
        name: 'zs',
        age: 18
    };

Array

    // 使用Array构造函数
    var arr = new Array(5);
    console.log(arr) //数组里边有5项
    var arr1 = new Array('red','green','blue');
    console.log(arr1) // ["red", "green", "blue"]

    // 使用数组字面量表示法
    var arr2 = ['red','green','blue'];
    console.log(arr2) // ["red", "green", "blue"]
    
    // 使用length属性在数组末尾添加新项
    var arr3 = ['red','green','blue'];
    arr3[arr3.length]="black";
    console.log(arr3) //["red", "green", "blue", "black"]
    
     **检测数组**
    // instanceof
    console.log(arr3 instanceof Array)

    // Array.isArray()方法
    console.log(Array.isArray(arr2))
	
    **转换方法**
    // 所有对象的__proto__都有toLocalString()、toString()和valueOf()方法
    
    // 数组的toString()方法
    var arr4 = ['red','green','blue'];
    console.log(arr4.toString())
    // valueOf()方法返回本身
    console.log(arr4.valueOf()) //["red", "green", "blue"]
    
    // 栈方法push()和pop()方法
    // 队列方法 unshift()和shift()
    // sort()方法
    // sort()方法按升序排列数组项——最小的值在最前面,最大的值在最后   面,为了实现排序,sort()方法会调用每个数组项 
    的toString()转型方法,比较得到的字符串,以确定如何排序
   
    var values = [0,2,5,10,15];
    values.sort();
    console.log(values) //[0, 10, 15, 2, 5]

    // sort()方法可以接收一个比较函数作为参数,比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负 
    数,如果两个参数相等,则返回0,如果第一个参数应该位于第二个之后则返回一个正数

    function compare(value1, value2) {
        if (value1 < value2) {
            return -1;
        } else if (value1 > value2) {
            return 1;
        } else {
            return 0;
        }
    }
    // 例
    var val1 = [0,1,5,10,15];
    val1.sort(compare);
    console.log(val1)
    
    **操作方法**
    // concat()方法基于当前数组的所有项创建一个新数组。具体来说,这个方法会先创建当前数组的一个副本,然后将接收到
    的参数添加到这个副本的末尾,最后返回新构建的数组。如果没有给concat()方法传递参数,它只是复制当前数组并返回副
    本。
    var colors = ['red','green','blue'];
    var colors2 = colors.concat('yellow',['black','brown']);
    console.log(colors2)

    // slice [slaɪs] 从…切成
    // slice()方法基于当前数组中的一或多个项创建一个新数组。slice()方法可以接收一个或连个参数,即要返回项的起始和结束
    位置。在只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方
    法返回其实和结束位置之间的项--但不包括结束位置的项。注意,slice()方法不会影响原数组。
    var colors = ['red','green','blue','purple'];
    var colors3 = colors.slice(1);
    console.log(colors3) //["green", "blue"."purple"]
    var colors4 = colors.slice(1,3) //["green", "blue"]
    console.log(colors4)
    // 如果 slice()方法的参数中有一个负数,则用数组长度加上该数来确定相应的位
    // 置。例如,在一个包含 5 项的数组上调用 slice(-2,-1)与调用 slice(3,4)得到的
    // 结果相同。如果结束位置小于起始位置,则返回空数组。
    
    

    
    // [splaɪs] 剪接
    // splice()方法,常用
    - **删除**:可以删除任意数量的项,只需指定2个参数:要伤处的第一项的位置和要删除的项数。例如,splice(0,2)会删除数组中的前两项
    - **插入**:可以向指定位置插入任意数量的项,只需提供3个参数;起始位置、0(要删除的项数 )和要插入的项。例如,splice(2,0,‘red’.'green')会从当前数组的位置2开始插入字符串‘red’和‘green’。
    - **替换**:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定3个参数:起始位置、要删除的项数和要插入的任意数量的项。例如,splice(2,1,'red','green')删除当前数组位置2的项,然后插入‘red’,'green'
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"); // 从位置 1 开始插入两项
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,返回的数组中只包含一项
    // 位置方法
    // indexOf()和lastIndexOf()。这两个方法接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中,indexOf()方法从数组的开头(位置0)开始向后查找,lastIndexOf()方法从数组的末尾开始向前查找

    // 这两个方法都返回要查找的项在数组中的位置,在没有找到的情况下返回-1

    var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    alert(numbers.indexOf(4)); //3
    alert(numbers.indexOf(100)); //-1

迭代方法,可接收三个参数,数组项的值、该值在数组中的位置和数组对象本身

  • every() 全部为true,返回true
  • some() 任一项为true,返回true
  • map() 返回执行结果后的数组
  • filter() 返回为true项组成的数组
  • forEach() 遍历,没有返回值

Date类型

    // Date类型
    var now = new Date();
	//获取毫秒数
    var now = Date.now()

日期格式化方法

  • toDateString()——以特定于实现的格式显示星期几、月、日和年;
  • toTimeString()——以特定于实现的格式显示时、分、秒和时区;
  • toLocaleDateString()——以特定于地区的格式显示星期几、月、日和年;
  • toLocaleTimeString()——以特定于实现的格式显示时、分、秒;
  • toUTCString()——以特定于实现的格式完整的 UTC 日期。

日期/时间组件方法
在这里插入图片描述

RegExp 类型

Function 类型

函数实际上是对象。每个函数都是Function类型的实例,和其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。函数通常使用函数声明语法定义

function sum(num1,num2) {
	return num1 + num2;
}
//也可以使用函数表达式
var sum = function(num1,num2) {
	return num1 + num2
}
// 也可以使用Function构造函数,Function 构造函数可以接收任意数量的参数,
但最后一个参数始终都被看成是函数体,
var sum = new Function("num1", "num2", "return num1 + num2"); // 不推荐

函数表达式定义了变量 sum 并将其初始化为一个函数。function 关键字后面没有函数名就是匿名函数,因为在使用函数表达式定义函数时,没有必要使用函数名——通过变量 sum 即可以引用函数。另外,还要注意函数末尾有一个分号,就像声明其他变量时一样。

使用Function构造函数不推荐,因为这种语法会导致解析两次代码(第一次是解析常规 ECMAScript 代码,第二次是解析传入构造函数中的字符串),从而影响性能。

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

function sum(num1, num2){ 
 return num1 + num2; 
} 
alert(sum(10,10)); //20 
var anotherSum = sum; 
alert(anotherSum(10,10)); //20 
sum = null; 
alert(anotherSum(10,10)); //20

以上代码首先定义了一个名为 sum()的函数,用于求两个值的和。然后,又声明了变量 anotherSum,并将其设置为与 sum 相等(将 sum 的值赋给 anotherSum)。注意,使用不带圆括号的函数名是访问函
数指针,而非调用函数。此时,anotherSum 和 sum 就都指向了同一个函数,因此 anotherSum()也可以被调用并返回结果。即使将 sum 设置为 null,让它与函数“断绝关系”,但仍然可以正常调用
anotherSum()。

没有重载

将函数名想象为指针,有助于理解为什么ECMAScript没有重载的概念

function addSomeNumber(num) {
	return num + 100;
}

function addSomeNumber(num) {
	return num + 200;
}

var result = addSomeNumber(100); 
 console.log(result)//300

声明了两个同名函数,而结果则是后面的函数覆盖了前面的函数。以上代码实际
上与下面的代码没有什么区别。

var addSomeNumber = function (num) {
	return num + 100;
};

addSomeNumber = function (num) {
	return num +200;
};
var result = addSomeNumber(100);
console.log(result) //300

在创建第二个函数时,实际上覆盖了引用第一个函数的变量 addSomeNumber。

函数声明与函数表达式

alert(sum(10,10));
function sum(num1,num2) {
	return num1 + num2;
} //ok

alert(sum(10,10));
var sum = function(num1,num2) {
	return num1 + num2;
}//报错Uncaught TypeError:

作为值的函数

因为ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回

function callSomeFunction(someFunction,someArgument) {
		return someFunction(someArgument);
}

这个函数接收两个参数。第一个参数是一个函数,第二个参数是要传递给该函数的一个值,例:

function add10(num) {
		return num + 10;
}

var results1 = callSomeFunction(add10,10);
alert(result1); //20

function getGreeting(name) {
		return "Hello," + name;
}

var result2 = callSomeFunction(getGreeting, 'Nicholas');
alert(result2) //"Hello,Nicholas"

这里的callSomeFunction()函数是通用的,即无论第一个参数中传递进来的是什么函数,它都会返回执行第一个参数后的结果。还记得吧,要访问函数的指针而不执行函数的话,必须去掉函数名后面的那对圆括号。因此上边例子中传递给callSomeFunction()的是add10 和getGreeting,而不是执行它们之后的结果。

当然,可以从一个函数中返回另一个函数,这是一种极为有用的技术。例如,假如有一个对象数组(数组对象),我们想要根据某个对象属性对数组进行排序。而传递给数组sort()方法的比较函数要接收两个参数,即要比较的值。可是,我们需要一种方式来指明按照哪个属性来排序。要解决这个问题,可以定义一个函数,它接收一个属性名,然后根据这个属性名来创建一个比较函数,下面就是这个函数的定义。

    function createComparisonFunction(propertyName) {
        return function (object1, object2) {
            var value1 = object1[propertyName];
            var value2 = object2[propertyName];
            if (value1 < value2) {
                return -1;
            } else if (value1 > value2) {
                return 1;
            } else {
                return 0;
            }
        };
    }

这个函数定义看起来有点复杂,但实际上无非就是在一个函数中嵌套了另一个函数,而且内部函数前面加了一个 return 操作符。在内部函数接收到 propertyName 参数后,它会使用方括号表示法来取得给定属性的值。取得了想要的属性值之后,定义比较函数就非常简单了。上面这个函数可以像在下面例子中这样使用。

    var data = [{ name: "Zachary", age: 28 }, { name: "Nicholas", age: 29 }];
    data.sort(createComparisonFunction("name"));
    alert(data[0].name); //Nicholas 
    data.sort(createComparisonFunction("age"));
    alert(data[0].name); //Zachary

这里,我们创建了一个包含两个对象的数组 data。其中,每个对象都包含一个 name 属性和一个age 属性。在默认情况下,sort()方法会调用每个对象的 toString()方法以确定它们的次序;但得到的结果往往并不符合人类的思维习惯。因此,我们调用createComparisonFunction(“name”)方法创建了一个比较函数,以便按照每个对象的 name 属性值进行排序。而结果排在前面的第一项是 name为"Nicholas",age 是 29 的对象。然后,我们又使用了 createComparisonFunction(“age”)返回的比较函数,这次是按照对象的 age 属性排序。得到的结果是 name 值为"Zachary",age 值是 28 的对象排在了第一位。

函数内部属性

在函数内部,有两个特殊的对象arguments和this。其中,arguments是一个类数组对象,包含着传入函数中的所有参数。arguments的主要用途是保存函数参数,还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数,例如下面的阶乘函数。

    function factorial(num) {
        if (num <= 1) {
            return 1;
        } else {
            return num * factorial(num - 1)
        }
    }

定义阶乘函数一般都要用到递归算法;如上面的代码所示,在函数有名字,而且名字以后也不会变得情况下,这样定义没有问题。但问题是这个函数的执行与函数名factorical紧紧耦合在了一起。为了消除这种紧密耦合的现象,可以像下面这样使用arguments.callee。

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

函数的名字仅仅是一个包含指针的变量而已
ECMAScript 5 也规范化了另一个函数对象的属性:caller。这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为 null。例如:

    function outer() {
        inner();
    }
    function inner() {
        alert(inner.caller); //ƒ outer() {inner();}
    }
    outer();

以上代码会导致警告框中显示 outer()函数的源代码。因为 outer()调用了 inter(),所以inner.caller 就指向 outer()。为了实现更松散的耦合,也可以通过 arguments.callee.caller来访问相同的信息。

    function outer() {
        inner();
    }
    function inner() {
        alert(arguments.callee.caller);
    }
    outer();

函数属性和方法

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

    function sayName(name) {
        alert(name);
    }

    function sum(num1, num2) {
        return num1 + num2;
    }

    function sayHi() {
        alert('hi');
    }

    alert(sayName.length); //1
    alert(sum.length); //2
    alert(sayHi.length); //0

每个函数都包含两个非继承而来的方法:apply()和call()。这两个方法的用途都是在特定的作用域中调动函数,实际上等于设置函数体内this对象的值。首先,apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是Array的实例,也可以是arguments对象。例如:

    function sum(num1, num2) {
        return num1 + num2;
    }

    function callSum1(a, b) {
        return sum.apply(this, arguments);
    }

    function callSum2(c, d) {
        return sum.apply(this, [c, d])
    }

    alert(callSum1(10, 10));
    alert(callSum2(10, 20));

在上面这个例子中,callSum1()在执行sum()函数时传入了this作为this值(因为是在全局作用域中调用的恶,所以传入的就是window对象)和arguments对象。

call()方法与apply()方法的作用相同,区别在意接收参数的方式不同。call()方法第一个参数是this值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用call()方法时,传递给函数的参数必须逐个列举出来,例如:

    function sum(num1,num2) {
        return num1 + num2;
    }

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

    alert(callSum(10,10)); //20

事实上,传递参数并非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

sayColor.call(this)和 sayColor.call(window),则是两
显式地在全局作用域中调用函数的方式,结果当然都会显示"red"。当运行 sayColor.call(o)时,函数的执行环境就不一样了,因为此时函数体内的 this 对象指向了 o,于是结果显示的是"blue"。就是在o中调用sayColor函数或者是先将 sayColor()函数放到了对象 o 中,然后再通过 o 来调用它的

bind()方法这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。例如:

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

    var objectSayColor = sayColor.bind(o);
    objectSayColor(); //blue

sayColor()调用 bind()并传入对象 o,创建了 objectSayColor()函数。objectSayColor()函数的 this 值等于 o,因此即使是在全局作用域中调用这个函数,也会看到"blue"。

基本包装类型

单体内置对象

总结

对象在 JavaScript 中被称为引用类型的值,而且有一些内置的引用类型可以用来创建特定的对象,现简要总结如下:

  • 引用类型与传统面向对象程序设计中的类相似,但实现不同;
  • Object 是一个基础类型,其他所有类型都从 Object 继承了基本的行为;
  • Array 类型是一组值的有序列表,同时还提供了操作和转换这些值的功能;
  • Date 类型提供了有关日期和时间的信息,包括当前日期和时间以及相关的计算功能;
  • RegExp 类型是 ECMAScript 支持正则表达式的一个接口,提供了最基本的和一些高级的正则表达式功能。

函数实际上是 Function 类型的实例,因此函数也是对象;而这一点正是 JavaScript 最有特色的地方。由于函数是对象,所以函数也拥有方法,可以用来增强其为。
因为有了基本包装类型,所以 JavaScript 中的基本类型值可以被当作对象来访问。三种基本包装类型分别是:Boolean、Number 和 String。以下是它们共同的特征:

  • 每个包装类型都映射到同名的基本类型;
  • 在读取模式下访问基本类型值时,就会创建对应的基本包装类型的一个对象,从而方便了数据操作;
  • 操作基本类型值的语句一经执行完毕,就会立即销毁新创建的包装对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值