Javascript之Array对象

The JavaScript Array object is a global object that is used in the construction of arrays; which are high-level, list-like objects.

先看看Array的prototype的结构:

Array的prototype的结构

0.length属性

length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标。

注意:length属性是可以手动修改的,而且通过下标赋值时自动更新length的值;

手动修改length
length自动更新为大于数组最大项的下标

1.concat

concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。


将数组和/或值连接成新数组

2.constructor

3.copyWithin

Syntax:

arr.copyWithin(target)

arr.copyWithin(target,start)

arr.copyWithin(target,start,end)

Parameters:

target

Zero based index at which to copy the sequence to. If negative, target will be counted from the end.

If target is at or greater than arr.length, nothing will be copied. If target is positioned after start, the copied sequence will be trimmed to fit arr.length.

start Optional

Zero based index at which to start copying elements from. If negative, start will be counted from the end.

If start is omitted, copyWithin will copy from the start (defaults to 0).

end Optional

Zero based index at which to end copying elements from. copyWithin copies up to but not including end. If negative, end will be counted from the end.

If end is omitted, copyWithin will copy until the end (default to arr.length).

Return value

The modified array.

详述

The copyWithin works like C and C++'s memmove, and is a high-performance method to shift the data of an Array. This especially applies to the TypedArray method of the same name. The sequence is copied and pasted as one operation; pasted sequence will have the copied values even when the copy and paste region overlap.

The copyWithin function is intentionally generic, it does not require that its this value be an Array object.

The copyWithin method is a mutable method. It does not alter the length of this, but will change its content and create new properties if necessary.

总结:

#1.target参数是必须的,也就是说copyWithin方法至少需要一个参数,否则该方法无效

缺少必要的参数

#2.target参数可以为负数,此时从末尾开始计算


target为负数

#3.start参数默认是0,当为负数时从末尾开始计算

#4.end参数默认是数组的长度,当为负数时从末尾开始计算

end参数使用默认值

4.entries

entries() 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。该方法返回一个新的 Array 迭代器对象。Array Iterator是对象,它的原型(__proto__:Array Iterator)上有一个next方法,可用用于遍历迭代器取得原数组的[key,value]。

使用entries获取迭代器来遍历数组

5.every:

every() 方法测试数组的所有元素是否都通过了指定函数的测试。

语法:

arr.every(callback[, thisArgs])

参数

callback

用来测试每个元素的函数。

thisArg

执行 callback 时使用的this值。

说明

every 方法为数组中的每个元素执行一次callback 函数,直到它找到一个使callback 返回false(表示可转换为布尔值 false 的值)的元素。如果发现了一个这样的元素,every 方法将会立即返回false。否则,callback 为每一个元素返回 true,every就会返回true。callback 只会为那些已经被赋值的索引调用。不会为那些被删除或从来没被赋值的索引调用。

callback 被调用时传入三个参数:元素值,元素的索引,原数组。

如果为 every 提供一个thisArg参数,则该参数为调用 callback 时的 this 值。如果省略该参数,则 callback 被调用时的 this 值,在非严格模式下为全局对象,在严格模式下传入 undefined。

every 不会改变原数组。

every遍历的元素范围在第一次调用 callback 之前就已确定了。在调用 every 之后添加到数组中的元素不会被 callback 访问到。如果数组中存在的元素被更改,则他们传入 callback的值是 every 访问到他们那一刻的值。那些被删除的元素或从来未被赋值的元素将不会被访问到。

every和数学中的"所有"类似,当所有的元素都符合条件才返回true。另外,空数组也是返回true。(空数组中所有元素都符合给定的条件,注:因为空数组没有元素)。

测试数组中的值

6.fill:

fill方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。

语法:

arr.fill(value[, start[, end]])

描述:

具体要填充的元素区间是 [start, end) , 一个半开半闭区间.

fill 方法接受三个参数value, start 以及 end.start 和 end 参数是可选的, 其默认值分别为0和 this 对象的length 属性值.

如果start是个负数, 则开始索引会被自动计算成为length+start, 其中length是this 对象的 length 属性值. 如果 end 是个负数, 则结束索引会被自动计算成为 length+end.

fill方法故意被设计成通用方法, 该方法不要求 this 是数组对象.

fill方法是个可变方法, 它会改变调用它的 this 对象本身, 然后返回它, 而并不是返回一个副本.

当一个对象被传递给 fill 方法的时候, 填充数组的是这个对象的引用.

