Javascript高级程序设计 读书笔记

Javascript 引用类型(Object Array)

2018-02-04  本文已影响24人  Sue1024

ECMAScript中,引用类型是一种数据结构,用来描述对象的属性和方法。对象则是某个引用类型的实例,可用new操作符跟一个构造函数创建新对象。

Object 类型

创建Object实例:

构造函数
var cat = new Object();
cat.name = "cat";
var cat = Object();
cat.name = "cat";
对象字面量
var cat = {
  name: "cat",
  "age": 18
}

使用这种方式创建不会调用Object()构造函数
属性名之间用逗号相隔,最后一个属性后面不应该有逗号,属性名可以是字符串。
书中还提到了当需要向一个函数中传入大量可选参数时(可选参数可以是函数更加灵活),使用对象字面量是一个很好的选择,因为它不仅代码简单,也可以显示封装性,例如:

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";
  }
  alert(output);
}
displayInfo({
  name: "Nicholas",
  age: 29
});
displayInfo({
  name: "Greg"
});

访问对象属性

使用两种方式可以访问对象属性:

cat.name;
cat["name"];

当对象名是变量,或包含会引起语法错误的字符(比如空格),或者包含非字母非数值时,只能使用方括号(书中还提到了关键字和保留字,笔者记得它们只是不能用作标识符,而且试了好多,发现都可以作为属性名),比如:

var key = "name";
cat[key]; // cat
cat["&key"] = "key"];
cat["&key"]; / /key
cat["first name"] = "cat";
cat["first name"]; // cat

Array 类型

ECMAScript数组每一项可以保存任何类型的数据,大小可以动态调整,之后会举相应的例子。

创建数组

构造函数
var array1 = new Array();
var array2 = new Array(10);
var array3 = Array();
var array4 = new Array("sue", 18, {"birth": "1993-10-24"});

由上述例子可以看出,使用构造函数创建数组时,可以不传参,即创建一个空数组(长度为0),可以传入不小于0的整数作为长度,可以不使用new操作符,每一项都可以使用任何数据类型。

数组字面量
var array1 = []; //empty array, length 0
var array2 = ["first", "second", "third"];

使用这种方式创建不会调用Array()构造函数
由于IE8及之前版本与其他浏览器表现不一致,不建议使用以下方式创建:

var array3 = [1, 2,];//IE 8 length is 3; other, length is 2
var array4 = [,,,,]; //IE 8 length is 5; other, length is 4

访问数组

var array = [1, 2, 3];
array[0]; //1
array[2] = 4; // 4
array[2]; // 4
array[5] = 10; // 10
array[5]; //10
array.length; //6
array.length = 10; // 10
array[9]; // undefined
array.length = 1;
array[1]; // undefined
array[12]; //undefined

由上述例子可以看出,数组的索引是从0开始的,最后一个值的索引为length-1,如果给索引超出length-1的数组项赋值,那么数组长度会延长至index+1,如果直接更改数组长度,可以在末尾移除项或添加项,可以通过给指定项赋值来改变指定项的值,如果读取索引超出length-1的数组项,将返回undefined,可以使用以下方式在数组的末尾添加一项:

var array = [1,2,3];
array[array.length] = 4;
array[3]; //4

数组中最多可以包含4 294 967 295项。

检测数组

instanceof

如果要判断的数组与Array构造函数拥有同一个全局作用域,我们可以使用

var array = [1, 2, 3];
array instanceof Array; // true

我们知道,instanceof其实是做了如下判断:

array.constructor==Array

举个例子:
index.html(部分)

<iframe name="childframe" src="Child.html"></iframe>
<script type="text/javascript">
   window.onload = function () {
    array= [1, 2, 3];
    var result = window.frames[0].search(array);
    console.log(window.frames[0].window === window); //false
};
</script>

child.html(部分)

<script type="text/javascript">
  search: function (array) {
    var result = array instanceof Array;
    console.log(result, array.constructor === Array); // false, false
  }  
</script>

可以看出index.html中的window与Child.html中的window并不相同,那么array也不是Child.html中Array的实例。

Array.isArray()

在IE9+、Firefox 4+、Safari 5+、Opera 10.5+和Chrome,这些浏览器中,为了解决上述问题,新增了Array.isArray()方法

var array = [1, 2, 3];
Array.isArray(array); // true
prototype.call()
Object.prototype.toString.call(array)=='[object Array]'

转换方法

toString

调用每一项的toString()方法,然后用逗号连接起来。

array.toString(); //"1,2,3"
valueOf

不进行转换,返回原数组

toLocaleString

调用每一项的toLocaleString()方法,然后用逗号连接起来。

join

调用每一项的toString()方法,然后使用给定字符连接起来。

array.join(); //"1,2,3"
array.join("||"); //"1||2||3"

undefinednull项在toString() toLocaleString() valueOf时,变成空值""

栈方法

提供了模拟栈数据结构先入后出规则的两个方法。

pop

移除数组的最后一项,使数组的长度减1,并返回被移除的项。

push

向数组尾部添加任意数量的项,并返回数组长度。

var array = [1, 2, 3];
array.push(4, 5); //5
array.pop(); //5

队列方法

提供了模拟队列数据结构先入先出访问规则的两个方法。

正向队列 shift() + push()

shift()可以移除数组的第一项,并返回该项。

反向队列 unshift() + pop()

unshift()可以在数组前端插入任意个数的项并返回新数组的长度。

