ES6數(shù)組的擴展

最近一直在看es6新曾的一寫數(shù)組的拓展,總結(jié)出了一些知識點

  • find,findIndex事示,inclueds
  • Map Set
  • 靜態(tài)方法(from早像,of)

find,findIndex,inclueds

find和findIndex

語法

arr .find(callback(element[, index[, array]])[, thisArg])
arr .findIndex(callback(element[, index[, array]])[, thisArg])

參數(shù)

callback

函數(shù)對數(shù)組中的每個值執(zhí)行,取三個參數(shù)

element

當前元素在數(shù)組中處理很魂。

index(可選的)

數(shù)組中正在處理的當前元素的索引扎酷。

array(可選的)

該陣列find被召喚檐涝。

thisArg (可選的)

this在執(zhí)行時使用的對象callback遏匆。

數(shù)組實例的find方法,用于找出第一個符合條件的數(shù)組成員谁榜。它的參數(shù)是一個回調(diào)函數(shù)幅聘,所有數(shù)組成員依次執(zhí)行該回調(diào)函數(shù),直到找出第一個返回值為true的成員窃植,然后返回該成員的value帝蒿。如果沒有符合條件的成員,則返回undefined巷怜。

let inventory = [
    {name: 'apples', quantity: 2},
    {name: 'bananas', quantity: 0},
    {name: 'cherries', quantity: 5}
];

function findCherries(fruit) { 
    return fruit.name === 'cherries';
}

console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }

下面代碼是找出數(shù)組中第一個大于9的成員

[1, 5, 10, 15].find((value, index, arr)=> {
  return value > 9;
}) // 10

[1, 5, 10, 15].find((value, index, arr)=> {
  if(index>2){
    return value > 9;
  }
}) // 15

數(shù)組實例的findIndex方法的用法與find方法非常類似葛超,返回第一個符合條件的數(shù)組成員的位置暴氏,如果所有成員都不符合條件,則返回-1绣张。上面find一樣答渔,不贅述。

[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}) // 2

這兩個方法都可以接受第二個參數(shù)侥涵,用來綁定回調(diào)函數(shù)的this對象沼撕。

function f(value){
  return value > this.age;
}
let person = {name: 'John', age: 20};
[10, 12, 26, 15].find(f, person);    // 26

includes

includes方法返回一個布爾值,表示某個數(shù)組是否包含給定的值芜飘,與字符串的includes方法類似

語法

arr .includes(searchElement [务豺,fromIndex])

參數(shù)

searchElement

要在數(shù)組中定位的元素。

fromIndex (可選的)

用于開始搜索的索引嗦明。如果索引大于或等于數(shù)組的長度笼沥,則返回-1,這意味著不會搜索該數(shù)組招狸。如果提供的索引值為負數(shù)敬拓,則將其作為數(shù)組末尾的偏移量。注意:如果提供的索引為負數(shù)裙戏,則仍會從前到后搜索數(shù)組乘凸。如果提供的索引為0,則將搜索整個數(shù)組累榜。默認值:0(搜索整個數(shù)組)营勤。

返回值

數(shù)組中元素的第一個索引; -1如果沒有找到。

[1, 2, 3].includes(2)     // true
[1, 2, 3].includes(4)     // false
[1, 2, NaN].includes(NaN) // true

