ES6中字符串的擴展

本篇介紹 ES6 對字符串的改造和增強,下一章介紹字符串對象的新增方法儡司。

字符的 Unicode 表示法

ES6 加強了對 Unicode 的支持旨椒,允許采用\uxxxx形式表示一個字符壳鹤,其中xxxx表示字符的 Unicode 碼點。

"\u0061"
// "a"

但是航缀,這種表示法只限于碼點在\u0000~\uFFFF之間的字符。超出這個范圍的字符堰怨,必須用兩個雙字節(jié)的形式表示芥玉。

"\uD842\uDFB7"
// "??"

"\u20BB7"
// " 7"

上面代碼表示,如果直接在\u后面跟上超過0xFFFF的數(shù)值(比如\u20BB7)备图,JavaScript 會理解成\u20BB+7灿巧。由于\u20BB是一個不可打印字符,所以只會顯示一個空格揽涮,后面跟著一個7抠藕。

ES6 對這一點做出了改進,只要將碼點放入大括號蒋困,就能正確解讀該字符盾似。

"\u{20BB7}"
// "??"

"\u{41}\u{42}\u{43}"
// "ABC"

let hello = 123;
hell\u{6F} // 123

'\u{1F680}' === '\uD83D\uDE80'
// true

上面代碼中,最后一個例子表明雪标,大括號表示法與四字節(jié)的 UTF-16 編碼是等價的零院。

有了這種表示法之后,JavaScript 共有 6 種方法可以表示一個字符村刨。

'\z' === 'z'  // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true

字符串的遍歷器接口

ES6 為字符串添加了遍歷器接口(詳見《Iterator》一章)告抄,使得字符串可以被for...of循環(huán)遍歷。

for (let codePoint of 'foo') {
  console.log(codePoint)
}
// "f"
// "o"
// "o"

除了遍歷字符串烹困,這個遍歷器最大的優(yōu)點是可以識別大于0xFFFF的碼點玄妈,傳統(tǒng)的for循環(huán)無法識別這樣的碼點。

let text = String.fromCodePoint(0x20BB7);

for (let i = 0; i < text.length; i++) {
  console.log(text[i]);
}
// " "
// " "

for (let i of text) {
  console.log(i);
}
// "??"

上面代碼中,字符串text只有一個字符拟蜻,但是for循環(huán)會認為它包含兩個字符(都不可打右锴),而for...of循環(huán)會正確識別出這一個字符酝锅。

直接輸入 U+2028 和 U+2029

JavaScript 字符串允許直接輸入字符诡必,以及輸入字符的轉(zhuǎn)義形式。舉例來說搔扁,“中”的 Unicode 碼點是 U+4e2d爸舒,你可以直接在字符串里面輸入這個漢字,也可以輸入它的轉(zhuǎn)義形式\u4e2d稿蹲,兩者是等價的扭勉。

'中' === '\u4e2d' // true

但是,JavaScript 規(guī)定有5個字符苛聘,不能在字符串里面直接使用涂炎,只能使用轉(zhuǎn)義形式。

  • U+005C:反斜杠(reverse solidus)
  • U+000D:回車(carriage return)
  • U+2028:行分隔符(line separator)
  • U+2029:段分隔符(paragraph separator)
  • U+000A:換行符(line feed)

舉例來說设哗,字符串里面不能直接包含反斜杠唱捣,一定要轉(zhuǎn)義寫成\\或者\u005c

這個規(guī)定本身沒有問題网梢,麻煩在于 JSON 格式允許字符串里面直接使用 U+2028(行分隔符)和 U+2029(段分隔符)震缭。這樣一來,服務器輸出的 JSON 被JSON.parse解析战虏,就有可能直接報錯拣宰。

const json = '"\u2028"';
JSON.parse(json); // 可能報錯

JSON 格式已經(jīng)凍結(jié)(RFC 7159),沒法修改了活烙。為了消除這個報錯徐裸,ES2019 允許 JavaScript 字符串直接輸入 U+2028(行分隔符)和 U+2029(段分隔符)。

const PS = eval("'\u2029'");

