Iterator 與for...of...

原生具備 Iterator 接口的數(shù)據(jù)結(jié)構(gòu)如下杈湾。
Array
Map
Set
String
TypedArray
函數(shù)的 arguments 對(duì)象
NodeList 對(duì)象

JavaScript 原有的表示“集合”的數(shù)據(jù)結(jié)構(gòu)吏垮,主要是數(shù)組(Array)對(duì)象(Object),ES6 又添加了MapSet后豫。這樣就有了四種數(shù)據(jù)集合,用戶(hù)還可以組合使用它們燥狰,定義自己的數(shù)據(jù)結(jié)構(gòu)圈驼,比如數(shù)組的成員是Map,Map的成員是對(duì)象隐圾。這樣就需要一種統(tǒng)一的接口機(jī)制伍掀,來(lái)處理所有不同的數(shù)據(jù)結(jié)構(gòu)。

遍歷器(Iterator)就是這樣一種機(jī)制暇藏。它是一種接口蜜笤,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪(fǎng)問(wèn)機(jī)制。任何數(shù)據(jù)結(jié)構(gòu)只要部署Iterator接口盐碱,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)把兔。

Iterator 的作用有三個(gè):一是為各種數(shù)據(jù)結(jié)構(gòu)沪伙,提供一個(gè)統(tǒng)一的、簡(jiǎn)便的訪(fǎng)問(wèn)接口县好;二是使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列围橡;三是ES6創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator接口主要供for...of消費(fèi)缕贡。

Iterator 的遍歷過(guò)程是這樣的翁授。

(1)創(chuàng)建一個(gè)指針對(duì)象,指向當(dāng)前數(shù)據(jù)結(jié)構(gòu)的起始位置晾咪。也就是說(shuō)收擦,遍歷器對(duì)象本質(zhì)上,就是一個(gè)指針對(duì)象谍倦。
(2)第一次調(diào)用指針對(duì)象的next方法塞赂,可以將指針指向數(shù)據(jù)結(jié)構(gòu)的第一個(gè)成員。
(3)第二次調(diào)用指針對(duì)象的next方法昼蛀,指針就指向數(shù)據(jù)結(jié)構(gòu)的第二個(gè)成員宴猾。
(4)不斷調(diào)用指針對(duì)象的next方法,直到它指向數(shù)據(jù)結(jié)構(gòu)的結(jié)束位置曹洽。

每一次調(diào)用next方法鳍置,都會(huì)返回?cái)?shù)據(jù)結(jié)構(gòu)的當(dāng)前成員的信息。具體來(lái)說(shuō)送淆,就是返回一個(gè)包含value和done兩個(gè)屬性的對(duì)象税产。其中,value屬性是當(dāng)前成員的值偷崩,done屬性是一個(gè)布爾值辟拷,表示遍歷是否結(jié)束。

下面是一個(gè)模擬next方法返回值的例子阐斜。

var it = makeIterator(['a', 'b']);

it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}

上面代碼定義了一個(gè)makeIterator函數(shù)衫冻,它是一個(gè)遍歷器生成函數(shù),作用就是返回一個(gè)遍歷器對(duì)象谒出。對(duì)數(shù)組['a', 'b']執(zhí)行這個(gè)函數(shù)隅俘,就會(huì)返回該數(shù)組的遍歷器對(duì)象(即指針對(duì)象)it。

next方法返回一個(gè)對(duì)象笤喳,表示當(dāng)前數(shù)據(jù)成員的信息为居。這個(gè)對(duì)象具有value和done兩個(gè)屬性,value屬性返回當(dāng)前位置的成員杀狡,done屬性是一個(gè)布爾值蒙畴,表示遍歷是否結(jié)束,即是否還有必要再一次調(diào)用next方法呜象。

默認(rèn) Iterator 接口