使用fill填充数组

7.filter:

filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。

语法:

var new_array = arr.filter(callback[, thisArg])

参数:

callback

用来测试数组的每个元素的函数。调用时使用参数 (element, index, array)。

返回true表示保留该元素(通过测试),false则不保留。

thisArg

可选。执行 callback 时的用于this的值。

使用filter过滤数组

8.find:

find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined

find方法的语法和filter类似。

find 方法对数组中的每一项元素执行一次callback 函数,直至有一个 callback 返回 true。当找到了这样一个元素后,该方法会立即返回这个元素的值,否则返回 undefined。注意 callback 函数会为数组中的每个索引调用即从 0 到 length - 1,而不仅仅是那些被赋值的索引,这意味着对于稀疏数组来说,该方法的效率要低于那些只遍历有值的索引的方法。

callback 函数带有3个参数:当前元素的值、当前元素的索引,以及数组本身。

如果提供了 thisArg 参数,那么它将作为每次 callback 函数执行时的上下文对象,否则上下文对象为 undefined

find 方法不会改变数组。

在第一次调用 callback 函数时会确定元素的索引范围,因此在 find 方法开始执行之后添加到数组的新元素将不会被 callback 函数访问到。如果数组中一个尚未被callback函数访问到的元素的值被callback函数所改变,那么当callback函数访问到它时,它的值是将是根据它在数组中的索引所访问到的当前值。被删除的元素仍旧会被访问到。

使用find方法查找数组中的元素

9.findIndex:

findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。

与find的方法用法相同。

使用findIndex查找数组中满足条件的元素的下标

10.forEach:

forEach() 方法对数组的每个元素执行一次提供的函数。

forEach 方法按升序为数组中含有效值的每一项执行一次callback函数,那些已删除(使用delete方法等情况)或者未初始化的项将被跳过(但不包括那些值为 undefined 的项)(例如在稀疏数组上)。

callback 函数会被依次传入三个参数:

数组当前项的值

数组当前项的索引

数组对象本身

如果给forEach传递了thisArg参数,当调用时,它将被传给callback 函数,作为它的this值。否则,将会传入 undefined 作为它的this值。callback函数最终可观察到this值,这取决于 函数观察到this的常用规则

forEach遍历的范围在第一次调用callback前就会确定。调用forEach后添加到数组中的项不会被callback访问到。如果已经存在的值被改变,则传递给callback 的值是forEach遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 shift()) ,之后的元素将被跳过 - 参见下面的示例。

forEach() 为每个数组元素执行callback函数;不像map() 或者reduce() ,它总是返回 undefined值,并且不可链式调用。典型用例是在一个链的最后执行副作用。

注意:forEach() 没有返回值,无法中止。

使用forEach函数实现对象复制

11.includes:

includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。

语法:

arr.includes(searchElement[, fromIndex])

fromIndex, 从该索引处开始查找 searchElement。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜索。如果值不在有效范围内,默认为 0。

12.indexOf:

indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。

语法:

arr.indexOf(searchElement[, fromIndex=0])

开始查找的位置。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找,-2表示从倒数第二个元素开始查找 ,以此类推。 注意:如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。如果抵消后的索引值仍小于0,则整个数组都将会被查询。其默认值为0.join:ƒ join()

13.join:

join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。

语法:

str = arr.join(separator)

separator,指定一个字符串来分隔数组的每个元素。如果需要(separator),将分隔符转换为字符串。如果省略(),数组元素用逗号分隔。默认为 ","。如果separator是空字符串(""),则所有元素之间都没有任何字符。返回值:一个所有数组元素连接的字符串。如果 arr.length 为0,则返回空字符串。

说明:所有的数组元素被转换成字符串,再用一个分隔符将这些字符串连接起来。如果元素是undefined 或者null, 则会转化成空字符串。

14.keys:

keys() 方法返回一个新的Array迭代器,它包含数组中每个索引的键。

使用keys()函数获取迭代器来遍历数组
索引迭代器会包含那些没有对应元素的索引

15.lastIndexOf:

lastIndexOf() 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。

语法:

arr.lastIndexOf(searchElement[, fromIndex = arr.length - 1])

从此位置开始逆向查找。默认为数组的长度减 1,即整个数组都被查找。如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移。即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找。

使用 lastIndexOf 定位数组中的值

16.map:

map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