根據(jù)這個提案啸盏,上面的代碼不會報錯重贺。

注意,模板字符串現(xiàn)在就允許直接輸入這兩個字符回懦。另外气笙,正則表達式依然不允許直接輸入這兩個字符,這是沒有問題的怯晕,因為 JSON 本來就不允許直接包含正則表達式潜圃。

JSON.stringify() 的改造

根據(jù)標準,JSON 數(shù)據(jù)必須是 UTF-8 編碼舟茶。但是谭期,現(xiàn)在的JSON.stringify()方法有可能返回不符合 UTF-8 標準的字符串堵第。

具體來說,UTF-8 標準規(guī)定隧出,0xD8000xDFFF之間的碼點踏志,不能單獨使用,必須配對使用胀瞪。比如针余,\uD834\uDF06是兩個碼點,但是必須放在一起配對使用凄诞,代表字符??圆雁。這是為了表示碼點大于0xFFFF的字符的一種變通方法。單獨使用\uD834\uDFO6這兩個碼點是不合法的帆谍,或者顛倒順序也不行伪朽,因為\uDF06\uD834并沒有對應的字符。

JSON.stringify()的問題在于既忆,它可能返回0xD8000xDFFF之間的單個碼點驱负。

JSON.stringify('\u{D834}') // "\u{D834}"

為了確保返回的是合法的 UTF-8 字符,ES2019 改變了JSON.stringify()的行為患雇。如果遇到0xD8000xDFFF之間的單個碼點,或者不存在的配對形式宇挫,它會返回轉(zhuǎn)義字符串苛吱,留給應用自己決定下一步的處理。

JSON.stringify('\u{D834}') // ""\\uD834""
JSON.stringify('\uDF06\uD834') // ""\\udf06\\ud834""

模板字符串

傳統(tǒng)的 JavaScript 語言器瘪,輸出模板通常是這樣寫的(下面使用了 jQuery 的方法)翠储。

$('#result').append(
  'There are <b>' + basket.count + '</b> ' +
  'items in your basket, ' +
  '<em>' + basket.onSale +
  '</em> are on sale!'
);

上面這種寫法相當繁瑣不方便,ES6 引入了模板字符串解決這個問題橡疼。

$('#result').append(`
  There are <b>${basket.count}</b> items
   in your basket, <em>${basket.onSale}</em>
  are on sale!
`);