Iterator 接口的目的膳凝,就是為所有數(shù)據(jù)結(jié)構(gòu)碑隆,提供了一種統(tǒng)一的訪(fǎng)問(wèn)機(jī)制,即for...of循環(huán)(詳見(jiàn)下文)蹬音。當(dāng)使用for...of循環(huán)遍歷某種數(shù)據(jù)結(jié)構(gòu)時(shí)上煤,該循環(huán)會(huì)自動(dòng)去尋找 Iterator 接口。

一種數(shù)據(jù)結(jié)構(gòu)只要部署了 Iterator 接口祟绊,我們就稱(chēng)這種數(shù)據(jù)結(jié)構(gòu)是”可遍歷的“(iterable)楼入。

ES6 規(guī)定,默認(rèn)的 Iterator 接口部署在數(shù)據(jù)結(jié)構(gòu)的Symbol.iterator屬性牧抽,或者說(shuō)嘉熊,一個(gè)數(shù)據(jù)結(jié)構(gòu)只要具有Symbol.iterator屬性,就可以認(rèn)為是“可遍歷的”(iterable)扬舒。Symbol.iterator屬性本身是一個(gè)函數(shù)阐肤,就是當(dāng)前數(shù)據(jù)結(jié)構(gòu)默認(rèn)的遍歷器生成函數(shù)。執(zhí)行這個(gè)函數(shù)讲坎,就會(huì)返回一個(gè)遍歷器孕惜。至于屬性名Symbol.iterator,它是一個(gè)表達(dá)式晨炕,返回Symbol對(duì)象的iterator屬性衫画,這是一個(gè)預(yù)定義好的、類(lèi)型為 Symbol 的特殊值瓮栗,所以要放在方括號(hào)內(nèi)削罩。

const obj = {
  [Symbol.iterator] : function () {
    return {
      next: function () {
        return {
          value: 1,
          done: true
        };
      }
    };
  }
};

上面代碼中,對(duì)象obj是可遍歷的(iterable)费奸,因?yàn)榫哂蠸ymbol.iterator屬性弥激。執(zhí)行這個(gè)屬性,會(huì)返回一個(gè)遍歷器對(duì)象愿阐。該對(duì)象的根本特征就是具有next方法微服。每次調(diào)用next方法,都會(huì)返回一個(gè)代表當(dāng)前成員的信息對(duì)象缨历,具有value和done兩個(gè)屬性以蕴。

ES6 的有些數(shù)據(jù)結(jié)構(gòu)原生具備 Iterator 接口(比如數(shù)組),即不用任何處理辛孵,就可以被for...of循環(huán)遍歷舒裤。原因在于,這些數(shù)據(jù)結(jié)構(gòu)原生部署了Symbol.iterator屬性(詳見(jiàn)下文)觉吭,另外一些數(shù)據(jù)結(jié)構(gòu)沒(méi)有(比如對(duì)象)。凡是部署了Symbol.iterator屬性的數(shù)據(jù)結(jié)構(gòu)仆邓,就稱(chēng)為部署了遍歷器接口鲜滩。調(diào)用這個(gè)接口伴鳖,就會(huì)返回一個(gè)遍歷器對(duì)象。
下面的例子是數(shù)組的Symbol.iterator屬性徙硅。

let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();

iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }

上面代碼中榜聂,變量arr是一個(gè)數(shù)組,原生就具有遍歷器接口嗓蘑,部署在arr的Symbol.iterator屬性上面须肆。所以,調(diào)用這個(gè)屬性桩皿,就得到遍歷器對(duì)象豌汇。

對(duì)于原生部署 Iterator 接口的數(shù)據(jù)結(jié)構(gòu),不用自己寫(xiě)遍歷器生成函數(shù)泄隔,for...of循環(huán)會(huì)自動(dòng)遍歷它們拒贱。除此之外,其他數(shù)據(jù)結(jié)構(gòu)(主要是對(duì)象)的 Iterator 接口佛嬉,都需要自己在Symbol.iterator屬性上面部署逻澳,這樣才會(huì)被for...of循環(huán)遍歷。

