《ES6標(biāo)準(zhǔn)入門——阮一峰》總結(jié)

這是筆者讀完阮一峰的《ES6標(biāo)準(zhǔn)入門》的總結(jié),可稱為《ES6標(biāo)準(zhǔn)入門的入門》,總結(jié)的知識點(diǎn)都比較通俗易懂,可為想大概了解ES6但沒有時(shí)間閱讀全書的人做一個(gè)參考。

1.let 和 const

暫時(shí)性死區(qū) (Temporal Dead Zone)

letconst命令聲明的變量無變量提升,且都會(huì)被鎖定在聲明的代碼塊中,在letconst命令執(zhí)行前,使用該變量都將報(bào)錯(cuò),這一部分稱為“暫時(shí)性死區(qū)”。

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

let tmptmp變量綁定至{}代碼塊之內(nèi),外部的tmp聲明無效,tmp = 'abc'就處在死區(qū),所以報(bào)錯(cuò)。同理在以前沒有letconst命令的時(shí)候,typeof是一個(gè)安全的運(yùn)算符,即使變量沒有被聲明,也會(huì)正常返回undefined,但如果typeof處在死區(qū)中,處理了在后文被letconst的變量,將會(huì)報(bào)錯(cuò)。

typeof undeclared_variable; // undefined 未被let和const聲明反而沒事
if (true) {
  // TDZ開始 (Temporal Dead Zone: 暫時(shí)性死區(qū))
  typeof tmp // ReferenceError
  let tmp; // TDZ結(jié)束
  console.log(tmp); // undefined
}
頂層對象

varfunction的全局聲明會(huì)自動(dòng)綁定到windowglobal對象,這是ES5全局變量的一個(gè)缺陷letconst不會(huì)。

var a = 1;
// 如果在 Node 的 REPL 環(huán)境,可以寫成 global.a
// 或者采用通用方法,寫成 this.a
window.a // 1

let b = 1;
window.b // undefined
const命令

const聲明的變量只是引用無法修改,對象的內(nèi)部結(jié)構(gòu)可以改變,使用Object.freeze()可以徹底鎖定某對象,需遞歸鎖定多層級對象。

var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, i) => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};

2.變量的解構(gòu)賦值

解構(gòu)時(shí)分為匹配模式和被賦值的變量,若相同可簡寫,注意區(qū)分
// 被解構(gòu)的對象的key,和后邊被賦值的變量同名,可以簡寫。
let { matchValue } = { matchValue: 123 };
console.log(matchValue); //123

等價(jià)于

let { matchValue: matchValue } = { matchValue: 123 }
console.log(matchValue); //123

通過代碼的高亮可以看出相互之間的對應(yīng)關(guān)系。所以

let { matchValue: value } = { matchValue: 123 }
console.log(matchValue); //報(bào)錯(cuò),未定義,這個(gè)只是匹配模式,不會(huì)被賦值
console.log(value); //123
函數(shù)參數(shù)

首先解構(gòu)賦值允許指定默認(rèn)值,這為函數(shù)參數(shù)設(shè)置默認(rèn)值提供基礎(chǔ)。

// 數(shù)組解構(gòu)賦值的默認(rèn)值
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x = 'a', y = 'b'] = ['aa', undefined]; // x='aa', y='b'

// 對象解構(gòu)賦值的默認(rèn)值
let {x, y = 5} = {x: 1};
x // 1
y // 5

這里只討論一下參數(shù)為Object類型時(shí),該如何設(shè)置默認(rèn)值,比如一些options的設(shè)置,通過設(shè)置默認(rèn)值,可有效避免var foo = options.foo || 'default foo';。有三種形式,注意這三種的區(qū)別:

const ajax1 = function (url, { type = 'GET', dataType = 'json'} = {}) {
  // TODO
}
const ajax2 = function (url, {} = { type = 'GET', dataType = 'json' }) {
  // TODO
}
const ajax3 = function (url, { type = 'GET', dataType = 'json'} ) {
  // TODO
}

