一、前言

以下内容均摘自《JavaScript语言精粹》一书,本人在读这本书时,发现作者诠释JavaScript很犀利,特别是数组部分,固记录下来,想和大家分享下。

随笔主要包含两大部分:

  1、数组阐述部分;

  2、其他片段。

二、JavaScript数组

数组是一段线性分配的内存,它通过整数计算偏移并访问其中的元素。数组是一种性能出色的数据结构。不幸的是,JavaScript没有像此类数组一样的数据结构。

作为替代,JavaScript提供了一种拥有一些类数组(array-like)特性的对象。它把数组的下标转变成字符串,用其作为属性。它明显地比一个真正的数组慢,但它使用起来更方便。它的属性的检索和更新的方式和对象一模一样,只不过多一个可以用整数作为属性名的特性。数组有自己的字面量格式。

数组--字面量:

数组字面量提供了一种非常方便地创建数组的表示法。一个数组字面量是在一对方括号中包围零个或多个用逗号分隔的值的表达式。数组字面量允许出现在任何表达式可以出现的地方。数组的第一个值将获得属性名’0’,第二值将获得属性名’1’,依次类推:

var empty = [];
var numbers = [
'zero', 'one', 'two', 'three', 'four',
'five', 'six', 'seven', 'eight', 'nine'
];
empty[1] //undefined
numbers[1] //'one' empty.length //
numbers.length //

对象字面量:

var numbers_object = {
'0': 'zero', '1': 'one', '2': 'two',
'3': 'three', '4': 'four', '5': 'five',
'6': 'six', '7': 'seven', '8': 'eight',
'9': 'nine'
};

两者产生的结果相似。numbers和numbers_object都是包含10个属性的对象,并且那些属性刚好有相同的名字和值。但是它们也有一些显著的不同。numbers继承自Array.prototype,而numbers_object继承自Object.prototype,所以numbers继承了大量有用的用法。同时,numbers也有一个诡异的length属性,而numbers_object则没有。

在大多数语言中,一个数组的所有元素都要求是相同的类型。JavaScript允许数组包含任意混合类型的值。

var misc = [
'string', 98.6, true, false, null, undefined,
['nested', 'array'], {object: true}, NaN,
Infinity
];
misc.length //

数组--长度:

每个数组都有一个length属性。和大多数其他语言不通,JavaScript数组的length是没有上界的。如果你用大于或等于当前length的数字作为下标来存储一个元素,那么length值会被增大以容纳新元素,不会发生数组越界错误。

length属性的值是这个数组的最大整数属性名加上1.它不一定等于数组里的属性的个数:

var myArray = [];
myArray.length // myArray[1000000] = true;
myArray.length //
//myArray只包含一个属性

[ ]后置下标运算符把它所含的表达式转换成一个字符串,如果该表达式有toString方法,就使用该方法的值。这个字符串将被用作属性名。如果这个字符串看起来像一个大于等于这个数组当前的length且小于4294967295的正整数,那么这个数组的length就会被重新设置为新的下标加1。

你可以直接设置length的值。设置更大的length不会给数组分配更多的空间。而把length设小将导致所有下标大于等于新length的属性被删除:

numbers.length = 3;
//numbers是['zero', 'one', 'two']

通过把下标指定为一个数组的当前length,可以附加一个新元素到该数组的尾部:

numbers[numbers.length] = 'shi';
//numbers是['zero', 'one', 'two', 'shi']

有时用push方法可以更方便地完成同样的事情:

numbers.push('go');
//numbers是['zero', 'one', 'two', 'shi', 'go']

数组--删除:

由于JavaScript的数组其实就是对象,所以delete运算符可以用来从数组中移除元素:

delete numbers[2];
//numbers是['zero', 'one', undefined, 'shi', 'go']

不幸的是,那样会在数组中留下一个空洞。这是因为排在被删除元素之后的元素保留着它们最初的属性。而你通常想要的是递减后面每个元素的属性。

幸运的是,JavaScript数组有一个splice方法。它可以对数组做个手术,删除一些元素并将它们替换为其他的元素。第1个参数是数组中的一个序号,第2个参数是要删除的元素个数。任何额外的参数会在序号那个点的位置被插入到数组中:

numbers.splice(2, 1);
//numbers是['zero', 'one', 'shi', 'go']

值为’shi’的属性的键值从’3’变到’2’。因为被删除属性后面的每个属性必须被移除,并且以一个新的键值重新插入,这对于大型数组来说可能会效率不高。

