在JavaScript中,除了5种原始数据类型之外,其他所有的都是对象,包括函数(Function)。

基本数据类型:String,boolean,Number,Undefined, Null

引用数据类型:Object(Array,Date,RegExp,Function)

在这个前提下,咱们再来讨论JavaScript的对象。

1、创建对象

var obj = {}; //种方式创建对象,被称之为对象直接量(Object Literal)
var obj = new Object(); // 创建一个空对象,和{}一样

更多创建对象的知识,参见《JavaScript权威指南(第6版)》第6章

2、创建数组

var arr = [];//这是使用数组直接量(Array Literal)创建数组
var arr = new Array();//构造函数Array() 创建数组对象

更多创建数组的知识,参见《JavaScript权威指南(第6版)》第7章。

3、对象与数组的关系

在说区别之前,需要先提到另外一个知识,就是JavaScript的原型继承。所有JavaScript的内置构造函数都是继承自 Object.prototype。在这个前提下,可以理解为使用 new Array() 或 [] 创建出来的数组对象,都会拥有 Object.prototype 的属性值。

对于题主的问题意味着:

var obj = {};// 拥有Object.prototype的属性值
var arr = [];
//使用数组直接量创建的数组,由于Array.prototype的属性继承自 Object.prototype,
//那么,它将同时拥有Array.prototype和Object.prototype的属性值

可以得到对象和数组的第一个区别:对象没有数组Array.prototype的属性值

4、什么是数组

数组具有一个最基本特征:索引,这是对象所没有的,下面来看一段代码:

var obj = {};
var arr = [];obj[2] = 'a';
arr[2] = 'a';console.log(obj[2]); // 输出 a
console.log(arr[2]); // 输出 a
console.log(obj.length); // 输出 undefined
console.log(arr.length); // 输出 3

通过上面这个测试,可以看到,虽然 obj[2]与arr[2] 都输出'a',但是,在输出length上有明显的差异,这是为什么呢?

obj[2]与arr[2]的区别

  • obj[2]输出'a',是因为对象就是普通的键值对存取数据

  • 而arr[2]输出'a' 则不同,数组是通过索引来存取数据,arr[2]之所以输出'a',是因为数组arr索引2的位置已经存储了数据

obj.length与arr.length的区别

  • obj.length并不具有数组的特性,并且obj没有保存属性length,那么自然就会输出undefined

  • 而对于数组来说,length是数组的一个内置属性,数组会根据索引长度来更改length的值。

为什么arr.length输出3,而不是1呢?

  • 这是由于数组的特殊实现机制,对于普通的数组,如果它的索引是从0开始连续的,那么length的值就会等于数组中元素个数

  • 而对于上面例子中arr,在给数组添加元素时,并没有按照连续的索引添加,所以导致数组的索引不连续,那么就导致索引长度大于元素个数,那么我们称之为稀疏数组。

有关稀疏数组的特性就不再讨论更多,参见《JavaScript权威指南(第6版)》7.3节。

5、伪数组

定义:

1、拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理,这里你可以当做是个非负整数串来理解)
2、不具有数组所具有的方法

伪数组,就是像数组一样有 length 属性,也有 0123 等属性的对象,看起来就像数组一样,但不是数组,比如

var fakeArray = {length: 3,"0": "first","1": "second","2": "third"
};for (var i = 0; i < fakeArray.length; i++) {console.log(fakeArray[i]);
}Array.prototype.join.call(fakeArray,'+');

常见的参数的参数 arguments,DOM 对象列表(比如通过 document.getElementsByTags 得到的列表),jQuery 对象(比如 $("div"))。

伪数组是一个 Object,而真实的数组是一个 Array

fakeArray instanceof Array === false;
Object.prototype.toString.call(fakeArray) === "[object Object]";var arr = [1,2,3,4,6];
arr instanceof Array === true;
Object.prototype.toString.call(arr) === "[object Array]"

《javascript权威指南》上给出了代码用来判断一个对象是否属于“类数组”。如下:

// Determine if o is an array-like object.
// Strings and functions have numeric length properties, but are
// excluded by the typeof test. In client-side JavaScript, DOM text
// nodes have a numeric length property, and may need to be excluded
// with an additional o.nodeType != 3 test.
function isArrayLike(o) {    if (o &&                                // o is not null, undefined, etc.typeof o === 'object' &&            // o is an objectisFinite(o.length) &&               // o.length is a finite numbero.length >= 0 &&                    // o.length is non-negativeo.length===Math.floor(o.length) &&  // o.length is an integero.length < 4294967296)              // o.length < 2^32return true;                        // Then o is array-likeelsereturn false;                       // Otherwise it is not
}

不过有个更简单的办法来判断,用 Array.isArray

Array.isArray(fakeArray) === false;
Array.isArray(arr) === true;

从外观上看伪数组,看不出来它与数组的区别,在JavaScript内置对象中常见的伪数组就是大名鼎鼎的auguments:

(function() {console.log(typeof arguments); // 输出 object,它并不是一个数组
}());

另外在DOM对象中,childNodes也是伪数组

console.log(typeof document.body.childNodes); // 输出 object

除此之外,还有很多常用的伪数组,就不一一列举。

伪数组存在的意义,是可以让普通的对象也能正常使用数组的很多算法,比如:

var arr = Array.prototype.slice.call(arguments)或者
var arr = Array.prototype.slice.call(arguments, 0); // 将arguments对象转换成一个真正的数组Array.prototype.forEach.call(arguments, function(v) {// 循环arguments对象
});

除了使用 Array.prototype.slice.call(arguments),你也可以简单的使用[].slice.call(arguments) 来代替。另外,你可以使用 bind 来简化该过程。

var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);function list() {return slice(arguments);
}var list1 = list(1, 2, 3); // [1, 2, 3]

将具有length属性的对象转换成数组对象,arguments是每个函数在运行的时候自动获得的一个近似数组的对象(传入函数的参数从0开始按数字排列,而且有length)。

比如当你 func('a', 'b', 'c') 的时候,func里面获得的arguments[0] 是 'a',arguments[1] 是 'b',依次类推。但问题在于这个arguments对象其实并不是Array,所以没有slice方法。Array.prototype.slice.call( )可以间接对其实现slice的效果,而且返回的结果是真正的Array

对于IE9以前的版本(DOM实现基于COM),我们可以使用makeArray来实现。