一個(gè)對(duì)象如果要具備可被for...of循環(huán)調(diào)用的 Iterator 接口暖呕,就必須在Symbol.iterator的屬性上部署遍歷器生成方法(原型鏈上的對(duì)象具有該方法也可)斜做。

class RangeIterator {
  constructor(start, stop) {
    this.value = start;
    this.stop = stop;
  }

  [Symbol.iterator]() { return this; }

  next() {
    var value = this.value;
    if (value < this.stop) {
      this.value++;
      return {done: false, value: value};
    }
    return {done: true, value: undefined};
  }
}

function range(start, stop) {
  return new RangeIterator(start, stop);
}

for (var value of range(0, 3)) {
  console.log(value); // 0, 1, 2
}

上面代碼是一個(gè)類(lèi)部署 Iterator 接口的寫(xiě)法。Symbol.iterator屬性對(duì)應(yīng)一個(gè)函數(shù)湾揽,執(zhí)行后返回當(dāng)前對(duì)象的遍歷器對(duì)象瓤逼。
有了遍歷器接口,數(shù)據(jù)結(jié)構(gòu)就可以用for...of循環(huán)遍歷(詳見(jiàn)下文)钝腺,也可以使用while循環(huán)遍歷抛姑。

var $iterator = ITERABLE[Symbol.iterator]();
var $result = $iterator.next();
while (!$result.done) {
  var x = $result.value;
  // ...
  $result = $iterator.next();
}

上面代碼中,ITERABLE代表某種可遍歷的數(shù)據(jù)結(jié)構(gòu)艳狐,$iterator是它的遍歷器對(duì)象定硝。遍歷器對(duì)象每次移動(dòng)指針(next方法),都檢查一下返回值的done屬性毫目,如果遍歷還沒(méi)結(jié)束蔬啡,就移動(dòng)遍歷器對(duì)象的指針到下一步(next方法),不斷循環(huán)镀虐。
調(diào)用 Iterator 接口的場(chǎng)合
有一些場(chǎng)合會(huì)默認(rèn)調(diào)用 Iterator 接口(即Symbol.iterator方法)箱蟆,除了下文會(huì)介紹的for...of循環(huán),還有幾個(gè)別的場(chǎng)合刮便。

調(diào)用iterator的場(chǎng)合

(1)解構(gòu)賦值

對(duì)數(shù)組和 Set 結(jié)構(gòu)進(jìn)行解構(gòu)賦值時(shí)空猜,會(huì)默認(rèn)調(diào)用Symbol.iterator方法。

let set = new Set().add('a').add('b').add('c');

let [x,y] = set;
// x='a'; y='b'

let [first, ...rest] = set;
// first='a'; rest=['b','c'];

(2)擴(kuò)展運(yùn)算符

擴(kuò)展運(yùn)算符(...)也會(huì)調(diào)用默認(rèn)的 Iterator 接口。

// 例一
var str = 'hello';
[...str] //  ['h','e','l','l','o']

// 例二
let arr = ['b', 'c'];
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']

上面代碼的擴(kuò)展運(yùn)算符內(nèi)部就調(diào)用 Iterator 接口辈毯。

實(shí)際上坝疼,這提供了一種簡(jiǎn)便機(jī)制,可以將任何部署了 Iterator 接口的數(shù)據(jù)結(jié)構(gòu)谆沃,轉(zhuǎn)為數(shù)組钝凶。也就是說(shuō),只要某個(gè)數(shù)據(jù)結(jié)構(gòu)部署了 Iterator 接口唁影,就可以對(duì)它使用擴(kuò)展運(yùn)算符耕陷,將其轉(zhuǎn)為數(shù)組。

let arr = [...iterable];
(3)yield*

yield*后面跟的是一個(gè)可遍歷的結(jié)構(gòu)据沈,它會(huì)調(diào)用該結(jié)構(gòu)的遍歷器接口哟沫。

let generator = function* () {
  yield 1;
  yield* [2,3,4];
  yield 5;
};

var iterator = generator();

iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: 4, done: false }
iterator.next() // { value: 5, done: false }
iterator.next() // { value: undefined, done: true }

(4)其他場(chǎng)合

由于數(shù)組的遍歷會(huì)調(diào)用遍歷器接口,所以任何接受數(shù)組作為參數(shù)的場(chǎng)合卓舵,其實(shí)都調(diào)用了遍歷器接口南用。下面是一些例子。

for...of
Array.from()
Map(), Set(), WeakMap(), WeakSet()(比如new Map([['a',1],['b',2]]))
Promise.all()
Promise.race()

字符串的 Iterator 接口

字符串是一個(gè)類(lèi)似數(shù)組的對(duì)象掏湾,也原生具有 Iterator 接口裹虫。

var someString = "hi";
typeof someString[Symbol.iterator]
// "function"

var iterator = someString[Symbol.iterator]();

iterator.next()  // { value: "h", done: false }
iterator.next()  // { value: "i", done: false }
iterator.next()  // { value: undefined, done: true }

上面代碼中,調(diào)用Symbol.iterator方法返回一個(gè)遍歷器對(duì)象融击,在這個(gè)遍歷器上可以調(diào)用next方法筑公,實(shí)現(xiàn)對(duì)于字符串的遍歷。

可以覆蓋原生的Symbol.iterator方法尊浪,達(dá)到修改遍歷器行為的目的匣屡。

var str = new String("hi");

[...str] // ["h", "i"]

str[Symbol.iterator] = function() {
  return {
    next: function() {
      if (this._first) {
        this._first = false;
        return { value: "bye", done: false };
      } else {
        return { done: true };
      }
    },
    _first: true
  };
};

[...str] // ["bye"]
str // "hi"

上面代碼中,字符串str的Symbol.iterator方法被修改了拇涤,所以擴(kuò)展運(yùn)算符(...)返回的值變成了bye捣作,而字符串本身還是hi。

Iterator接口與Generator函數(shù)

Symbol.iterator方法的最簡(jiǎn)單實(shí)現(xiàn)鹅士,還是使用Generator函數(shù)券躁。

var myIterable = {};

myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};
[...myIterable] // [1, 2, 3]

// 或者采用下面的簡(jiǎn)潔寫(xiě)法

let obj = {
  * [Symbol.iterator]() {
    yield 'hello';
    yield 'world';
  }
};

for (let x of obj) {
  console.log(x);
}
// hello
// world

上面代碼中,Symbol.iterator方法幾乎不用部署任何代碼掉盅,只要用yield命令給出每一步的返回值即可也拜。
for...of循環(huán)可以代替數(shù)組實(shí)例的forEach方法。

const arr = ['red', 'green', 'blue'];

arr.forEach(function (element, index) {
  console.log(element); // red green blue
  console.log(index);   // 0 1 2
});

JavaScript 原有的for...in循環(huán)趾痘,只能獲得對(duì)象的鍵名慢哈,不能直接獲取鍵值。ES6 提供for...of循環(huán)永票,允許遍歷獲得鍵值卵贱。

var arr = ['a', 'b', 'c', 'd'];

for (let a in arr) {
  console.log(a); // 0 1 2 3
}

for (let a of arr) {
  console.log(a); // a b c d
}

上面代碼表明滥沫,for...in循環(huán)讀取鍵名,for...of循環(huán)讀取鍵值艰赞。如果要通過(guò)for...of循環(huán)佣谐,獲取數(shù)組的索引,可以借助數(shù)組實(shí)例的entries方法和keys方法.

類(lèi)似數(shù)組的對(duì)象

類(lèi)似數(shù)組的對(duì)象包括好幾類(lèi)方妖。下面是for...of
循環(huán)用于字符串、DOM NodeList 對(duì)象罚攀、arguments
對(duì)象的例子党觅。

// 字符串
let str = "hello";
for (let s of str) { 
console.log(s); // h e l l o
}