重排序

reserve()

将数组反转,比如:

var array = [1, 2, 3];
array.reverse(); // [3, 2, 1]
sort()

由于reverse只能单一地将数组反转,不够灵活,因此又有了sort()。默认情况下,sort()按从小到大的顺序给数组排序,排序时,首先对每一项执行toString(),然后比较字符串的大小,即sort()无论何时都是在比较字符串大小,即使数组项里全是数值。

var array = [1, 2, 10, 3, 23];
array.sort(); // [1, 10, 2, 23, 3]

sort()可以接收比较函数为参数来指定比较逻辑,比较函数接收两个参数,当第一个应该在第二个之后时,返回大于0的数值,两者相等时,返回0,第二个应该在第二个之前时,返回小于0的数值,比如我们声明一个可以按数值由大到小排序的比较函数:

function compare(num1, num2) {
  if(num1 > num2) {
    return 1;
  } else if(num1 === num2) {
    return 0;
  } else {
    return -1;
  }
}
array.sort(compare); // [1, 2, 3, 10, 23]

当数据项全部是数值或者对每一项调用其valueOf()方法都返回一个数值,那么我们可以简化以上逻辑:

function compare(num1, num2) {
  return num1 - num2;
}

操作方法

concat
var array = [1, 2, 3];
array.concat(); // [1, 2, 3]
array.concat([2,3,4]); // [1, 2, 3, 2, 3, 4];
array.concat(5); // [1, 2, 3, 5]
array.concat(4, 5, [6, 7, 8]); //[1,2 ,3, 4, 5, 6, 7, 8]);
array; //[1, 2, 3]
slice

slice()基于给定数组的片段返回新数组,不会影响原来的数组。

var array = [1, 2, 3];
array.slice(2); // [3]
array.slice(3); // []
array.slice(0, 2); // [1, 2]
array.slice(3, 2); //[]
array.slice(-3, -2); //相当于array.slice(0, 1) 返回[1]
array; //[1, 2, 3]
splice
  1. 删除项。指定两个参数,即删除的起始位置(如果项数大于0,起始位置是被第一个删除的项)和删除的项数,返回被删除的项组成的数组。
  2. 插入项。指定多个参数,第一个是插入的开始位置(第一个插入项将获得的索引位置)、0(删除0项)、插入的项(可多个)。
  3. 替代项。指定多个参数,第二个是替代的开始位置、删除的项数、插入的项(可多个,插入项的数量不用跟删除项数保持一致)。
    以上方法返回的都是被删除的项组成的数组,举一些例子:
var array = [1, 2, 3, 4];
array.splice(0, 1); // [1]
array; //[2, 3, 4]
array.splice(1, 0, 4, 5); //[]
array; //[2, 4, 5, 3, 4]
array.splice(2, 2, 7, 8, 9); //[5, 3]
array; //[2, 4, 7, 8, 9]

位置方法

indexOf

从数组开头向后查找

lastIndexOf

从数组末尾向前查找
二者都接收2个参数,查找的项,和查找起点(可选),如果找不到,返回-1,只要找到与查找项全等的项,则返回其索引。

var array = [1, 2, 3, 4, 3];
array.indexOf(3); //2
array.lastIndexOf(3); //4
array.indexOf(3, 3); //4
array.indexOf(3, 2); //2
array.lastIndexOf(3, 1); // -1
array.lastIndexOf(3, 3); //2 

支持这两个方法的浏览器包括:IE9+、Firefox 2+、Safari 3+、Opera 9.5+和Chrome。

迭代方法

以下每个方法接收两个参数,第一个是对每一项执行的函数,第二个是该函数的this(作用域),该函数接收三个参数,第一个是当前项,第二个是当前项的索引,第三个是数组。

every()

对每一项运行给定函数,如果都返回true,则返回true

some()

对每一项运行给定函数,如果存在返回true的项,则返回true

filter()

对每一项运行给定函数,返回该函数会返回true 的项组成的数组。

forEach()

对每一项运行给定函数,无返回值。

map()

对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
支持这些迭代方法的浏览器有IE9+、Firefox 2+、Safari 3+、Opera 9.5+和Chrome。
举一些例子:

function function1(value, index, array) {
  return value > 2;
}
function function2(value, index, array) {
  return value * 2;
}
function function3(value, index, array) {
  array[index] = value * 2;
}
var array = [1, 2, 3, 4, 5];
array.every(function1, this); // false
array; // [1, 2, 3, 4, 5]
array.some(function1, this); // true
array; // [1, 2, 3, 4, 5]
array.filter(function1, this); // [3, 4, 5]
array; // [1, 2, 3, 4, 5]
array.forEach(function2, this); //undefined
array; //[1, 2, 3, 4, 5]
array.map(function2, this); //[2, 4, 6, 8, 10]
array; //[1, 2, 3, 4, 5]
array.forEach(function3, this); // undefined
array; [2, 4, 6, 8, 10]

这五个方法传入的函数都可以获取整个数组和相应的索引,都是可以更改数组的。

归并方法

以下两个方法都会遍历数组所有项,得出最后一个返回值

function sum(preV, curV, index, array) {
  return preV + curV;
}
var array = [1, 2, 3, 4];
array.reduce(sum); //10

支持这两个归并函数的浏览器有IE9+、Firefox 3+、Safari 4+、Opera 10.5 和Chrome。

上一篇下一篇

猜你喜欢

热点阅读