map 方法会给原数组中的每个元素都按顺序调用一次callback 函数。callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。 callback函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。

callback 函数会被自动传入三个参数:数组元素,元素索引,原数组本身。

如果thisArg参数有值,则每次callback函数被调用的时候,this 都会指向thisArg 参数上的这个对象。如果省略了thisArg 参数,或者赋值为 null 或 undefined,则 this 指向全局对象 。

map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)。

使用 map 方法处理数组时,数组元素的范围是在 callback 方法第一次调用之前就已经确定了。在 map 方法执行的过程中:原数组中新增加的元素将不会被 callback 访问到;若已经存在的元素被改变或删除了,则它们的传递到 callback 的值是 map 方法遍历到它们的那一时刻的值;而被删除的元素将不会被访问到。

使用 map 方法获取每个字符所对应的 ASCII 码组成的数组

17.pop:

pop()方法从数组中删除最后一个元素,并返回该元素的。此方法更改数组的长度

pop方法有意具有通用性。该方法和 call() 或 apply() 一起使用时,可应用在类似数组的对象上。pop方法根据 length属性来确定最后一个元素的位置。如果不包含length属性或length属性不能被转成一个数值,会将length置为0,并返回undefined。

空数组上调用 pop(),返回  undefined

18.push:

push() 方法将一个或多个元素添加到数组的末尾,并返回新数组的长度。

语法:

arr.push(element1,...,elementN)

返回值:当调用该方法时,新的 length 属性值将被作为返回值返回。

push方法有意具有通用性。该方法和 call() 或 apply() 一起使用时,可应用在类似数组的对象上。push方法根据length属性来决定从哪里开始插入给定的值。如果length不能被转成一个数值,则插入的元素索引为 0,包括length不存在时。当 length 不存在时,将会创建它。

唯一的原生类数组(array-like)对象是 Strings,尽管如此,它们并不适用该方法,因为字符串是不可改变的。

push()函数返回数组的长度

19.reduce:

reduce() 方法对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值。

语法:

arr.reduce(callback[, initialValue])

callback

执行数组中每个值的函数,包含四个参数:

accumulator

累加器累加回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(如下所示)。

currentValue

数组中正在处理的元素。

currentIndex | 可选

数组中正在处理的当前元素的索引。 如果提供了initialValue,则索引号为0,否则为索引为1。

array | 可选

调用reduce的数组

initialValue | 可选

用作第一个调用callback的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。

注意:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。

没有提供initialValue,reduce函数调用2次callback
提供initialValue,reduce函数调用3次callback
提供initialValue=0,把reduce函数作为求和器

20.reduceRight:

reduceRight() 方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。

reduceRight 为数组中每个元素调用一次 callback 回调函数,但是数组中被删除的索引或从未被赋值的索引会跳过。回调函数接受四个参数:初始值(或上次调用回调的返回值)、当前元素值、当前索引,以及调用 reduce 的数组。

首次调用回调函数时,previousValue 和 currentValue可以是两个值之一。如果调用 reduceRight 时提供了initialValue参数,则previousValue等于initialValue,currentValue等于数组中的最后一个值。如果没有提供initialValue参数,则previousValue 等于数组最后一个值,currentValue 等于数组中倒数第二个值。

如果数组为空,且没有提供initialValue 参数,将会抛出一个TypeError 错误。如果数组只有一个元素且没有提供initialValue 参数,或者提供了initialValue 参数,但是数组为空将会直接返回数组中的那一个元素或 initialValue 参数,而不会调用callback。

reduce和reduceRight的区别

21.reverse:

reverse() 方法将数组中元素的位置颠倒,并返回该数组的引用。

利用reverse函数反转字符串

22.shift:

shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。如果数组为空则返回undefined 。

shift 方法移除索引为 0 的元素(即第一个元素),并返回被移除的元素,其他元素的索引值随之减 1。如果 length 属性的值为 0 (长度为 0),则返回 undefined

shift 方法并不局限于数组:这个方法能够通过call 或 apply方法作用于类似数组的对象上。但是对于没有 length 属性(从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。

shift函数删除数组中第一个元素

23.slice:

slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象。且原始数组不会被修改。

语法:

arr.slice([begin[, end]])

begin | 可选

从该索引处开始提取原数组中的元素(从0开始)。

如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2)表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。

如果省略 begin,则 slice 从索引 0 开始。

end | 可选