[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true

沒有該方法之前壹罚,我們通常使用數(shù)組的indexOf方法葛作,檢查是否包含某個值。
indexOf方法有兩個缺點猖凛,一是不夠語義化赂蠢,它的含義是找到參數(shù)值的第一個出現(xiàn)位置,所以要去比較是否不等于-1辨泳,表達起來不夠直觀虱岂。二是,它內(nèi)部使用嚴格相等運算符(===)進行判斷菠红,這會導致對NaN的誤判第岖。
includes使用的是不一樣的判斷算法,就沒有這個問題试溯。

[NaN].indexOf(NaN)
// -1
[NaN].includes(NaN)
// true

另外蔑滓,這find(),findIndex()兩個方法都可以發(fā)現(xiàn)NaN,也彌補了數(shù)組的indexOf方法的不足。

[NaN].findIndex(y => Object.is(NaN, y))
// 0
[NaN].find(y => Object.is(NaN, y))
// NaN

附: Object.is() , === 和 == 對比表


對比表
//Object.is()的實現(xiàn)原理
isObject = function(x, y) {
    if (x === y) { // Steps 1-5, 7-10
      // 針對 +0不等于-0
      return x !== 0 || 1 / x === 1 / y;
    } else {
      // 針對 NaN等于NaN
      return x !== x && y !== y;
    }
  };

數(shù)組的去重

//最原始方法
var array = [1, 1, '1', '1'];

function unique(array) {
    // res用來存儲結(jié)果
    var res = [];
    for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {
        for (var j = 0, resLen = res.length; j < resLen; j++ ) {
            if (array[i] === res[j]) {
                break;
            }
        }
        // 如果array[i]是唯一的键袱,那么執(zhí)行完循環(huán)燎窘,j等于resLen
        if (j === resLen) {
            res.push(array[i])
        }
    }
    return res;
}

console.log(unique(array)); // [1, "1"]


//indexOf
var array = [1, 1, '1'];

function unique(array) {
    var res = [];
    for (var i = 0, len = array.length; i < len; i++) {
        var current = array[i];
        if (res.indexOf(current) === -1) {
            res.push(current)
        }
    }
    return res;
}

console.log(unique(array));

//filter
var array = [1, 2, 1, 1, '1'];

function unique(array) {
    var res = array.filter(function(item, index, array){
        return array.indexOf(item) === index;
    })
    return res;
}

console.log(unique(array));

Map和Set

在以數(shù)組和對象為編程主力的JavaScript 語言,ES6 中引入了4種新的數(shù)據(jù)結(jié)構(gòu)蹄咖,分別是:集合(Set)荠耽、弱集合(WeakSet)、映射(Map)比藻、弱映射(WeakMap)铝量。

Set

Set 對象是值的集合,可以按照插入的順序迭代它的元素银亲。Set 中的元素只會出現(xiàn)一次慢叨,即 Set 中的元素是唯一的。

語法

new Set([ iterable ]);

參數(shù)

iterable
是一個可迭代的對象务蝠,它的所有元素將被添加到新的 Set 中拍谐。
由于 Set 中的值總是唯一的,所以需要判斷兩個值是否相等馏段。在上面轩拨,內(nèi)部使用Object.is()方法檢測兩個值是否一致,但+0院喜、-0和0被視為是相等的元素亡蓉,NaN 和 undefined 是可以被存儲在 Set 中的,因為 NaN 在ES6中是嚴格相等的喷舀。

new Set([NaN, NaN, 2, "2", +0, -0]); // Set(4) {NaN, 2, '2', 0}

屬性

Set.prototype.size:返回 Set 對象的值的個數(shù)砍濒。

let mySet1 = new Set([NaN, NaN, 2, 3, 5, 5]);
mySet1.size; // 4

方法

(1)、在 Set 對象尾部添加一個元素:Set.prototype.add(value)

let  mySet1=new Set([NaN,1,2,3]).add(NaN).add(2).add(4); //Set(5) {NaN, 1, 2, 3, 4}

(2)硫麻、清除 Set 中所有的元素:Set.prototype.clear()

let mySet2=new Set(NaN,1,2,3).clear();  //undefined

(3)爸邢、判斷值是否存在于 Set 中:Set.prototype.has(value);

let mySet3=new Set([1,2,3,4,5]).has(2); //true
let mySet4=new Set([1,2,3,4,5]).has(7); //false

(4)拿愧、刪除 Set 中的某個值: Set.prototype.delete(value);

var mySet = new Set();
mySet.add("foo");
mySet.delete("bar"); // 返回 false杠河,不包含 "bar" 這個元素
mySet.delete("foo"); // 返回 true,刪除成功
mySet.has("foo");    // 返回 false浇辜,"bar" 已經(jīng)成功刪除

WeakSet

1券敌、WeakSet 結(jié)構(gòu)與 Set 結(jié)構(gòu)類似,WeakSet 是一個構(gòu)造函數(shù)奢赂,可以使用 new 命令創(chuàng)建 WeakSet 數(shù)據(jù)結(jié)構(gòu)陪白。

const a= ["yuan", "monkey"];
const myWeakSet = new WeakSet(a);  // WeakSet {"yuan", "monkey" }

2颈走、與 Set 區(qū)別
(1)膳灶、WeakSet 的成員只能是對象,而不能是其他類型的值。
(2)轧钓、WeakSet 中的對象都是弱引用序厉,即垃圾回收機制不考慮 WeakSet 對該對象的引用。 也就是說毕箍,如果其他對象都不再引用該對象弛房,那么垃圾回收機制會自動回收該對象所占用的內(nèi)存,不考慮該對象還存在于 WeakSet 之中而柑。這是因為垃圾回收機制依賴引用計數(shù)文捶,如果一個值的引用次數(shù)不為0,垃圾回收機制就不會釋放這塊內(nèi)存媒咳。結(jié)束使用該值之后粹排,有時會忘記取消引用,導致內(nèi)存無法釋放涩澡,進而可能會引發(fā)內(nèi)存泄漏顽耳。WeakSet 里面的引用,都不計入垃圾回收機制妙同,所以就不存在這個問題射富。因此,WeakSet 適合臨時存放一組對象粥帚,以及存放跟對象綁定的信息胰耗。只要這些對象在外部消失,它在 WeakSet 里面的引用就會自動消失芒涡。

由于上面這個特點宪郊,WeakSet 的成員是不適合引用的,因為它會隨時消失拖陆。另外弛槐,由于 WeakSet 內(nèi)部有多少個成員,取決于垃圾回收機制有沒有運行依啰,運行前后很可能成員個數(shù)是不一樣的乎串,而垃圾回收機制何時運行是不可預測的,因此 ES6 規(guī)定 WeakSet 不可遍歷速警。

這些特點同樣適用于本章后面要介紹的 WeakMap 結(jié)構(gòu)叹誉。
(3)、WeakSet 沒有size 屬性闷旧,沒有辦法遍歷其成員长豁。
3、方法
(1)忙灼、WeakSet.prototype.add(value):添加新成員匠襟;
(2)钝侠、WeakSet.prototype.delete(value):清楚指定成員;
(3)酸舍、WeakSet.prototype.has(value):判斷是否存在某個成員

Map

Map 對象保存鍵值對帅韧。任何值(對象或者原始值) 都可以作為一個鍵或一個值。
一個Map對象以插入順序迭代其元素 — 一個 for...of 循環(huán)為每次迭代返回一個[key啃勉,value]數(shù)組忽舟。

語法

new Map([ iterable ]);

參數(shù)

iterable
Iterable 可以是一個數(shù)組或者其他 iterable 對象,其元素或為鍵值對淮阐,或為兩個元素的數(shù)組叮阅。 每個鍵值對都會添加到新的 Map。null 會被當做 undefined泣特。

方法

(1)Map.prototype.set(key, value)
設(shè)置Map對象中鍵的值帘饶。返回該Map對象。
(2)Map.prototype.clear()
移除Map對象的所有鍵/值對 群扶。
(3)Map.prototype.has(key)
返回一個布爾值及刻,表示Map實例是否包含鍵對應(yīng)的值崇堰。

myMap.set("bar", "baz");
myMap.set(1, "foo");

myMap.size;       // 2
myMap.has("bar"); // true

myMap.clear();

myMap.size;       // 0
myMap.has("bar")  // false

(4)Map.prototype.delete(key)
移除任何與鍵相關(guān)聯(lián)的值徙融,并且返回該值容诬,該值在之前會被

var myMap = new Map();
myMap.set("bar", "foo");
myMap.delete("bar"); // 返回 true笤昨。成功地移除元素
myMap.has("bar");    // 返回 false涯保。"bar" 元素將不再存在于 Map 實例中

應(yīng)用

應(yīng)用
(1)旧困、Map 與 數(shù)組之間的相互轉(zhuǎn)換

// Map 轉(zhuǎn)數(shù)組
var myMap = new Map();
myMap.set("bar", "foo");
myMap.set(1, "bar");
[...myMap]; //  [ ["bar", "foo"], [1, "bar"] ]
// 數(shù)組轉(zhuǎn)Map
const arr = new Map( [ ["bar", "foo"], [1, "bar"] ]);
console.log(arr);  // Map {"bar" => "foo", 1 => "bar"}

(2)寨蹋、Map 與對象相互轉(zhuǎn)換

// Map 轉(zhuǎn)對象
function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [k, v] of strMap) {
    obj[k] = v;
  }
  return obj;
}
 const myMap = new Map();