ajax1的默認(rèn)參數(shù)表示,如果沒有傳入options,則用一個(gè)沒有鍵值對的對象{}作為默認(rèn)值,但也正是因此,傳入的options沒有options.typeoptions.dataType這兩個(gè)屬性,則賦予默認(rèn)值type = 'GET', dataType = 'json',這是針對鍵值對某一個(gè)key設(shè)默認(rèn)值。

ajax2的默認(rèn)參數(shù)表示,如果沒有傳入options對象,則用一個(gè){ type = 'GET', dataType = 'json' }這樣的options對象作為默認(rèn)值,這是針對這一整個(gè)options設(shè)默認(rèn)值。弊端就是如果開發(fā)者在使用時(shí)這樣寫

ajax2(url, {type = 'POST'})

那么dataType參數(shù)將要丟失,因?yàn)?code>{type = 'POST'}代替了默認(rèn)參數(shù){ type = 'GET', dataType = 'json' },所以一般通過形如ajax1的方式定義默認(rèn)參數(shù)。

ajax3的默認(rèn)參數(shù)有一個(gè)問題,就是當(dāng)沒有傳入options的時(shí)候,相當(dāng)于從undefined中取值typedataType來解構(gòu),所以會(huì)報(bào)錯(cuò),所以ajax1會(huì)通過= {}的方式,把不傳入options的情況過濾掉。

3.各種數(shù)據(jù)結(jié)構(gòu)的擴(kuò)展

字符串

``表示模板字符串,就不多介紹了,功能強(qiáng)大好用。
--------------------
codePointAt可作為charCodeAt的替代品,必要時(shí)使用for...of遍歷字符串,他們都是為了處理32 位的 UTF-16 字符。

var s = "??a";
s.length // 3  無法正確識別字符串長度,會(huì)把‘??’識別為2個(gè)字符
s.charAt(0) // '' charAt無法處理這個(gè)字
s.charAt(1) // ''
s.charCodeAt(0) // 55362 charCodeAt只能兩字節(jié)兩字節(jié)的分開返回
s.charCodeAt(1) // 57271

下面看一下ES6的codePointAtfor...of

let s = '??a';
s.codePointAt(0) // 134071 可以識別一整個(gè)字
s.codePointAt(1) // 57271 第三,四字節(jié)會(huì)被返回
s.codePointAt(2) // 97 字符串長度仍有問題
// 使用for...of循環(huán)正確處理
for (let ch of s) {
  console.log(ch.codePointAt(0).toString(16));
}
// 20bb7 134071是10進(jìn)制,20bb7為16進(jìn)制表示
// 61 字符串長度也沒問題,循環(huán)執(zhí)行了2次

--------------------
還引入了includesstartWithendWithpadStartpadEnd等方法,具體使用方法可以通過API手冊了解一下。

Number

parseInt等全局方法掛在到Number上,如Number.parseIntNumber.parseFloat等,增加了一些高階計(jì)算函數(shù)。

函數(shù)

箭頭函數(shù),this的指向在函數(shù)生成時(shí)固定,說白了就是this指向與外部一致。
--------------------
函數(shù)參數(shù)設(shè)置默認(rèn)值,前文已經(jīng)說明。補(bǔ)充一點(diǎn),設(shè)置某參數(shù)必須可以:

function throwNeedThisParamException(param) {
  throw new Error(`Missing parameter: ${param}`);
}
function demo (x = throwNeedThisParamException('x')) {

}

參數(shù)的默認(rèn)值是在取不到值的情況下才會(huì)執(zhí)行,所以正常情況不會(huì)拋出這個(gè)錯(cuò)誤。
--------------------
參數(shù)的rest形式,例子如下:

function demo (...values) {
  console.log(values)
  console.log('-----------------------')
  console.log(arguments)
}
demo(1,2,3,4)   
//[1,2,3,4]  
-----------------------
//[1, 2, 3, 4, callee: (...), Symbol(Symbol.iterator): ?]

