给数组增加属性和方法(prototype)

案例分析

var obj = {
  count: 1
}

var myArray = ['red', 'white', 'black'];
console.log(myArray.length);

myArray.obj = obj;
console.log(myArray.length);

两次打印myArray的length是多少?为什么?


理想与现实的冲突

我认为结果应该是 3 4

但结果是 4 4

打印的数组如我所想 [ 'red', 'white', 'black', obj: { count: 1 } ]

然length 仍然为3

老实说,一上来就被整懵逼了。

从现实出发


可仔细一看,案例本来就没有给数组多增加元素个数。

myArray.obj = obj;

这一点非常关键 案例用的时 点语法 赋值操作,那么意思就是给myarray数组增加了一个obj属性。属性值是定义的obj对象。

而真正的向数组添加元素 用的是数组的 push方法。push才是真正的向数组中添加一个元素。

如果代码改成这样,数组长度就是理想的长度了。

myArray.push(obj);
console.log(myArray);
console.log(myArray.length);

而.obj只是为当前的这个数组增加属性,

myArray.name = 'xiaoming';
console.log(myArray);
console.log(myArray.length);

实验表明,使用.属性只能增加数组的属性,

而这些属性和值通常通过键值对的形式放在数组元素的后面,而不会增加数组的个数。

[ 'red', 'white', 'black', obj: { count: 1 } ]

对数组长度的理解


数组长度:

The length property of an object which is an instance of type Array sets or returns the number of elements in that array. The value is an unsigned, 32-bit integer that is always numerically reater than the highest index in the array.

  1. length 属性 是数组设置或返回数组中的元素个数。它的值是无符号32位整数,始终数值上大于数组中的最高索引。
var fruits = [];
fruits.push('banana', 'apple', 'peach');
console.log(fruits.length); // 3
// 当给数组设置一个属性,当这个属性是合法的数组索引,并且数组索引超出了当前数组的边界,引擎就会相应的更新数组的length属性
fruits[5] = 'mango';
console.log(fruits[5]); // 'mango'
console.log(Object.keys(fruits));  // ['0', '1', '2', '5']
console.log(fruits.length); // 6

  1. 由于length可以取值也可以赋值,所以length属性并不能确切的表示数组中元素的个数,解释如下:

You can set the length property to truncate an array at any time. When you extend an array by changing its length property, the number of actual elements does not increase; for example, if you set length to 3 when it is currently 2, the array still contains only 2 elements. Thus, the length property does not necessarily indicate the number of defined values in the array. See also Relationship between length and numerical properties.

你可以随时设置length属性来缩短一个数组,它真的就缩小的,只会保留length个元素。
当你通过改变length属性扩大数组时,实际的元素个数并没有增加,例如,当前数组有2个元素,把length设置为3,数组依然只包含2个元素。因此 length属性不能确切的反映数组中的元素个数。

  1. length和数字属性的关系
    我们知道数组是通过索引访问的 或者说 通过下标来访问的。那么下标其实就是数字属性,而数组的length属性是和数字属性连在一起的。
    其中数组几个内置的函数(比如, join, slice, indexOf, 等) 被调用时会计算数组的length属性,
    其他的方法(比如, push, splice, 等)也会更新数组的length属性

  2. 既然属性可以用点语法访问,为什么数字属性不行
    属性一般可以通过点语法访问,这要求点语法点到的必须是一个合法命名的变量。而合法的命名是不允许以数字开头的。
    所以这个属性只能通过括号表示法方法 即myArray[0]

  1. 关于数组中有多少个元素的思考
    通过上述分析,我们知道length属性并不能正确表示数组中有多少个元素。
    比如说修改数组的最高索引,或者更直接点直接修改length属性的值,这样都无法反应数组到底有几个元素。
    这就有个问题,如何知道数组中到底有多少个元素?
    上面打印结果的 obj:{count:1}是不是数组的元素呢?应不应该算上?
    数组的属性是数字,通过索引访问。数组的索引就是数组特殊的属性名,而obj不是数字属性 以这种形式展示在数组中 obj:{count:1} 那么数组本质上或许也是这么写的[0:'red',1:'white']
    那么我个人觉得要算上,数组中键的个数就代表了数组中有多少个元素
    console.log(Object.keys(myArray).length);
    然而这么算就会有一个困惑。还好这个属性是添加在具体的数组中的,所以才有显示出来,如果是在Array.prototype中定义的,那么就不会打印出来。所以我觉得非数字类索引是不需要的算入有多少个元素的。
    如果要算有多少个元素,就要排除到这些非数字属性。

总结与应用


如果看到键值对的形式(外面没有括号包裹,即非独立对象)出现在数组中,

那它就不是作为数组元素存在的,而是作为数组的属性或方法存在的。

这就意味着 可以给数组增加 属性和方法 方便我们使用了。

比如返回每个数组的平方

var myArray = [1,2,3,4,5];
myArray.square = function () {
    for (var i = this.length - 1; i >= 0; i--) {
        this[i] *= this[i];
    }
    return this;
};
console.log(myArray.square());

加深理解


我查了查,这个东西其实叫做原型prototype其作用就是给对象添加属性和方法的。上述链接是W3C的参考例子。是从具体的对象层面增加的属性和方法。案例也是这个意思。

还可以给每一个对象增加属性和方法,这是MDN对Array.prototype的解释,比如给Array增加一个first方法,那么所有的数组实例都拥有这个方法,而且打印数组时,此方法在数组中不会看到。

console.log(myArray.square());
if (!Array.prototype.first) {
  Array.prototype.first = function() {
    return this[0];
  }
}
console.log(myArray.first());

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容

  • Javascript有很多数组的方法,有的人有W3C的API,还可以去MDN上去找,但是我觉得API上说的不全,M...
    顽皮的雪狐七七阅读 4,071评论 0 6
  • 一、JS前言 (1)认识JS 也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HT...
    凛0_0阅读 2,758评论 0 8
  • 第1章 认识JS JavaScript能做什么?1.增强页面动态效果(如:下拉菜单、图片轮播、信息滚动等)2.实现...
    mo默22阅读 1,257评论 0 5
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,741评论 0 33
  • FreeCodeCamp - Basic JavaScript 写在前面: 我曾经在进谷前刷过这一套题,不过当时只...
    付林恒阅读 16,436评论 5 28