模板字符串(template string)是增強版的字符串援所,用反引號(`)標識。它可以當作普通字符串使用欣除,也可以用來定義多行字符串住拭,或者在字符串中嵌入變量。

// 普通字符串
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
 not legal.`

console.log(`string text line 1
string text line 2`);

// 字符串中嵌入變量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

上面代碼中的模板字符串历帚,都是用反引號表示滔岳。如果在模板字符串中需要使用反引號,則前面要用反斜杠轉(zhuǎn)義挽牢。

let greeting = `\`Yo\` World!`;

如果使用模板字符串表示多行字符串谱煤,所有的空格和縮進都會被保留在輸出之中。

$('#list').html(`
<ul>
  <li>first</li>
  <li>second</li>
</ul>
`);

上面代碼中禽拔,所有模板字符串的空格和換行刘离,都是被保留的室叉,比如<ul>標簽前面會有一個換行。如果你不想要這個換行硫惕,可以使用trim方法消除它茧痕。

$('#list').html(`
<ul>
  <li>first</li>
  <li>second</li>
</ul>
`.trim());

模板字符串中嵌入變量,需要將變量名寫在${}之中疲憋。

function authorize(user, action) {
  if (!user.hasPrivilege(action)) {
    throw new Error(
      // 傳統(tǒng)寫法為
      // 'User '
      // + user.name
      // + ' is not authorized to do '
      // + action
      // + '.'
      `User ${user.name} is not authorized to do ${action}.`);
  }
}

大括號內(nèi)部可以放入任意的 JavaScript 表達式凿渊,可以進行運算,以及引用對象屬性缚柳。

let x = 1;
let y = 2;

`${x} + ${y} = ${x + y}`
// "1 + 2 = 3"

`${x} + ${y * 2} = ${x + y * 2}`
// "1 + 4 = 5"

let obj = {x: 1, y: 2};
`${obj.x + obj.y}`
// "3"

模板字符串之中還能調(diào)用函數(shù)埃脏。

function fn() {
  return "Hello World";
}

`foo ${fn()} bar`
// foo Hello World bar

如果大括號中的值不是字符串,將按照一般的規(guī)則轉(zhuǎn)為字符串秋忙。比如彩掐,大括號中是一個對象,將默認調(diào)用對象的toString方法灰追。

如果模板字符串中的變量沒有聲明堵幽,將報錯。

// 變量place沒有聲明
let msg = `Hello, ${place}`;
// 報錯

由于模板字符串的大括號內(nèi)部弹澎,就是執(zhí)行 JavaScript 代碼朴下,因此如果大括號內(nèi)部是一個字符串,將會原樣輸出苦蒿。

`Hello ${'World'}`
// "Hello World"

模板字符串甚至還能嵌套殴胧。

const tmpl = addrs => `
  <table>
  ${addrs.map(addr => `
    <tr><td>${addr.first}</td></tr>
    <tr><td>${addr.last}</td></tr>
  `).join('')}
  </table>
`;

上面代碼中,模板字符串的變量之中佩迟,又嵌入了另一個模板字符串团滥,使用方法如下。

const data = [
    { first: '<Jane>', last: 'Bond' },
    { first: 'Lars', last: '<Croft>' },
];

console.log(tmpl(data));
// <table>
//
//   <tr><td><Jane></td></tr>
//   <tr><td>Bond</td></tr>
//
//   <tr><td>Lars</td></tr>
//   <tr><td><Croft></td></tr>
//
// </table>

如果需要引用模板字符串本身报强,在需要時執(zhí)行灸姊,可以寫成函數(shù)。

let func = (name) => `Hello ${name}!`;
func('Jack') // "Hello Jack!"

上面代碼中秉溉,模板字符串寫成了一個函數(shù)的返回值力惯。執(zhí)行這個函數(shù),就相當于執(zhí)行這個模板字符串了坚嗜。

實例:模板編譯

下面夯膀,我們來看一個通過模板字符串,生成正式模板的實例苍蔬。

let template = `
<ul>
  <% for(let i=0; i < data.supplies.length; i++) { %>
    <li><%= data.supplies[i] %></li>
  <% } %>
</ul>
`;

上面代碼在模板字符串之中诱建,放置了一個常規(guī)模板。該模板使用<%...%>放置 JavaScript 代碼碟绑,使用<%= ... %>輸出 JavaScript 表達式俺猿。

怎么編譯這個模板字符串呢茎匠?

一種思路是將其轉(zhuǎn)換為 JavaScript 表達式字符串。

echo('<ul>');
for(let i=0; i < data.supplies.length; i++) {
  echo('<li>');
  echo(data.supplies[i]);
  echo('</li>');
};
echo('</ul>');

這個轉(zhuǎn)換使用正則表達式就行了押袍。

let evalExpr = /<%=(.+?)%>/g;
let expr = /<%([\s\S]+?)%>/g;

template = template
  .replace(evalExpr, '`); \n  echo( $1 ); \n  echo(`')
  .replace(expr, '`); \n $1 \n  echo(`');

template = 'echo(`' + template + '`);';

然后诵冒,將template封裝在一個函數(shù)里面返回,就可以了谊惭。

let script =
`(function parse(data){
  let output = "";

  function echo(html){
    output += html;
  }

  ${ template }

  return output;
})`;

return script;

將上面的內(nèi)容拼裝成一個模板編譯函數(shù)compile汽馋。

function compile(template){
  const evalExpr = /<%=(.+?)%>/g;
  const expr = /<%([\s\S]+?)%>/g;

  template = template
    .replace(evalExpr, '`); \n  echo( $1 ); \n  echo(`')
    .replace(expr, '`); \n $1 \n  echo(`');

  template = 'echo(`' + template + '`);';

  let script =
  `(function parse(data){
    let output = "";

    function echo(html){
      output += html;
    }

    ${ template }

    return output;
  })`;

  return script;
}

compile函數(shù)的用法如下。

let parse = eval(compile(template));
div.innerHTML = parse({ supplies: [ "broom", "mop", "cleaner" ] });
//   <ul>
//     <li>broom</li>
//     <li>mop</li>
//     <li>cleaner</li>
//   </ul>

標簽模板

模板字符串的功能圈盔,不僅僅是上面這些豹芯。它可以緊跟在一個函數(shù)名后面,該函數(shù)將被調(diào)用來處理這個模板字符串驱敲。這被稱為“標簽模板”功能(tagged template)铁蹈。

alert`hello`
// 等同于
alert(['hello'])

標簽模板其實不是模板,而是函數(shù)調(diào)用的一種特殊形式众眨∥漳粒“標簽”指的就是函數(shù),緊跟在后面的模板字符串就是它的參數(shù)娩梨。

但是沿腰,如果模板字符里面有變量,就不是簡單的調(diào)用了狈定,而是會將模板字符串先處理成多個參數(shù)矫俺,再調(diào)用函數(shù)。

let a = 5;
let b = 10;

tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);