內(nèi)置的arguments為類數(shù)組結(jié)構(gòu),可以看見有一個(gè)Symbol類型的字段Symbol.iterator,這是它的迭代器,使其可以向數(shù)組一樣遍歷。但如果展開看其__proto__,值為Object。而使用rest形式的參數(shù),可以直接將參數(shù)轉(zhuǎn)為數(shù)組。注意rest形式的參數(shù)只能用作最后一個(gè)參數(shù)。
--------------------
函數(shù)的length屬性返回函數(shù)參數(shù)的個(gè)數(shù),name屬性返回聲明的函數(shù)名稱,ES6的變量式聲明返回變量名。

function f1 () {}
f1.name // f1
const f2 = function (x,y) {}
f2.name // f2
f2.length // 2

--------------------
雙冒號運(yùn)算符,代替bindcallapply綁定this對象指向。foo::bar(arguments)相當(dāng)于bar.apply(foo, arguments)
--------------------
尾調(diào)用,說白了就是最后返回值為執(zhí)行另一個(gè)函數(shù)return anotherFunction(),而return anotherFunction() + 1不屬于尾調(diào)用,因?yàn)樵趫?zhí)行完anotherFunction后還需要+1。尾調(diào)用的優(yōu)勢就是在return后,可以釋放當(dāng)前函數(shù)執(zhí)行所需要的一切資源空間。對比如下兩個(gè)例子,是做斐波那契數(shù)列求值的:

function Fibonacci (n) {
  if ( n <= 1 ) {return 1};

  return Fibonacci(n - 1) + Fibonacci(n - 2);
}
Fibonacci(10) // 89
Fibonacci(100) // 堆棧溢出
Fibonacci(500) // 堆棧溢出

這是最簡單的寫法,清晰明了,第n項(xiàng)就是前兩項(xiàng)的和。但是,為了計(jì)算加號兩邊的值,必須要保存函數(shù)執(zhí)行的全部資源,遞歸后造成堆棧溢出。這不屬于尾調(diào)用。

function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
  if( n <= 1 ) {return ac2};
  return Fibonacci2 (n - 1, ac2, ac1 + ac2);
}
Fibonacci2(100) // 573147844013817200000
Fibonacci2(1000) // 7.0330367711422765e+208
Fibonacci2(10000) // Infinity

這是優(yōu)化過的遞歸調(diào)用,return之后無需保存函數(shù)所需要的資源,所以不會(huì)堆棧溢出,只是在邏輯上不好理解。這種寫法Fibonacci2 (n - 1, ac2, ac1 + ac2)可以看成一個(gè)從前到后推導(dǎo)過程,n相當(dāng)于一個(gè)計(jì)數(shù)器,每次值的增長是通過兩個(gè)數(shù)求和ac1 + ac2作為第二個(gè)數(shù),ac2作為第一個(gè)數(shù)。

數(shù)組

擴(kuò)展運(yùn)算符...,與上文的rest參數(shù)是相反的用法,rest參數(shù)是把一個(gè)個(gè)的參數(shù)總和到數(shù)組rest參數(shù)中,而擴(kuò)展運(yùn)算符是把數(shù)組中的元素一個(gè)個(gè)提取出來。
擴(kuò)展運(yùn)算符可以用來方便的復(fù)制一個(gè)數(shù)組。

let arr = [1,2,3]
console.log(...arr)  // 等價(jià)于console.log(1,2,3)
let arr2 = [...arr] // 等價(jià)于let arr2 = [1,2,3],新建一個(gè)數(shù)組
arr.push(4)
console.log(arr2) // [1,2,3]

--------------------
數(shù)組可以通過Array.fromArray.of生成,可以通過keys()values()entries()遍歷。
Array.from可以從具有iterator的數(shù)據(jù)結(jié)構(gòu)生成數(shù)組,比如arguments對象,document.querySelectorAll()獲得的DOM對象,這些都是類數(shù)組,或者MapSet等新增的數(shù)據(jù)結(jié)構(gòu)。
Array.of可以代替new Array(),因?yàn)?code>new Array()的參數(shù)與行為不統(tǒng)一,當(dāng)傳入一個(gè)參數(shù)且為數(shù)字時(shí),表示數(shù)組長度,Array.of不會(huì)有這個(gè)問題,會(huì)通過參數(shù)創(chuàng)建數(shù)組。
Array還新增了一些工具方法,如findfindIndexincludes等可以參考其他API手冊。

