林大妈的JavaScript基础知识(三):JavaScript编程(4)数组
数组,是一段线性分配的,具有非常高性能的数据结构。简单地说,数组以连续的空间存储,通过整数地计算偏移量访问其中的元素,将读取修改的时间复杂度降低至O(1),我们称之为猝发式存取。是不是非常期待?没错,像这样的好东西,JavaScript没有。
1. Array简介
但作为替代,JavaScript设计者想出了一个更方便但性能相对较低的方案,打印观察Array.prototype,会发现,设计者为我们提供的是一个array-like(类数组)的对象。在检索和更新属性上,Array就和普通的对象一模一样(也就是说要遍历所有属性),只是多了一个不可枚举的属性length来记录这个对象所表示的数组的长度。尽管Array对象的性能明显比数组要差,但是搭配上弱类型的JavaScript语言(当然,JavaScript中不存在传统的数组一部分原因也是因为这一点),它在使用上非常的方便。更贴心的是,设计者还为我们提供了许多内置的方法,可以快速解决其他语言费很大劲才能解决的问题。
2. 声明
数组的声明跟对象的声明很类似。我们可以用两种方法初始化一个数组:① 直接用 var array = []; 我们称之为数组字面量的方式来初始化;② 使用构造函数 var array = new Array(); 如果参数填入一个数字,则返回一个长度为这个数字的空数组,如果参数填入多个值,则返回一个按顺序保存了这些值的Array对象。
3. 修改
上面我们已经搞清楚了Array对象总体的结构,这样修改一个数组就可以转化为我们以前学到的修改一个对象属性的知识了。由于JavaScript的灵活性,除非你定义一个大到Infinity的数组,其他情况下均不会因为越界报错(Runtime Error也许是很多人的噩梦,反正是我的噩梦)。因此,假如我们现在有这样一个数组:
var myArray = [0, '1', true]
利用JavaScript会帮我们维护length属性这一特点(但为了编写易维护的代码,不推荐这些简单粗暴的做法),我们也可以做一些在别的语言中看起来不可思议的操作,例如:① myArray[8] = undefined 会直接把Array的长度扩展到8;② myArray.length = 0; 能直接清空数组。除了可以这样清空数组,还可以通过Array.prototype.splice方法完成清空,因此我们把目光放到数组的原型方法上来。
4. 原型方法(均以上面的myArray举例)
① indexOf
indexOf方法同时存在于Array.prototype和String.prototype中,可以用它来检测数组或字符串中是否存在对应的元素,如果存在,则返回它的下标,如果不存在,则返回-1:
console.log(myArray.indexOf(0)); //0
console.log(myArray.indexOf(1)); //-1
由于在数组中,1和'1'是两个不同的值,因此第二句返回结果-1。
② push、pop、unshift、shift
push朝数组末尾推入若干新元素,返回加入后数组的length。
pop弹出数组末尾的一个元素,返回被弹出的元素。
unshift朝数组开头推入若干新元素,返回加入后数组的length。
shift弹出数组开头的一个元素,返回被弹出的元素。
console.log(myArray.push('A', 'B')); //
console.log(myArray.pop()); //'B'
console.log(myArray.unshift('A', 'B')); //
console.log(myArray.shift()); //'A'
③ sort(这时候我们重新定义一下 myArray = [5, 2, 0, 10, 17, 25]; )
sort方法在原数组上动刀,这里我们期望将数组中的数按从小到大的顺序排列,sort函数可以帮我们做到这一点,但需要注意的是,sort函数默认把这些元素转化为字符串进行比较。因此这个数组排序以后的结果是这样的:
console.log(myArray.sort()); // [0, 10, 17, 2, 25, 5]
因此通常需要填入一个比较判断函数作为参数,下面传入一个箭头函数,按照我所定义的这个函数进行判断大小再排序:
console.log(myArray.sort((x, y)=>{return x - y;})); // [0, 2, 5, 10, 17, 25]
④ reverse和join
reverse方法在原数组上动刀,返回跟原来相反的数组;join方法相当于String.prototype.split方法的反函数,填入一个字符串参数,以这个参数将每个元素分隔开,合并成一个字符串并返回。这两个方法可以搭配使用来处理反向输出字符串的问题:
var str = "Hello world!"; console.log(str.split('').reverse().join(''));
//"!dlrow olleH"
console.log(str.split(' ').reverse().join(' '));
//"world! Hello"
这里由于每个函数返回值都是与其相对应的数组或字符串,可以直接在这个返回值上进行操作,因此我们还用到了链式调用的技巧。
⑤ slice和splice
这两个方法的区别和使用非常重要,又由于它们名字之间只差一个字母,缺少练习时我们很容易会将其混淆。
slice方法可以类比String.prototype.substring。指定一个参数n,它将返回一个新数组,这个数组中含有原数组下标从n到末尾的所有元素。指定两个参数a和b时,它将返回一个新数组,这个数组含有原数组下标从a到b的所有元素(不得不说,用中文来描述真的非常蹩脚):
var myArray = [1, 2, 3, 4, 5, 6, 7, 8]; var aNewArray = myArray.slice(3);
var aNewNewArray = myArray.slice(3, 5); console.log(aNewArray);
//[4, 5, 6, 7, 8]
console.log(aNewNewArray);
//[4, 5]
当然了,这两种操作都是含头不含尾的。如果不指定参数地使用slice,它将返回一个跟原数组一模一样的数组,利用这一点,我们可以用一句代码复制一个数组。
splice是修改一个数组的“万能方法”,要注意它将直接在原数组上动刀,返回值是被删除的元素组成的数组:
var myArray = ['CapAmerica', 'IronMan', 'Hulk', 'Thor'];
// param: 从第4个元素开始操作,删除0个元素,加入新元素'BlackWidow'
myArray.splice(3, 0, 'BlackWidow');
// 由于删除0个元素,它将返回一个空数组 console.log(myArray);
// ['CapAmerica', 'IronMan', 'Hulk', 'Thor', 'BlackWidow'] // param:从第二个元素开始,删除三个元素,加入这些新元素
myArray.splice(2, 3, 'ScarletWitch', 'Vision', 'CapMarvel');
//返回['Hulk', 'Thor', 'BlackWidow'] console.log(myArray);
//['CapAmerica', 'IronMan', 'ScarletWitch', 'Vision', 'CapMarvel']
⑥ concat
concat方法不会动原数组,而是返回新数组。它返回一个将原数组和所有你填入的参数都合并在一起的新数组,因此我们想到了可以用它搭配splice方法来实现一个JavaScript版本的快速排序:
function quickSort(arr) {
if(arr.length <=1) return arr;
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
var left = [], right = [];
for(var i = 0; i < arr.length; i++) {
if(arr[i] < pivot) left.push(arr[i]);
else right.push(arr[i]);
};
return quickSort(left).concat(pivot, quickSort(right));
}
拓展:1. ES6 Map
我们都知道,在Array对象中,每个元素就是一个对象,通过键值对存储数据。但其中的键只能是字符串类型。我们渴求能用类似Number或其他基本数据类型作为键,这样的表达会更清晰。因此ES6为我们带来了Map数据结构,它还具有极高的查询效率。且看它的使用语法:
var myMap = new Map([['name', 'MotherLyn'],['score', 51]]);
观察发现,我们完全可以把它当做是一个两列n行的,对数据类型有规范的二维Array。它还有许多内置方法:set、get、has、delete。
要注意的是,Map中所有的键类似数据库中的primary key,也就是他们都是不可重复的,填入相同的键不同的值只会把以往的数据冲掉。
2. ES6 Set
Set与Map类似但又十分不同。说它相同是因为Set对数据类型也是存在划分的(3和‘3’是不同的两个键);说它不同是因为Set只一个值而不是一个键值对。因此使用Set时只需要传入一个一维的Array即可:
var mySet = new Set(['MotherLyn', 51]);
通过使用内置方法add、delete和has可以进行增删查改操作。
3. ES6 for of遍历方法
前面我们提到,使用for in遍历会将可枚举的原型属性一块遍历到。为了解决这个问题,ES6提出了for of遍历。它在使用上和for in是相同的,只是把in改成of而已。
总结:① JavaScript中的Array对象只是一个内建的对象,并不是传统意义上的数组,它在内存中不是连续的空间,因此只能遍历元素来进行查找修改,性能较差但灵活性非常好。
② Array.prototype中有非常多的方法,常用的有以上这些:indexOf、push、pop、unshift、shift、sort、reverse、join、slice、splice和concat。还有很多其他的方法,要善用这些方法只能靠多练习,慢慢积累。
③ ES6中的Map和Set都是类似Array的数据结构,它们都严格管理数据类型,但区别是Map以键值对的方式存储,Set只能存储值而不能存储键。
林大妈的JavaScript基础知识(三):JavaScript编程(4)数组的更多相关文章
- JavaScript基础知识整理(1)数组
第一:创建. 1,var arr= new Array(); //数组为空.长度为0. arr[0]="apple"; arr[1]="orange"; arr ...
- 【javascript基础知识】javascript中的转义序列和特殊数值常量
javascript的转义序列 \0 NUL字符(\u0000) \b 退格符(\u0008) \t 水平制表符(\u0009) \n 换行符(\u000A) \v 垂直制表符(\u000B) \f ...
- Javascript 基础知识学习--javascript中的参数传递都是按值传递的
ECMAScript中所有函数的参数传递都是按值传递的,无论参数是值类型还是引用类型的.过去我跟大多数人一样觉得跟传值类型相关. 自己写了一个测试的例子,确实如此 function add(a) { ...
- 学习javascript基础知识系列第二节 - this用法
通过一段代码学习javascript基础知识系列 第二节 - this用法 this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象.但是在javascr ...
- 学习javascript基础知识系列第三节 - ()()用法
总目录:通过一段代码学习javascript基础知识系列 注意: 为了便于执行和演示,建议使用chrome浏览器,按F12,然后按Esc(或手动选择)打开console,在console进行执行和演示 ...
- Javascript基础知识总结一
Javascript基础知识总结一 <!DOCTYPE html> <html> <head lang="en"> <meta chars ...
- JavaScript基础知识(一)
一.JavaScript基础 1.JavaScript用法: HTML 中的脚本必须位于 <script> 与 </script> 标签之间. 脚本可被放置在 HTML 页面的 ...
- JavaScript基础(三)
十三.JS中的面向对象 创建对象的几种常用方式 1.使用Object或对象字面量创建对象 2.工厂模式创建对象 3.构造函数模式创建对象 4.原型模式创建对象 1.使用Object或对象字面量创建对象 ...
- javascript 基础知识学习1
JavaScript 是脚本语言.浏览器会在读取代码时,逐行地执行脚本代码.而对于传统编程来说,会在执行前对所有代码进行编译.基础知识:1).JavaScript 对大小写敏感.JavaScript ...
- JavaScript 基础知识 - BOM篇
前言 本篇文章是JavaScript基础知识的BOM篇,如果前面的<JavaScript基础知识-DOM篇>看完了,现在就可以学习BOM了. 注意: 所有的案例都在这里链接: 提取密码密码 ...
随机推荐
- Element-ui安装之MessageBox详解
1.首先根据官方文档进行Element-ui的安装,这个过程很简单(通过webpack-simple) 1) vue init webpack-simple element-ui 2) cd elem ...
- Python生成word
Python生成word 使用python-docx-template库, 将html转为word. python-docx-template可以使用类似jinja2的模板语法. 依赖docx库, 安 ...
- 【朝花夕拾】Android自定义View篇之(九)多点触控(下)实践出真知
前言 在上一篇文章中,已经总结了MotionEvent以及多点触控相关的基础理论知识和常用的函数.本篇将通过实现单指拖动图片,多指拖动图片的实际案例来进行练习并实现一些效果,来理解前面的理论知识.要理 ...
- 阿里云服务器纯净版centos7.4 LNMP安装
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable ...
- Disruptor 详解 一
这篇博客将主要通过几个示例,简单讲述 Disruptor 的使用方法: 一.disruptor 简介 Disruptor 是英国外汇交易公司 LMAX 开发的一个无锁高性能的线程间消息传递的框架.目前 ...
- easyui 使用jquery动态添加组件样式问题
可以使用$.parser.parse();这个方法进行处理: 例如: $.parser.parse(); 表示对整个页面重新渲染,渲染完就可以看到easyui原来的样式了: var targe ...
- 基于Django框架 CRM的增删改查
思路: 创建表------从数据库读出数据展示出来------配置路由-----写视图函数------写对应页面 练习点: 数据库建表 ORM 数据库数据读取 数据 ModelForm (form组 ...
- 解决thinkphp在开发环境下文件模块找不到的问题
win10系统下,phpstudy开发环境下小问题描述: 找不到public公共模块. Not Found The requested URL /public/admin/login.html was ...
- 嵊州D1T3 睡美人航班
嵊州D1T3 睡美人航班 不知不觉中,我对她的爱意已经达到了 n. 是这样子的,第 1 分钟,我对她的爱意值是 (1, 1). 假如当第 x 分钟时我对她的爱意值是 (a, b),那么第 x + 1 ...
- c++学习书籍推荐《C++ Templates》下载
详细讲解C++模板语言的概念. 使用C++模板的常用设计技巧. 应用例证(其中一些是“高 级”应用). 百度云及其他网盘下载地址:点我 名人推荐 如果今年你只打算买一本C++的书,那就选<C++ ...