数组--枚举:

因为JavaScript的数组其实就是对象,所以for in语句可以用来遍历一个数组的所有属性。遗憾的是,for in无法保证属性的顺序,而大多数要遍历数组的场合都期望按照阿拉伯数字来产生元素。此外,可能从原型链中得到意外属性的问题依旧存在。

幸运的是,常规for语句可以避免这些问题。JavaScript的for语句和大多数类C(C-like)语言相似。它被3个从句控制—第1个初始化循环,第2个执行条件检测,第3个执行增量运算:

var i;
for(i = 0; i < myArray.length; i += 1){
document.writeln(myArray[i]);
}

数组--容易混淆的地方:

在JavaScript编程中,一个常见的错误是在必须使用数组时使用了对象,或者在必须使用对象时使用了数组。其实规则很简单:当属性名是小而连续的整数时,你应该使用数组。否则,使用对象。

JavaScript本身对于数组和对象的区别是混乱的。typeof运算符报告数组的类型是’object’,这没有任何意义。

JavaScript没有一个好的机制来区别数组和对象。我们可以通过定义自己的is_array函数来弥补这个缺陷:

var is_array = function(value){
return value &&
typeof value === 'object' &&
value.constructor === Array;
};

遗憾的是,它在识别从不同的窗口(window)或帧(frame)里构造的数组时会失败。有一个更好的方式去判断一个对象是否为数组:

var is_array = function(value){
return Object.prototype.toString.apply(value) === '[object Array]';
};

数组--小结:

JavaScript没有真正的数组。这也不全是坏事。JavaScript的数组确实非常容易使用。你不必给它们设置维度,而且它们永远不会产生越界(out-of-bounds)错误。但它们的性能相比真正的数组可能相当糟糕。

typeof运算符不能辨别数组和对象。要判断一个值是否为数组,你还需要检查它的constructor属性:

if(my_value && typeof my_value === 'object' && my_value.constructor === Array){
//my_value是一个数组
}

上面的检测对于在不同帧或窗口创建的数组将会给出false。当数组有可能在其他的帧中被创建时,下面的检测更为可靠:

if(Object.prototype.toString.apply(my_value) === '[object Array]'){
//my_value确实是一个数组
}

arguments数组不是一个数组,它只是一个有着length成员属性的对象。上面的检测会分辨出arguments并不是一个数组。

三、花絮

1、  JavaScript是弱类型,固不需要进行类型转换;

2、  一个编译单元包含一组可执行的语句。在Web浏览器中,每个<script>标签提供一个被编译且立即执行的编译单元。因为缺少链接器,JavaScript把它们一起抛到一个公共的全局名字空间中。

3、  词法作用域:当定义了一个函数后,当前的作用域就会被保存下来,并且成为函数内部状态的一部分。

4、  在if判断中,下列值被当做假:

   False    null    undefined    空字符串’ ’    数字0    NaN

5、  函数包含一组语句,它们是JavaScript的基础模块单元,用于代码复用、信息隐藏和组合调用。函数也是对象,与众不同之处在于它们可以被调用。因为函数是对象,所以它们可以像任何其他的值一样被使用。函数可以保存在变量、对象和数组中。函数可以被当做参数传递给其他函数,函数也可以再返回函数。而且函数是对象,所以函数可以拥有方法。当一个函数被保存为一个对象属性时,我们称它为一个方法;当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用;当一个函数,如果创建的目的就是希望结合new前缀来调用,那它就被称为构造函数。

6、  对象字面量是一种可以方便地按指定规格创建新对象的表示法。属性名可以死标识符或字符串。这些名字被当做字面量而不是变量名来对待,所以对象的属性名在编译时才能知道。

7、  柯里化:允许我们把函数与传递给它的参数相结合,产生出一个新的函数。通过创建一个保存着原始函数和要被套用的参数的闭包工作。它返回另一个函数,该函数被调用时,会返回调用原始函数的结果,并传递调用curry时的参数加上当前调用的参数。它使用Array的concat方法连接两个参数数组。

