05 引用类型

js的引用类型大体上可以对应于其他oop语言的类,但是并不具备其他oop语言所支持的类和接口等基本结构。

5.1 Object类型

创建一个Object实例有两种方式。下面两种写法等价

var person = new Object();
var person = {};

在访问对象的属性时,也有两种等价写法。注意这里与python的不同,python用方括号是索引。

person.name;
person["name"];

5.2 Array类型

ECMA数组的每一项可以保存不同类型的数据,且数组的大小可以动态调整。

创建和使用

创建数组的两种方法

// 第一种方法,创建数组的new还可以省去不写
var colors = new Array();
var colors = new Array("red", "blue");
var colors = new Array(2); // 指定长度为2
// 第二种方法
var colors = [];
var colors = ["red", "blue"];

利用数组大小动态变化的特性,可以向下面这样添加元素

var colors = ["red"];
colors[colors.length] = "black";
alert(colors); // "red", "black"

另外,如果长度中没有元素,则是undefined

var colors = ["red"];
colors[99] = "black";
alert(colors.length); // 100

这时1到98都是undefined。

类型检测

if (myArray instanceof Array) {
// ...
}

如果一个网页有多个框架,也能存在多个全局环境,从而存在多个版本的Array构造函数。上面的方法可能失效。最好的办法是用Array.isArray()

if (Array.isArray(myArray)) {
// ...
}

转换方法

  • toString()

    把数组转换成字符串,用逗号分隔。toLocalString()也是

  • valueOf()

    返回数组本身。注意alert()接受的参数是字符换,会自动转换

  • join()

    返回字符串,把数组项用join的参数分隔。默认就是逗号

var nums = [1,2,3,4];
alert(typeof nums.valueOf()); // object
alert(typeof nums.toString()); // string
alert(typeof nums.toLocaleString()); // string
alert(nums.join("|")); // 1|2|3|4

栈和队列方法

  • push() 在后面添加一个或多个元素

  • pop() 弹出最后一个元素

  • shift() 弹出第一个元素

  • unshift() 在前面添加一个或多个元素

push和unshift传多个参数,就会添加多个元素

var a = [1,2,3];
a.push(7,8); // a = [1, 2, 3, 7, 8]
var item = a.pop(); // a = [1, 2, 3, 7], item = 8
var item2 = a.shift(); // a = [2, 3, 7], item2 = 1,
a.unshift(-1, 0); // a = [-1, 0, 2, 3, 7]

排序和反转方法

reverse()直接反转。sort()默认是根据元素的字符串(toString())的值来比较的,即是元素是数值类型也是

var b = [1,5,10,15];
b.sort(); //[1, 10, 15, 5]

如果要自定义排序方法,可以传入一个compare函数参数。compare函数接受两个参数。如果第一个应该在第二个元素前面,则返回负数。第一个元素应该在第二个元素后面,则返回正数。两个元素相等,则返回0。

// 简单的Numbe类型的比较函数可以写成这样
function compare (v1, v2) {
return v1 - v2;
}
var c = [1, 5, 50, 100, 10, 30];
c.sort(compare); // [1, 5, 10, 30, 50, 100]

操作方法

concat拼接数组,不改变原数组

var colors = ["red", "green", "blue"]
var colors2 = colors.concat("yello", [1,2])
// colors2 = ["red", "green", "blue", "yello", 1, 2]

slice切片,不改变原数组。两个参数都是索引,左闭右开。

var nums = [1,2,3,4,5];
var nums2 = nums.slice(1); // [2, 3, 4, 5]
var nums3 = nums.slice(1,3); // [2, 3]

splice删除元素。第一个参数是要删除的元素的索引,第二个参数是要删除的元素的数目,后面的元素是要插入的元素。splice的返回值是被删掉的元素的数组

删除索引0处的一个元素

var persons = ['leo', 'sirius', 'mike', 'nike']
var removed = persons.splice(0, 1);
// persons = ["leo"]
// removed = ["sirius", "mike", "nike"]

删除索引0处的0个元素,并插入两个元素

var persons = ['leo', 'sirius', 'mike', 'nike']
var removed = persons.splice(0, 0, 'tom', 'cat');
// persons = ["tom", "cat", "leo", "sirius", "mike", "nike"]
// removed = []

位置方法

  • indexOf()

  • lastIndexOf()

两个方法都接受两个参数:要查找的元素,起始索引。indexOf是从前往后找,lastIndexOf是从后往前找。

迭代方法

  • every() 对数组每一项运行给定函数,每一项都返回true,则返回true

  • some() 对数组每一项运行给定函数,任意一项返回true,则返回true

  • filter() 对数组每一项运行给定函数,返回改函数会返回true的项组成的数组

  • map() 对数组每一项运行给定函数,返回函数的返回组成的数组

  • forEach() 对数组每一项运行给定函数,没有返回值

归并方法

  • reduce()

  • reduceRight()

两个函数除了方向不同,其他都一样。参数有两个,第一个是作用函数,第二个是初始值。

作用函数又有四个参数,分别是:前一值,当前值,项的索引和数组对象

var num = [1,2,3,4,5];
var res = num.reduce(function(prev, cur, idx, array) {
return prev + cur;
}, 100);
// res = 115

5.3 Date类型

Date.parse()和Date.UTC()都接受一个表示时间的字符串,返回时间戳的毫秒数。

获取当前时间的两种方法

+new Date();
// 1576909191177
Date.now();
// 1576909216932

还有一些返回格式化时间字符串的方法

  • toDateString()

  • toTimeString()

  • toLocaleDateString()

  • toLocaleTimeString()

  • toUTCString()

5.4 正则表达式(待记)

5.5 Function类型

概念

js中函数也是对象,每个函数都是Function类型的实例,且与其他引用类型一样都有属性与方法。函数名实际上是指向函数对象的指针。下面三种写法是等价的。

function sum1 (v1, v2) {
return v1 + v2;
}
var sum2 = function (v1, v2) {
return v1 + v2;
}
var sum3 = new Function("v1", "v2", "return v1 + v2");
sum1(2, 3); // 5
sum2(2, 3); // 5
sum3(2, 3); // 5

这也解释了js函数为什么没有重载,因为函数名作为指针只能指向一个特定的函数。