上面代碼中掸冤,模板字符串前面有一個標識名tag,它是一個函數(shù)友雳。整個表達式的返回值稿湿,就是tag函數(shù)處理模板字符串后的返回值。

函數(shù)tag依次會接收到多個參數(shù)押赊。

function tag(stringArr, value1, value2){
  // ...
}

// 等同于

function tag(stringArr, ...values){
  // ...
}

tag函數(shù)的第一個參數(shù)是一個數(shù)組饺藤,該數(shù)組的成員是模板字符串中那些沒有變量替換的部分,也就是說流礁,變量替換只發(fā)生在數(shù)組的第一個成員與第二個成員之間涕俗、第二個成員與第三個成員之間,以此類推神帅。

tag函數(shù)的其他參數(shù)再姑,都是模板字符串各個變量被替換后的值。由于本例中找御,模板字符串含有兩個變量元镀,因此tag會接受到value1value2兩個參數(shù)绍填。

tag函數(shù)所有參數(shù)的實際值如下。

  • 第一個參數(shù):['Hello ', ' world ', '']
  • 第二個參數(shù): 15
  • 第三個參數(shù):50

也就是說栖疑,tag函數(shù)實際上以下面的形式調(diào)用讨永。

tag(['Hello ', ' world ', ''], 15, 50)

我們可以按照需要編寫tag函數(shù)的代碼。下面是tag函數(shù)的一種寫法遇革,以及運行結(jié)果卿闹。

let a = 5;
let b = 10;

function tag(s, v1, v2) {
  console.log(s[0]);
  console.log(s[1]);
  console.log(s[2]);
  console.log(v1);
  console.log(v2);

  return "OK";
}

tag`Hello ${ a + b } world ${ a * b}`;
// "Hello "
// " world "
// ""
// 15
// 50
// "OK"

下面是一個更復雜的例子。

let total = 30;
let msg = passthru`The total is ${total} (${total*1.05} with tax)`;

function passthru(literals) {
  let result = '';
  let i = 0;

  while (i < literals.length) {
    result += literals[i++];
    if (i < arguments.length) {
      result += arguments[i];
    }
  }

  return result;
}

msg // "The total is 30 (31.5 with tax)"

上面這個例子展示了萝快,如何將各個參數(shù)按照原來的位置拼合回去锻霎。

passthru函數(shù)采用 rest 參數(shù)的寫法如下。

function passthru(literals, ...values) {
  let output = "";
  let index;
  for (index = 0; index < values.length; index++) {
    output += literals[index] + values[index];
  }

  output += literals[index]
  return output;
}

“標簽模板”的一個重要應用杠巡,就是過濾 HTML 字符串量窘,防止用戶輸入惡意內(nèi)容。

let message =
  SaferHTML`<p>${sender} has sent you a message.</p>`;

function SaferHTML(templateData) {
  let s = templateData[0];
  for (let i = 1; i < arguments.length; i++) {
    let arg = String(arguments[i]);

    // Escape special characters in the substitution.
    s += arg.replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");

    // Don't escape special characters in the template.
    s += templateData[i];
  }
  return s;
}