myMap.set("bar", "foo")
.set(1, "ooo");

strMapToObj(myMap ); // Object {1: "ooo", bar: "foo"}

// 對象轉(zhuǎn) Map
function objToStrMap(obj) {
  let strMap = new Map();
  for (let k of Object.keys(obj)) {
    strMap.set(k, obj[k]);
  }
  return strMap;
}
objToStrMap({1: "ooo", bar: "foo"}); // Map {"1" => "ooo", "bar" => "foo"}

(3)蹄胰、Map 與 JSON 相互轉(zhuǎn)換

// Map 轉(zhuǎn) JSON
// Map 的鍵名為字符串
function strMapToJson(jsonStr) {
  return JSON.stringify(strMapToObj(jsonStr));
}
const myMap = new Map();
myMap.set("bar", "foo")
.set(1, "ooo");
strMapToJson(myMap); // "{"1":"ooo","bar":"foo"}"

// Map 的鍵名為非字符串
function mapToArrayJson(map) {
  return JSON.stringify([...map]);
}
mapToArrayJson(myMap); // "[["bar","foo"],[1,"ooo"]]"

// Json 轉(zhuǎn) Map
// 正常情況下所有鍵名都為字符串
function jsonToStrMap(jsonStr) {
  return objToStrMap(JSON.parse(jsonStr));
}
jsonToStrMap("{"1":"ooo","bar":"foo"}"); // Map {"1" => "ooo", "bar" => "foo"}