// 伪数组转化成数组
var makeArray = function(obj) {    if (!obj || obj.length === 0) {        return [];}    // 非伪类对象,直接返回最好if (!obj.length) {        return obj;}    // 针对IE8以前 DOM的COM实现try {        return [].slice.call(obj);} catch (e) {        var i = 0,j = obj.length,res = [];        for (; i < j; i++) {res.push(obj[i]);}return res;}};

更多关于伪数组的知识,参见《JavaScript权威指南(第6版)》7.11节。

6、总结

  • 对象没有数组Array.prototype的属性值,类型是Object,而数组类型是Array;

  • 数组是基于索引的实现,length会自动更新,而对象是键值对;

  • 使用对象可以创建伪数组,伪数组可以正常使用数组的大部分方法;

JavaScript中的数组与伪数组的区别相关推荐

  1. JavaScript中利用for循环遍历数组

    这篇文章主要为大家详细介绍了JavaScript中利用for循环遍历数组,最好不要使用for in遍历,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 先看一段代码 1 2 3 4 5 6 7 8 ...

  2. java 真数组 伪数组_伪数组(ArrayLike)

    伪数组的定义和特性 伪数组 (ArrayLike),又称类数组.是一个类似数组的对象,但是有如下几个特征: 按索引方式储存数据: 0: xxx, 1: xxx, 2: xxx... 具有length属 ...

  3. html5有foreach吗,JavaScript中的map()和forEach()有什么区别?

    来源:https://medium.com/better-programming,作者:Moon,翻译:公众号<前端全栈开发者> JavaScript中一些最受欢迎的功能可能是map和fo ...

  4. java两字符串是否相等_Java与JavaScript中判断两字符串是否相等的区别

    JavaScript是一种常用的脚本语言,这也决定了其相对于其他编程语言显得并不是很规范.在JavaScript中判断两字符串是否相等 直接用==,这与C++里的String类一样.而Java里的等号 ...

  5. JavaScript中的name和classname有什么区别

    JavaScript 中的 name 和 className 有如下区别: name 属性通常用于表示 HTML 元素的名称,如表单元素中的 input 元素.它可以用于给服务器发送数据. class ...

  6. JavaScript中十种一步拷贝数组的方法

    JavaScript中我们经常会遇到拷贝数组的场景,但是都有哪些方式能够来实现呢,我们不妨来梳理一下. 1.扩展运算符(浅拷贝) 自从ES6出现以来,这已经成为最流行的方法.它是一个很简单的语法,但是 ...

  7. JavaScript中十个一步拷贝数组的方法

    JavaScript中我们经常会遇到拷贝数组的场景,但是都有哪些方式能够来实现呢,我们不妨来梳理一下. 1.扩展运算符(浅拷贝) 自从ES6出现以来,这已经成为最流行的方法.它是一个很简单的语法,但是 ...

  8. Web前端技术分享:Javascript中的内置对象数组讲解

    有关js中的数组,很多小伙伴可能都会有疑问,尤其是面试的过程中有大量有关于原生数组的题,以及数组中的方法,及方法的返回值.是否会修改原数组等等.想要彻底解决这些问题,就要系统的解析数组的方法,那么今天 ...

  9. JavaScript 中 15 种常见的数组操作

    本文 GitHub https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料.欢迎Star和完善,大家面试可以参照考点复习 ...

最新文章

  1. $(function(){}) 与(function(){})()在执行时的优先级
  2. XP调整禁用页面文件
  3. 分享十五个最佳jQuery幻灯插件和教程
  4. 图例 | Java混合模式分析之火焰图实例
  5. 95-10-160-启动-KafkaApis
  6. 求 一个字符 在二进制表示中1的个数
  7. Ubuntu 10.04 is coming
  8. 鸿蒙系统小米手机,华为鸿蒙系统已经发布,小米等国产手机会使用鸿蒙系统吗?...
  9. 零基础学python鱼c-《零基础入门学习Python》第二版和第一版的区别在哪里呢?...
  10. 打log的方式检查程序里面的问题 及示例代码 详解
  11. PHP上传的文件权限不足,上传文件的PHP脚本不工作的问题(目录权限问题)php-fpm+nginx...
  12. Tomcat实现Web Socket
  13. 企业短信平台发展趋势和展望——SUBMAIL赛邮
  14. 练习 颈部肌肉重要性及锻炼方法
  15. CentOS7 忘记密码——重置
  16. 红米NOTE5 ROOT教程
  17. 登录起凡是显示计算机拒绝无法连接,怎么解决win10系统无法连接打印机并显示未指定设备问题?...
  18. 计算机相关书籍推荐(持续更新)
  19. IT路要如何走?——老程序员的10个忠告
  20. 【Tyvj1922】Freda的迷宫

热门文章

  1. Profiler 使用说明
  2. matlab中用colfilt实现非线性滤波(图片版)
  3. Java关键字介绍之final
  4. 《Effective C#》Item 15:利用using和try-finally来释放资源
  5. 分配性质是什么意思_苏教版六年级数学上册3.9按比分配问题(1)微课视频 | 练习...
  6. NSURLErrorRelatedURLSessionTaskErrorKey
  7. 模拟linux文件系统的设计及实现_Linux后台服务器开发中,内存池设计与实现(c/c++)...
  8. WordPress插件扫描工具plecost
  9. 编码/解码和进制转化工具hURL
  10. Animator窗口视图Project视图PlayerIdleAnimation和PlayerWalkingAnimation