對象

Object.assign是合并對象,把多個(gè)對象合并到第一個(gè)對象上。
Object.create是以某原型,生成一個(gè)新對象。可選第二個(gè)參數(shù),為屬性描述符,使用方式參見下方代碼。
Object.getPrototypeOfObject.setPrototypeOf是獲取和設(shè)置對象的原型屬性__proto__,不應(yīng)顯式使用__proto__這個(gè)屬性。
Object.getOwnPropertyDescriptors是獲取對象的屬性信息,包括valuewritableenumerableconfigurable

const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
-------------------
Object.setPrototypeOf(target, { myProto: 'PROTO'})
Object.getPrototypeOf(target) //{ myProto: 'PROTO', __proto__: Object}
let newObj = Object.create(Object.getPrototypeOf(target))
newObj // 無顯式屬性{ __proto__:{ myProto: 'PROTO', __proto__: Object} } 
-------------------
const descriptors = Object.getOwnPropertyDescriptors(target)
console.log(descriptors)
// {
//   a: {value: 1, writable: true, enumerable: true, configurable: true},
//   b: {value: 2, writable: true, enumerable: true, configurable: true},
//   c: {value: 3, writable: true, enumerable: true, configurable: true}
// }
newObj = Object.create(Object.getPrototypeOf(target), descriptors)
newObj // { a:1, b:2, c:3, __proto__:{ myProto: 'PROTO', __proto__: Object} } 

--------------------
ES6允許字面量定義對象時(shí),用表達(dá)式作為屬性名,把表達(dá)式放在方括號內(nèi)。

const propKey = 'foo';

const obj = {
  [propKey]: true,
  ['a' + 'bc']: 123
};
obj // { foo: true, abc: 123 }

--------------------
Object.is優(yōu)化了===運(yùn)算符,處理了===的兩個(gè)問題。

NaN === NaN // false
Object.is(NaN, NaN) // true
--------------
+0 === -0 // true 
Object.is(+0, -0) // false

4.Symbol

Symbol為不會(huì)重復(fù)的值,第七種基本數(shù)據(jù)類型,類似字符串,可以作為對象的key,但不會(huì)被for...offor...inObject.getOwnPropertyNames()Object.keys()返回,如需要遍歷,需使用Object.getOwnPropertySymbols(),或者Reflect.ownKeys()返回全部key

let foo = Symbol('foo');
const obj = { [foo]: 'foobar' }
for (let i in obj) {
  console.log(i); // 無輸出
}
Object.getOwnPropertyNames(obj)
// []
Object.getOwnPropertySymbols(obj)
// [Symbol(foo)]
Reflect.ownKeys(obj)
// [Symbol(foo)]

Symbol.for() 和 Symbol.keyFor()

Symbol可以去確保生成的值不同,但有時(shí)需要保存下來以便再次使用,類似于單例,如果存在就不會(huì)重新創(chuàng)建。這個(gè)時(shí)候就需要使用Symbol.for()

let s1 = Symbol('foo');
let s2 = Symbol.for('foo');
let s3 = Symbol.for('foo');
s1 === s2 // false
s2 === s3 // true

從上例可以看出,Symbol.for類似于將這個(gè)Symbol登記,所以s1這個(gè)未登記的Symbol不會(huì)等于其他Symbol
Symbol.keyFor會(huì)返回已登記的Symbolkey,一定是登記過的才會(huì)返回。接上例:

Symbol.keyFor(s1) // undefiend
Symbol.keyFor(s2) // "foo"

5.Proxy和Reflect