// 整個JSON 是數(shù)組
function jsonToMap(jsronStr) {
  return new Map(JSON.parse(jsronStr)); 
}
jsonToMap([["bar","foo"],[1,"ooo"]]); // Map {"1" => "ooo", "bar" => "foo"}

WeakMap

含義

WeakMap 結(jié)構(gòu)與 Map結(jié)構(gòu)類似幕垦,也是用于生成鍵值對的集合丢氢。

與 Map 區(qū)別

(1)WeakMap 只接受對象作為鍵名(null 除外),不接受其他類型的值作為鍵名先改。
(2)WeakMap 的鍵名所指向的對象不計入垃圾回收機制疚察。
(3)沒有keys()、values()仇奶、entries() 遍歷操作貌嫡。
(4)沒有size 屬性。
(5)不支持clear() 方法该溯。
WeakMap 應(yīng)用的典型場合就是 DOM 節(jié)點作為鍵名岛抄。下面是一個例子。

let myElement = document.getElementById('logo');
let myWeakmap = new WeakMap();

myWeakmap.set(myElement, {timesClicked: 0});

myElement.addEventListener('click', function() {
  let logoData = myWeakmap.get(myElement);
  logoData.timesClicked++;
}, false);

上面代碼中狈茉,myElement是一個 DOM 節(jié)點夫椭,每當發(fā)生click事件,就更新一下狀態(tài)氯庆。我們將這個狀態(tài)作為鍵值放在 WeakMap 里蹭秋,對應(yīng)的鍵名就是myElement扰付。一旦這個 DOM 節(jié)點刪除,該狀態(tài)就會自動消失感凤,不存在內(nèi)存泄漏風險。

靜態(tài)方法(from粒督,of)

Array.from方法用于將兩類對象轉(zhuǎn)為真正的數(shù)組:類似數(shù)組的對象(array-like object)和可遍歷(iterable)的對象(包括 ES6 新增的數(shù)據(jù)結(jié)構(gòu) Set 和 Map)陪竿。

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

// ES5的寫法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的寫法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

//Set
let newArray=new Set(['a','b','c'])
let arr3=Array.from(newArray) //['a','b','c']

Array.to方法是用于將一組值,轉(zhuǎn)換為數(shù)組屠橄。和Array()的用途相似,但是這個方法的主要目的族跛,是彌補數(shù)組構(gòu)造函數(shù)Array()的不足。因為參數(shù)個數(shù)的不同锐墙,會導致Array()的行為有差異礁哄。

Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]

Array.of() // []
Array.of(1) // [1]
Array.of(3,11,8) // [1, 2]