在该索引处结束提取原数组元素(从0开始)。slice会提取原数组中索引从begin到end 的所有元素(包含begin,但不包含end)。

slice(1,4) 提取原数组中的第二个元素开始直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。

如果该参数为负数,则它表示在原数组中的倒数第几个元素结束抽取。 slice(-2,-1)表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。

如果end被省略,则slice会一直提取到原数组末尾。

如果 end 大于数组长度,slice 也会一直提取到原数组末尾。

用slice函数选择数组元素

24.some:

some() 方法测试数组中的某些元素是否通过由提供的函数实现的测试。

some 为数组中的每一个元素执行一次callback 函数,直到找到一个使得 callback 返回一个“真值”(即可转换为布尔值 true 的值)。如果找到了这样一个值,some将会立即返回true。否则,some 返回 false。callback只会在那些”有值“的索引上被调用,不会在那些被删除或从来未被赋值的索引上调用。

callback 被调用时传入三个参数:元素的值,元素的索引,被遍历的数组。

如果为 some 提供了一个thisArg参数,将会把它传给被调用的callback,作为this值。否则,在非严格模式下将会是全局对象,严格模式下是 undefined。

some被调用时不会改变数组。

some遍历的元素的范围在第一次调用callback. 时就已经确定了。在调用 some 后被添加到数组中的值不会被 callback 访问到。如果数组中存在且还未被访问到的元素被 callback 改变了,则其传递给 callback 的值是 some 访问到它那一刻的值。

25.sort:

sort() 方法用就地( in-place )的算法对数组的元素进行排序,并返回数组。 sort 排序不一定是稳定的。默认排序顺序是根据字符串Unicode码点。

语法:

arr.sort(compareFunction)

sort()函数默认按照Unicode排序
情况复杂时,sort使用默认排序不能得到想要的结果
使用映射优化排序
自定义排序函数

26.splice:

splice() 方法通过删除现有元素和/或添加新元素来更改一个数组的内容。

语法:

array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

splice方法使用deleteCount参数来控制是删除还是添加:

start参数是必须的,表示开始的位置(从0计数),如:start=0从第一个开始;start>= array.length-1表示从最后一个开始。

①、从start位置开始删除[start,end]的元素。

array.splice(start)

②、从start位置开始删除[start,Count]的元素。

array.splice(start, deleteCount)    

③、从start位置开始添加item1, item2, ...元素。

array.splice(start, 0, item1, item2, ...)   

删除一个元素并插入一个元素    
插入一个元素
清空数组

27.toLocaleString:

toLocaleString() 返回一个字符串表示数组中的元素。数组中的元素将使用各自的toLocaleString 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 ",")隔开。

toLocaleString()函数可以将数组以字符串形式表达,并可以传入两个参数

28.toString:

toString() 返回一个字符串,表示指定的数组及其元素。Array 对象覆盖了Object 的 toString 方法。对于数组对象,toString 方法返回一个字符串,该字符串由数组中的每个元素的 toString() 返回值经调用join() 方法连接(由逗号隔开)组成。

返回数组的字符串表达

29.unshift:

unshift() 方法将一个或多个元素添加到数组的开头,并返回新数组的长度。unshift 方法会在调用它的类数组(array-like)对象的开始位置插入给定的参数。

unshift 特意被设计成具有通用性;这个方法能够通过call 或 apply方法作用于类似数组的对象上。不过对于没有 length 属性(代表从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。

当一个对象调用该方法时,返回其 length 属性值。

在数组的头部插入值

30.values:

values() 方法返回一个新的Array Iterator 对象,该对象包含数组每个索引的值。

注意:Chrome 未实现,Firefox未实现,Edge已实现。

Chrome 及Firefox可以用"arr[Symbol.iterator]()"方法来代替values()方法:

Array.prototype[@@iterator]()属性和 values() 属性的初始值均为同一个函数对象。

node环境未实现values函数

31.Symbol(Symbol.iterator):ƒ values()

@@iterator 属性和 values() 属性的初始值均为同一个函数对象。

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

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,131评论 0 13
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,764评论 0 38
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,106评论 0 21
  • 创建数组 arr.length--- title: js正则表达式categories: javascriptda...
    angelwgh阅读 1,385评论 0 2
  • 在遇到事情时,第一个想到的是你 在看到喜欢的视频和图片是,第一个想到是你 就是想把一切都和你分享 但是 我在通讯录...
    冰大头阅读 291评论 0 0