Proxy代理對象的各種內(nèi)置方法,get set construct等,類似于攔截器。
Reflect則作為Object的替代者,Object上的一些靜態(tài)方法被移植到了Reflect上。
Reflect對象一共有 13 個(gè)靜態(tài)方法。

  • Reflect.apply(target, thisArg, args)
  • Reflect.construct(target, args)
  • Reflect.get(target, name, receiver)
  • Reflect.set(target, name, value, receiver)
  • Reflect.defineProperty(target, name, desc)
  • Reflect.deleteProperty(target, name)
  • Reflect.has(target, name)
  • Reflect.ownKeys(target)
  • Reflect.isExtensible(target)
  • Reflect.preventExtensions(target)
  • Reflect.getOwnPropertyDescriptor(target, name)
  • Reflect.getPrototypeOf(target)
  • Reflect.setPrototypeOf(target, prototype)
    通過ProxyReflect可以實(shí)現(xiàn)觀察者模式,說白了就是:監(jiān)聽set方法,執(zhí)行相應(yīng)操作。
const person = { name: 'Li', age: 18}
const personObserved = observe(person)

function observe(obj) {
  return new Proxy(obj, {
    set: function (target, key, value, receiver) {
      console.log(`setting ${key} to ${value}!`);
      return Reflect.set(target, key, value, receiver);
    }
  })
}

personObserved.name = 'zhang'
// setting name to zhang!

6.Promise

Promise用來處理異步操作,是構(gòu)造函數(shù),參數(shù)為thencatch后需要執(zhí)行的方法。下面是使用Promise封裝的ajax

const getJSON = function(url) {
  const promise = new Promise((resolve, reject) => {
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();
  });
  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出錯(cuò)了', error);
});

7. Iterator 和 for...of循環(huán)

Iterator被掛載在對象的Symbol.iterator屬性下,Symbol.iterator不是一個(gè)Iterator,而是會(huì)返回Iterator的函數(shù)。

const arr = [1,2,3,4,5]
let iterator = arr[Symbol.iterator]();
iterator // Array Iterator {}
iterator.next() // {value: 1, done: false}
......
iterator.next() // {value: 5, done: false}
iterator.next() // {value: undefined, done: true}

8. Generator 和 yield

Generator會(huì)生成一個(gè)Iterator,每次iterator.next()返回yield的產(chǎn)出值,且中斷程序執(zhí)行。yield*表示產(chǎn)出的值是另外一個(gè)generator的結(jié)果。代碼如下:

function* demo(){
  console.log(`${yield 1}`);
  console.log(`${yield 2}`);
  yield* demo2(); //返回另一個(gè)generator的結(jié)果
}
function* demo2(){
  yield 3;
}
let ite = demo();
ite.next() // 返回值:{value: 1, done: false}
ite.next() // console:undefined, 返回值:{value: 2, done: false}
ite.next(123456789) // console: 123456789, 返回值:{value: 3, done: false} 

解釋一下運(yùn)行結(jié)果:第一次ite.next()時(shí),程序執(zhí)行到yield 1被終止,故沒有打印日志,再次執(zhí)行ite.next()時(shí),代碼繼續(xù),開始執(zhí)行console.log(`${yield 1}`);,但輸出不是1而是undefiend,因?yàn)?code>ite.next()的參數(shù)值會(huì)被當(dāng)做上次yield語句的執(zhí)行結(jié)果,所以下面的ite.next(123456789)會(huì)輸出數(shù)字123456789

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,802評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,762評論 2 372

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

  • 聽歌的時(shí)候,我都會(huì)去關(guān)注一下歌詞,這里收集了一些自己特別喜歡并且覺得寫入心里去的。缺少了歌詞,或許再好的曲調(diào)也只會(huì)...
    挑兮達(dá)兮閱讀 640評論 0 2
  • 年少時(shí)我們有足夠多的理由去認(rèn)認(rèn)真真地喜歡另一個(gè)人,而長大后我們有同樣多的理由去認(rèn)認(rèn)真真地辜負(fù)另一個(gè)人。所以最初...
    Silvia15閱讀 756評論 3 2