上面代碼中,Array方法沒有參數(shù)溪北、一個參數(shù)桐绒、三個參數(shù)時,返回結(jié)果都不一樣之拨。只有當參數(shù)個數(shù)不少于 2 個時茉继,Array()才會返回由參數(shù)組成的新數(shù)組。參數(shù)個數(shù)只有一個時蚀乔,實際上是指定數(shù)組的長度烁竭。
Array.of基本上可以用來替代Array()或new Array(),并且不存在由于參數(shù)不同而導致的重載吉挣。它的行為非常統(tǒng)一派撕。Array.of總是返回參數(shù)值組成的數(shù)組。如果沒有參數(shù)睬魂,就返回一個空數(shù)組终吼。

數(shù)組的空值

數(shù)組的空位指,數(shù)組的某一個位置沒有任何值氯哮。比如衔峰,Array構(gòu)造函數(shù)返回的數(shù)組都是空位。注意蛙粘,空位不是undefined垫卤,一個位置的值等于undefined,依然是有值的出牧⊙ㄖ猓空位是沒有任何值

ES5 對空位的處理,已經(jīng)很不一致了舔痕,大多數(shù)情況下會忽略空位评抚。

forEach(), filter(), reduce(), every() 和some()都會跳過空位豹缀。
map()會跳過空位,但會保留這個值
join()和toString()會將空位視為undefined慨代,而undefined和null會被處理成空字符串邢笙。

// forEach方法
[,'a'].forEach((x,i) => console.log(i)); // 1

// filter方法
['a',,'b'].filter(x => true) // ['a','b']

// every方法
[,'a'].every(x => x==='a') // true

// reduce方法
[1,,2].reduce((x,y) => x+y) // 3

// some方法
[,'a'].some(x => x !== 'a') // false

// map方法
[,'a'].map(x => 1) // [,1]

// join方法
[,'a',undefined,null].join('#') // "#a##"

// toString方法
[,'a',undefined,null].toString() // ",a,,"

ES6中則是明確的將空處理成了undefined,由于空位的處理規(guī)則非常不統(tǒng)一,所以建議避免出現(xiàn)空位侍匙。
Array.from方法會將數(shù)組的空位氮惯,轉(zhuǎn)為undefined,也就是說想暗,這個方法不會忽略空位妇汗。

Array.from(['a',,'b'])
// [ "a", undefined, "b" ]

擴展運算符(...)也會將空位轉(zhuǎn)為undefined。

[...['a',,'b']]
// [ "a", undefined, "b" ]
copyWithin()會連空位一起拷貝说莫。

[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]
fill()會將空位視為正常的數(shù)組位置杨箭。

new Array(3).fill('a') // ["a","a","a"]
for...of循環(huán)也會遍歷空位。

let arr = [, ,];
for (let i of arr) {
  console.log(1);
}
// 1
// 1

問題 :
1.不太了解靜態(tài)方法和實例方法的區(qū)別
2.對promise概念有點模糊储狭,async 的使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末互婿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子辽狈,更是在濱河造成了極大的恐慌擒悬,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稻艰,死亡現(xiàn)場離奇詭異懂牧,居然都是意外死亡,警方通過查閱死者的電腦和手機尊勿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門僧凤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人元扔,你說我怎么就攤上這事躯保。” “怎么了澎语?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵途事,是天一觀的道長。 經(jīng)常有香客問我擅羞,道長尸变,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任减俏,我火速辦了婚禮召烂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘娃承。我一直安慰自己奏夫,他們只是感情好怕篷,可當我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酗昼,像睡著了一般廊谓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上麻削,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天蒸痹,我揣著相機與錄音,去河邊找鬼碟婆。 笑死电抚,一個胖子當著我的面吹牛惕稻,可吹牛的內(nèi)容都是我干的竖共。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼俺祠,長吁一口氣:“原來是場噩夢啊……” “哼公给!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜘渣,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤淌铐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蔫缸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腿准,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年拾碌,在試婚紗的時候發(fā)現(xiàn)自己被綠了吐葱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡校翔,死狀恐怖弟跑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情防症,我是刑警寧澤孟辑,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站蔫敲,受9級特大地震影響饲嗽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奈嘿,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一喝噪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧指么,春花似錦酝惧、人聲如沸榴鼎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巫财。三九已至,卻和暖如春哩陕,著一層夾襖步出監(jiān)牢的瞬間平项,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工悍及, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留闽瓢,地道東北人。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓心赶,卻偏偏與公主長得像扣讼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子缨叫,可洞房花燭夜當晚...
    茶點故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容