上面代碼中氢拥,sender變量往往是用戶提供的蚌铜,經(jīng)過SaferHTML函數(shù)處理,里面的特殊字符都會被轉(zhuǎn)義嫩海。

let sender = '<script>alert("abc")</script>'; // 惡意代碼
let message = SaferHTML`<p>${sender} has sent you a message.</p>`;

message
// <p>&lt;script&gt;alert("abc")&lt;/script&gt; has sent you a message.</p>

標簽模板的另一個應用冬殃,就是多語言轉(zhuǎn)換(國際化處理)。

i18n`Welcome to ${siteName}, you are visitor number ${visitorNumber}!`
// "歡迎訪問xxx叁怪,您是第xxxx位訪問者审葬!"

模板字符串本身并不能取代 Mustache 之類的模板庫,因為沒有條件判斷和循環(huán)處理功能奕谭,但是通過標簽函數(shù)涣觉,你可以自己添加這些功能。

// 下面的hashTemplate函數(shù)
// 是一個自定義的模板處理函數(shù)
let libraryHtml = hashTemplate`
  <ul>
    #for book in ${myBooks}
      <li><i>#{book.title}</i> by #{book.author}</li>
    #end
  </ul>
`;

除此之外血柳,你甚至可以使用標簽模板官册,在 JavaScript 語言之中嵌入其他語言淫茵。

jsx`
  <div>
    <input
      ref='input'
      onChange='${this.handleChange}'
      defaultValue='${this.state.value}' />
      ${this.state.value}
   </div>
`

上面的代碼通過jsx函數(shù)仍侥,將一個 DOM 字符串轉(zhuǎn)為 React 對象娱颊。你可以在 GitHub 找到jsx函數(shù)的具體實現(xiàn)馍忽。

下面則是一個假想的例子谅猾,通過java函數(shù)锤岸,在 JavaScript 代碼之中運行 Java 代碼茁计。

java`
class HelloWorldApp {
  public static void main(String[] args) {
    System.out.println("Hello World!"); // Display the string.
  }
}
`
HelloWorldApp.main();

模板處理函數(shù)的第一個參數(shù)(模板字符串數(shù)組)怀骤,還有一個raw屬性击敌。

console.log`123`
// ["123", raw: Array[1]]

上面代碼中介返,console.log接受的參數(shù),實際上是一個數(shù)組愚争。該數(shù)組有一個raw屬性映皆,保存的是轉(zhuǎn)義后的原字符串挤聘。

請看下面的例子。

tag`First line\nSecond line`

function tag(strings) {
  console.log(strings.raw[0]);
  // strings.raw[0] 為 "First line\\nSecond line"
  // 打印輸出 "First line\nSecond line"
}

上面代碼中捅彻,tag函數(shù)的第一個參數(shù)strings组去,有一個raw屬性,也指向一個數(shù)組步淹。該數(shù)組的成員與strings數(shù)組完全一致从隆。比如,strings數(shù)組是["First line\nSecond line"]缭裆,那么strings.raw數(shù)組就是["First line\\nSecond line"]键闺。兩者唯一的區(qū)別,就是字符串里面的斜杠都被轉(zhuǎn)義了澈驼。比如辛燥,strings.raw 數(shù)組會將\n視為\\n兩個字符,而不是換行符缝其。這是為了方便取得轉(zhuǎn)義之前的原始模板而設計的挎塌。

模板字符串的限制

前面提到標簽模板里面,可以內(nèi)嵌其他語言内边。但是榴都,模板字符串默認會將字符串轉(zhuǎn)義,導致無法嵌入其他語言漠其。

舉例來說嘴高,標簽模板里面可以嵌入 LaTEX 語言。

function latex(strings) {
  // ...
}

let document = latex`
\newcommand{\fun}{\textbf{Fun!}}  // 正常工作
\newcommand{\unicode}{\textbf{Unicode!}} // 報錯
\newcommand{\xerxes}{\textbf{King!}} // 報錯

Breve over the h goes \u{h}ere // 報錯
`