// DOM NodeList對(duì)象
let paras = document.querySelectorAll("p");
for (let p of paras) { 
p.classList.add("test");
}

// arguments對(duì)象
function printArgs() {
 for (let x of arguments) { 
console.log(x); 
  }
}
printArgs('a', 'b');
// 'a'
// 'b'

對(duì)于字符串來(lái)說(shuō),for...of
循環(huán)還有一個(gè)特點(diǎn)斋泄,就是會(huì)正確識(shí)別32位 UTF-16 字符杯瞻。
for (let x of 'a\uD83D\uDC0A') { console.log(x);}// 'a'// '\uD83D\uDC0A'

并不是所有類(lèi)似數(shù)組的對(duì)象都具有 Iterator 接口,一個(gè)簡(jiǎn)便的解決方法炫掐,就是使用Array.from
方法將其轉(zhuǎn)為數(shù)組魁莉。

let arrayLike = { length: 2, 0: 'a', 1: 'b' };
// 報(bào)錯(cuò)
for (let x of arrayLike) {
console.log(x);
}
// 正確
for (let x of Array.from(arrayLike)) {
console.log(x);
}


###對(duì)象
對(duì)于普通的對(duì)象,for...of結(jié)構(gòu)不能直接使用募胃,會(huì)報(bào)錯(cuò)旗唁,必須部署了 Iterator 接口后才能使用。但是痹束,這樣情況下检疫,for...in循環(huán)依然可以用來(lái)遍歷鍵名。

let es6 = {
edition: 6,
committee: "TC39",
standard: "ECMA-262"
};

for (let e in es6) {
console.log(e);
}
// edition
// committee
// standard

for (let e of es6) {
console.log(e);
}
// TypeError: es6[Symbol.iterator] is not a function

上面代碼表示祷嘶,對(duì)于普通的對(duì)象屎媳,for...in循環(huán)可以遍歷鍵名,for...of循環(huán)會(huì)報(bào)錯(cuò)论巍。

一種解決方法是烛谊,使用Object.keys方法將對(duì)象的鍵名生成一個(gè)數(shù)組,然后遍歷這個(gè)數(shù)組嘉汰。

for (var key of Object.keys(someObject)) {
console.log(key + ': ' + someObject[key]);
}

另一個(gè)方法是使用 Generator 函數(shù)將對(duì)象重新包裝一下丹禀。

function* entries(obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
}

for (let [key, value] of entries(obj)) {
console.log(key, '->', value);
}
// a -> 1
// b -> 2
// c -> 3

##與其他遍歷語(yǔ)法的比較
以數(shù)組為例,JavaScript 提供多種遍歷語(yǔ)法郑现。最原始的寫(xiě)法就是for循環(huán)湃崩。

for (var index = 0; index < myArray.length; index++) {
console.log(myArray[index]);
}

這種寫(xiě)法比較麻煩,因此數(shù)組提供內(nèi)置的forEach方法接箫。

myArray.forEach(function (value) {
console.log(value);
});

這種寫(xiě)法的問(wèn)題在于攒读,*無(wú)法中途跳出forEach循環(huán)*,break命令或return命令都不能奏效辛友。

for...in循環(huán)可以遍歷數(shù)組的鍵名薄扁。

for (var index in myArray) {
console.log(myArray[index]);
}

for...in循環(huán)有幾個(gè)缺點(diǎn)剪返。

數(shù)組的鍵名是數(shù)字,但是for...in循環(huán)是以字符串作為鍵名“0”邓梅、“1”脱盲、“2”等等。
for...in循環(huán)不僅遍歷數(shù)字鍵名日缨,還會(huì)遍歷手動(dòng)添加的其他鍵钱反,甚至包括原型鏈上的鍵。
某些情況下匣距,for...in循環(huán)會(huì)以任意順序遍歷鍵名面哥。
總之,for...in循環(huán)主要是為遍歷對(duì)象而設(shè)計(jì)的毅待,不適用于遍歷數(shù)組尚卫。