《JavaScript语言精粹》小记的更多相关文章

  1. 《C++语言导学》小记

    我看的这本是Bjarne Stroustrup写的,南开大学的杨巨峰和王刚译的.这本书不适合初学者看,我就是大概翻了翻其中感兴趣的章节. 这本书第14章的标题是“历史和兼容性”,这节内容我看了收获很深 ...

  2. Java语言导学笔记 Chapter 9 IO

    java.io 9.1.1 字符流 Reader为读取器(reader)提供API和部分实现,读取器是读取16位字符的流: Writer为写出器(writer)提供API和部分实现,写出器是写16位字 ...

  3. Java语言导学笔记 Chapter 8 Thread

    8.1 什么是线程 def: 线程是程序内的一个单一的顺序控制流程 作为一个顺序的控制流程,线程必须在运行它的程序中占用一些资源.例如,线程必须有它自己的执行堆栈和程序计数器.在线程内运行的代码只在此 ...

  4. java语言导学(5版)--第12章并发之二

    1不可变对象 概念:(immutable)对象创建后,状态不可更改.不可变对象在并发程序中尤其有用,因状态不可变,不会被线程干扰,也不会出现不一致状态. 书中通过实例是可变的类,并从此类衍生出一个不可 ...

  5. Spring Cloud微服务安全实战_1-1_导学

    这两年微服务是一个很火的话题 .在java语言的体系里,现在最火的就是SpringCloud. 本系列文章主要不是讲:怎么使用SpringSpringCloud组件搭建一个微服务的体系,如服务的认证注 ...

  6. springboot系列教程导学篇

    spring boot2.0系列教程学习之导学篇 springboot 2.0深度学习系列教程. Spring Boot 虽然凯哥从2015年年初开始就接触了spring boot.但是在之后的公司中 ...

  7. 001 01 Android 零基础入门 01 Java基础语法 01 Java初识 01 导学

    001 01 Android 零基础入门 01 Java基础语法 01 Java初识 01 导学 welcome to Java World 欢迎来到Java世界 一起领略Java编程世界的奥秘与奥妙 ...

  8. D10——C语言基础学PYTHON

    C语言基础学习PYTHON——基础学习D10 20180906内容纲要: 1.协程 (1)yield (2)greenlet (3)gevent (4)gevent实现单线程下socket多并发 2. ...

  9. 1-1 课程导学 & 1-2 项目需求分析,技术分解.

    1-1 课程导学 1-2 项目需求分析,技术分解. 要有一定的dart基础,了解安卓和ios的一些普通的开发

  10. 第一周<导学>

    导学 欧氏距离 平方 曼哈顿距离 一次方 马氏距离 协方差(先标准化再计算距离)\(d(x_{i},x_{j})=\sqrt{(x_{i}-x_{j})^{T}s^{-1}(x_{i}-x{j})}\ ...

随机推荐

  1. A library of generic data structures

    A library of generic data structures including a list, array, hashtable, deque etc.. https://github. ...

  2. sass和compass的配置

    http://note.youdao.com/share/?id=4f57187f9695bcaadf80516187d2de0e&type=note 当执行安装sass出错时,可以试试这个命 ...

  3. 关于C#的微信开发的入门记录二

    在准备了空间和域名之后,现在来讲讲我们接下来的编码过程: 今天就先到这里了!没有服务器那些的请看我之前的博客:http://www.cnblogs.com/zhankui/p/4515905.html ...

  4. 基于thinkphp的省略图便捷函数

    /** * 生成缩略图 * @param string $image 原图路径 例:thumb_5242d9082fcdc.jpg * @param string $type 图像格式 * @para ...

  5. swiper的初步使用

    1.引入文件,顺序引入(此处基于jquery,且版本至少1.7以上) <link rel="stylesheet" href="path/to/swiper-3.4 ...

  6. *HDU 1757 矩阵乘法

    A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  7. 2016huasacm暑假集训训练五 H - Coins

    题目链接:http://acm.hust.edu.cn/vjudge/contest/126708#problem/H 题意:A有一大堆的硬币,他觉得太重了,想花掉硬币去坐的士:的士司机可以不找零,但 ...

  8. backbone入门示例

    最近因为有个项目需要用backbone+mui  所以最近入坑backbone. Backbonejs有几个重要的概念,先介绍一下:Model,Collection,View,Router.其中Mod ...

  9. web Api 返回json 的两种方式

    web api写api接口时默认返回的是把你的对象序列化后以XML形式返回,那么怎样才能让其返回为json呢,下面就介绍两种方法: 方法一:(改配置法) 找到Global.asax文件,在Applic ...

  10. tar 命令

    tar -cf   打包的文件名    打包的文件   ------tar  -cf   db.all   test.txt   (-c  表示建立新的包,-f通常是必选项) tar -tf   打包 ...