上面代碼中和屎,變量document內(nèi)嵌的模板字符串拴驮,對于 LaTEX 語言來說完全是合法的,但是 JavaScript 引擎會報錯柴信。原因就在于字符串的轉(zhuǎn)義莹汤。

模板字符串會將\u00FF\u{42}當作 Unicode 字符進行轉(zhuǎn)義,所以\unicode解析時報錯颠印;而\x56會被當作十六進制字符串轉(zhuǎn)義,所以\xerxes會報錯抹竹。也就是說线罕,\u\x在 LaTEX 里面有特殊含義,但是 JavaScript 將它們轉(zhuǎn)義了窃判。

為了解決這個問題钞楼,ES2018 放松了對標簽模板里面的字符串轉(zhuǎn)義的限制。如果遇到不合法的字符串轉(zhuǎn)義袄琳,就返回undefined询件,而不是報錯燃乍,并且從raw屬性上面可以得到原始字符串。

function tag(strs) {
  strs[0] === undefined
  strs.raw[0] === "\\unicode and \\u{55}";
}
tag`\unicode and \u{55}`

上面代碼中宛琅,模板字符串原本是應該報錯的刻蟹,但是由于放松了對字符串轉(zhuǎn)義的限制,所以不報錯了嘿辟,JavaScript 引擎將第一個字符設置為undefined舆瘪,但是raw屬性依然可以得到原始字符串,因此tag函數(shù)還是可以對原字符串進行處理红伦。

注意英古,這種對字符串轉(zhuǎn)義的放松,只在標簽模板解析字符串時生效昙读,不是標簽模板的場合召调,依然會報錯。

let bad = `bad escape sequence: \unicode`; // 報錯
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛮浑,一起剝皮案震驚了整個濱河市唠叛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌陵吸,老刑警劉巖玻墅,帶你破解...
    沈念sama閱讀 210,835評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異壮虫,居然都是意外死亡澳厢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,900評論 2 383
  • 文/潘曉璐 我一進店門囚似,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剩拢,“玉大人,你說我怎么就攤上這事饶唤⌒旆ィ” “怎么了?”我有些...
    開封第一講書人閱讀 156,481評論 0 345
  • 文/不壞的土叔 我叫張陵募狂,是天一觀的道長办素。 經(jīng)常有香客問我,道長祸穷,這世上最難降的妖魔是什么性穿? 我笑而不...
    開封第一講書人閱讀 56,303評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮雷滚,結(jié)果婚禮上需曾,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好呆万,可當我...
    茶點故事閱讀 65,375評論 5 384
  • 文/花漫 我一把揭開白布商源。 她就那樣靜靜地躺著,像睡著了一般谋减。 火紅的嫁衣襯著肌膚如雪牡彻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,729評論 1 289
  • 那天逃顶,我揣著相機與錄音讨便,去河邊找鬼。 笑死以政,一個胖子當著我的面吹牛霸褒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盈蛮,決...
    沈念sama閱讀 38,877評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼废菱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抖誉?” 一聲冷哼從身側(cè)響起殊轴,我...
    開封第一講書人閱讀 37,633評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎袒炉,沒想到半個月后旁理,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,088評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡我磁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,443評論 2 326
  • 正文 我和宋清朗相戀三年孽文,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夺艰。...
    茶點故事閱讀 38,563評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡芋哭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出郁副,到底是詐尸還是另有隱情减牺,我是刑警寧澤,帶...
    沈念sama閱讀 34,251評論 4 328
  • 正文 年R本政府宣布存谎,位于F島的核電站拔疚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏既荚。R本人自食惡果不足惜草雕,卻給世界環(huán)境...
    茶點故事閱讀 39,827評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望固以。 院中可真熱鬧,春花似錦、人聲如沸憨琳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,712評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽篙螟。三九已至菌湃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間遍略,已是汗流浹背惧所。 一陣腳步聲響...
    開封第一講書人閱讀 31,943評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绪杏,地道東北人下愈。 一個月前我還...
    沈念sama閱讀 46,240評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像蕾久,于是被迫代替她去往敵國和親势似。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,435評論 2 348

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