for...of循環(huán)相比上面幾種做法,有一些顯著的優(yōu)點(diǎn)尸红。

for (let value of myArray) {
console.log(value);
}

有著同for...in一樣的簡(jiǎn)潔語(yǔ)法吱涉,但是沒(méi)有for...in那些缺點(diǎn)。
*不同于forEach方法外里,它可以與break怎爵、continue和return配合使用。*
提供了遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一操作接口级乐。
下面是一個(gè)使用break語(yǔ)句疙咸,跳出for...of循環(huán)的例子。

for (var n of fibonacci) {
if (n > 1000)
break;
console.log(n);
}

上面的例子风科,會(huì)輸出斐波納契數(shù)列小于等于1000的項(xiàng)撒轮。如果當(dāng)前項(xiàng)大于1000,就會(huì)使用break語(yǔ)句跳出for...of循環(huán)贼穆。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末题山,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子故痊,更是在濱河造成了極大的恐慌顶瞳,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愕秫,死亡現(xiàn)場(chǎng)離奇詭異慨菱,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)戴甩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)符喝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人甜孤,你說(shuō)我怎么就攤上這事协饲∥吠螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵茉稠,是天一觀(guān)的道長(zhǎng)描馅。 經(jīng)常有香客問(wèn)我,道長(zhǎng)而线,這世上最難降的妖魔是什么铭污? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮吞获,結(jié)果婚禮上况凉,老公的妹妹穿的比我還像新娘。我一直安慰自己各拷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布闷营。 她就那樣靜靜地躺著烤黍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪傻盟。 梳的紋絲不亂的頭發(fā)上速蕊,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音娘赴,去河邊找鬼规哲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诽表,可吹牛的內(nèi)容都是我干的唉锌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼竿奏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼袄简!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起泛啸,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤绿语,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后候址,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體吕粹,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年岗仑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匹耕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赔蒲,死狀恐怖泌神,靈堂內(nèi)的尸體忽然破棺而出良漱,到底是詐尸還是另有隱情,我是刑警寧澤欢际,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布母市,位于F島的核電站,受9級(jí)特大地震影響损趋,放射性物質(zhì)發(fā)生泄漏患久。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一浑槽、第九天 我趴在偏房一處隱蔽的房頂上張望蒋失。 院中可真熱鬧,春花似錦桐玻、人聲如沸篙挽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)铣卡。三九已至,卻和暖如春偏竟,著一層夾襖步出監(jiān)牢的瞬間煮落,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工踊谋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝉仇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓殖蚕,卻偏偏與公主長(zhǎng)得像轿衔,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嫌褪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

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

  • Iterator(遍歷器)的概念 JavaScript原有的表示“集合”的數(shù)據(jù)結(jié)構(gòu)呀枢,主要是數(shù)組(Array)和對(duì)象...
    呼呼哥閱讀 4,456評(píng)論 0 2
  • for in for in可以用來(lái)遍歷對(duì)象的可枚舉屬性列表(包括[[prototype]]鏈),單獨(dú)使用in操作符...
    ascend13閱讀 857評(píng)論 0 1
  • 一笼痛、let 和 constlet:變量聲明, const:只讀常量聲明(聲明的時(shí)候賦值)裙秋。 let 與 var 的...
    dadage456閱讀 763評(píng)論 0 0
  • 昨天我華小兔首次更新一張有對(duì)話(huà)的漫畫(huà)徐块,大家應(yīng)該看到了未玻。 畫(huà)風(fēng)是這樣的: “你有看到我朋友嗎?” “他長(zhǎng)什么樣胡控?” ...
    華小兔漫畫(huà)閱讀 269評(píng)論 0 0
  • 我的學(xué)習(xí)筆記的參考來(lái)源來(lái)自唐巧的博客,今天早上開(kāi)始學(xué)習(xí)他在基礎(chǔ)篇所講的排版引擎框架,首先我看到了這個(gè)"單一功能原則...
    iOSDevVicky閱讀 507評(píng)論 0 2