JavaScript之閉包與高階函數(shù)(二)

查看更多詳情歡迎訪問我的博客訪問我的github我的筆記站萎坷,選擇您喜歡的風格自由馳騁知識的海洋凹联。

高階函數(shù),是指可以作為參數(shù)傳遞或者可以作為返回值輸出的函數(shù)哆档。在JavaScript中蔽挠,函數(shù)是第一類對象,其既可以作為參數(shù)傳遞虐呻,也可以作為其他函數(shù)的返回值輸出象泵,顯然是高階函數(shù)。

高階函數(shù)之參數(shù)傳遞

把函數(shù)當作參數(shù)傳遞斟叼,最常見的要數(shù)回掉函數(shù)偶惠,,我們常常在回掉函數(shù)中存放的是代碼中易變的邏輯部分

回調(diào)函數(shù)

在JavaScript的學習和開發(fā)過程中朗涩,回調(diào)函數(shù)的使用率可謂尤其高忽孽,在DOM事件注冊事件處理程序,ajax異步請求等等諸多場景頻繁使用回調(diào)函數(shù)谢床。


    /**
     * [addHandler 處理事件注冊兼容]
     * @param {[type]} elem    [dom元素]
     * @param {[type]} type    [事件類型]
     * @param {[type]} handler [事件處理程序]
     */
    function addHandler(elem, type, handler) {
        if (document.addEventListener) {
            elem.addEventListener(type, handler);
        }else if (document.attachEvent) {
            elem.attachEvent('on' + type, handler);
        }else {
            elem['on' + type] = handler;
        }
    }
    function fn1(e) {
        console.log(e);
    } 
    var div = document.getElementById('myDiv');
    addHandler(div, 'click', fn1);

又比如Array.prototype.sort方法兄一,接受一個函數(shù)當作參數(shù),函數(shù)里面封裝的是對數(shù)組進行排序的規(guī)則识腿。


    var arr = [1, 3, 5, 7, 2, 4, 6];
    arr.sort(function(a, b) {
        return a - b; //從小到大排序出革,如需從大到小排序,只需return b - a;
    });

高階函數(shù)之返回值輸出

相信大家對函數(shù)式編程一定不陌生渡讼,至少都耳熟過骂束,,在函數(shù)式編程中成箫,將函數(shù)當作返回值輸出很是常見展箱。

類型檢測

JavaScript是一門動態(tài)的腳本語言,其數(shù)據(jù)類型直到程序運行時才能確定蹬昌,于是在JavaScript中對數(shù)據(jù)類型進行檢測判斷不如Java等其他靜態(tài)語言來的簡便直接混驰。

typeof和instanceof

JavaScript中,常見的兩個判斷數(shù)據(jù)類型的方法是使用typeof和instanceof,在大多數(shù)情況下還是能正確判斷出數(shù)據(jù)類型的,但這兩者都有其局限性皂贩,因此栖榨,其使用也必然有局限性。


    console.log(typeof null); //object
    var arr = [];
    console.log(arr instanceof Array);//true
    function test() {
        console.log(arguments instanceof Array); //輸出false
    }
    test();

只有當arr是數(shù)組明刷,且與Array構(gòu)造函數(shù)在同一全局作用域中婴栽,arr instanceof Array才返回true,如果arr是某一frame中定義的數(shù)組遮精,上式返回false居夹。

Object.prototype.toString

Object.prototype.toString方法總是返回字符串败潦,如Object.prototype.toString.call([1,2,3])總是返回"[object Array]",Object.prototype.toString.call('str')總是返回"[object String]",Object.prototype.toString.call(12)總是返回"[object Number]",所以可以使用Object.prototype.

更多關(guān)于calls與apply可查看本系列筆記篇JavaScript之this,call與apply

    
    var isType = function(type) {
        return function(obj) {
            return Object.prototype.toString.call(obj) == '[object ' + type + ']';
        }
    }
    var isString = isType('String');
    console.log(isString('testString')); //輸出true
    var isArray = isType('Array');
    console.log(isArray([1,3,5])); //輸出true

作用域安全的構(gòu)造函數(shù)

構(gòu)造函數(shù)准脂,即是一個函數(shù)劫扒,通過new操作符調(diào)用,以new操作符調(diào)用時狸膏,構(gòu)造函數(shù)內(nèi)部this指向新創(chuàng)建的構(gòu)造函數(shù)實例對象沟饥。


    function Animal(name, type) {
        this.name = name;
        this.type = type;
    }
    var animal1 = new Animal('wangwang', 'Dog');
    console.log(animal1.name, animal1.type); //輸出wnagwnag DOg
    var animal2 = Animal('miaomiao', 'Cat');
    console.log(window.name, window.type); //輸出miaomiao Cat
    console.log(animal2.name, animal2.type); //TypeError: Cannot read property 'name' of undefined

當使用new操作符調(diào)用Animal構(gòu)造函數(shù)時,會創(chuàng)建一個新的Animal對象湾戳,此對象擁有name和type屬性贤旷;當直接調(diào)用Animal構(gòu)造函數(shù)時,this對象指向全局環(huán)境即window(普通函數(shù)方式調(diào)用時砾脑,this總是指向全局環(huán)境幼驶,更多關(guān)于this指向問題可查看本系列筆記篇JavaScript之this,call與apply,于是上述代碼window上有name和type屬性韧衣,animal2上沒有盅藻。

上述問題該如何解決呢?既然問題源自this,那就從this著手:


    function Animal(name, type) {
        if (this instanceof Animal) {
            this.name = name;
            this.type = type;
        }else {
            return new Animal(name, type);
        }
    }
    var animal1 = new Animal('wangwang', 'Dog');
    console.log(animal1.name, animal1.type); //輸出wnagwnag DOg
    var animal2 = Animal('miaomiao', 'Cat');
    console.log(window.name); //輸出undefined
    console.log(animal2.name, animal2.type); //輸出miaomiao Cat

在使用new調(diào)用構(gòu)造函數(shù)時畅铭,this指向Animal實例氏淑,this instanceof Animal返回true;當直接調(diào)用構(gòu)造函數(shù)時硕噩,this指向全局環(huán)境window假残,this instanceof Animal返回false,此構(gòu)造函數(shù)內(nèi)部處理強制返回一個新實例炉擅,于是animal2中包含name和type屬性辉懒。

函數(shù)綁定

函數(shù)綁定常指在調(diào)用某一函數(shù)時,將此函數(shù)內(nèi)部this指向特定上下文環(huán)境坑资,就是函數(shù)內(nèi)部this和上下文環(huán)境的綁定耗帕。


    var Animal = {
        name: 'Cat',
        getName: function() {
            return this.name;
        }
    };
    var Animal2 = {
        name: 'Dog'
    };
    console.log(Animal.getName()); //輸出Cat
    var div = document.getElementById('myDiv');
    div.addEventListener('mouseover', Animal.getName); //返回undefined
    div.addEventListener('click', function(e) {
        console.log(this);
        console.log(Animal.getName()); //輸出Cat
    });

如上代碼中第一個輸出Cat穆端,很好理解袱贮,this指向Animal;而第二個返回undefined是為什么呢,因為在給DOM元素注冊事件處理程序時体啰,會修改事件處理程序的this指向攒巍,使其指向當前DOM元素(IE8除外,IE8中指向全局環(huán)境window)荒勇;第三處輸出Cat是因為DOM事件修改的是事件處理程序的this指向柒莉,即此處Animal.getName()的包含環(huán)境中的this,此包含函數(shù)形成一個閉包沽翔,在此閉包中直接調(diào)用Animal.getName()兢孝,getName函數(shù)里面this指向Animal窿凤。

我們再看一段代碼:


    Function.prototype.bind = function(context) {
        var self = this;
        return function() {
            self.apply(context, arguments);
        };
    };
    var Animal = {
        name: 'Cat',
        getName: function() {
            //console.log(this.name);
            return this.name;
        }
    };
    var Animal2 = {
        name: 'Dog'
    };
    console.log(Animal.getName.bind(Animal2)()); //輸出DOg
    var ani = Animal.getName.bind(Animal);
    console.log(ani(1,2,3)); //輸出Cat,此時bind方法返回的函數(shù)內(nèi)部的arguments屬性就是一個包含1,2,3的類數(shù)組
    var div = document.getElementById('myDiv');
    div.addEventListener('click', Animal.getName.bind(Animal)); 
    //點擊后返回Cat

我們在Function原型上定義了bind函數(shù),其返回一個函數(shù)跨蟹,這個函數(shù)形成一個閉包雳殊,其this與其包含函數(shù)this并不指向同一環(huán)境,于是使用了self保存包含函數(shù)的this對象窗轩,self便指向調(diào)用bind方法的函數(shù)夯秃,然后又使用apply調(diào)用此函數(shù),傳入了context上下文環(huán)境痢艺,及內(nèi)部閉包函數(shù)的參數(shù)仓洼。

注:在調(diào)用setTimeout,setInterval時,其內(nèi)部this總是指向全局環(huán)境window堤舒,因此定時器函數(shù)中被調(diào)用的函數(shù)經(jīng)常需要我們手動為其綁定上下文環(huán)境色建。


    var obj = {
        test: function() {
            console.log(this); //輸出object{test: function},即指向obj
            setTimeout(function() {
                console.log(this === window); //輸出true
            },300);
        }
    }
    obj.test();

函數(shù)柯里化

currying

函數(shù)柯里化(currying)又叫部分求值。一個currying的函數(shù)接收一些參數(shù)舌缤,接收了這些參數(shù)之后镀岛,該函數(shù)并不是立即求值,而是繼續(xù)返回另一個函數(shù)友驮,剛才傳入的參數(shù)在函數(shù)形成的閉包中被保存起來漂羊,待到函數(shù)真正需要求值的時候,之前傳入的所有參數(shù)都能用于求值卸留。


    var totalCost = 0;
    var cost = function(money) {
        totalCost += money;
    };
    cost(100);
    cost(200);
    cost(400);
    cost(800);
    console.log(totalCost); //輸出1500

如上累計計算totalCost值走越,每次都調(diào)用cost方法,假如我們只需保存前幾次的增加值耻瑟,在最后一次才求值旨指,如何實現(xiàn)為好呢?可以用currying函數(shù)化思想簡單實現(xiàn):


    var cost = (function() {
        var args = [];
        return function() {
            if (!arguments.length) {
                var num = 0;
                for (var i = 0, l = args.length; i < l; i++) {
                    num += args[i];
                }
                return num;
            }else {
                [].push.apply(args, arguments);
            }
        }
    })();
    cost(100);
    cost(200);
    cost(400);
    cost(800);
    console.log(cost()); //輸出1500

上述代碼每次調(diào)用cost傳入?yún)?shù)時并未真正進行計算喳整,而只是把參數(shù)保存在cost函數(shù)所形成的閉包中谆构,在其返回函數(shù)中可隨時訪問進行操作,最后需要進行求值時只需要以無參數(shù)形式調(diào)用cost即可框都。

接下來闡述如何實現(xiàn)一個通用的currying化函數(shù):


    var currying = function(fn) {

    };
    Function.prototype.currying = function() {
        var self = this;
        var args = []; //保存所有參數(shù)值
        return function() { //形成閉包搬素,返回一個新函數(shù),能保存對args的訪問
            if (!arguments.length) {
                return self.apply(this, args); //調(diào)用currying化函數(shù)魏保,并把args作為參數(shù)傳入熬尺。
            }else {
                [].push.apply(args, arguments); //將每次傳入的新參數(shù)存入args
                return arguments.callee;
            }
        }
    };
    var cost = (function() {
        var num = 0;
        return function() {
            num = 0; //確保每次調(diào)用cost()時重新計算所有已保存值值
            for (var i = 0, l = arguments.length; i < l; i++) {
                num += arguments[i]; //對所有參數(shù)求和
            }
            return num;
        }
    })();
    var cost = cost.currying();
    cost(100);
    cost(200);
    cost(400);
    console.log(cost()); //輸出700
    cost(800); 
    console.log(cost()); //輸出1500

如上實現(xiàn)了一個currying函數(shù),調(diào)用cost時明確傳入了參數(shù)谓罗,則此時只是保存參數(shù)值粱哼,不進行業(yè)務(wù)計算拐袜,cost返回另一個函數(shù)剪决。在不傳參數(shù)調(diào)用cost時斑唬,對之前所有保存的參數(shù)值進行業(yè)務(wù)計算完慧。

注:currying化函數(shù)后調(diào)用的cost都是currying函數(shù)cost,而非原本的cost函數(shù)绊含。

uncurrying

在JavaScript學習和開發(fā)過程中需纳,我們經(jīng)常需要讓某對象去調(diào)用一個原本不屬于自己的方法,如Array.prototype.push或是其他自定義對象上的方法艺挪,一般我們經(jīng)常使用的是apply與call,更多有關(guān)apply與call請訪問本系列篇JavaScript之this,call與apply.


    var obj = {
        name: 'Dog',
        getName: function() {
            return this.name;
        }
    };
    var obj2 = {
        name: 'Cat'
    };
    console.log(obj.getName.call(obj2)); //輸出Cat

在本節(jié)不翩,我們要使用uncurrying來實現(xiàn)通用的方法以實現(xiàn)需求:


    Function.prototype.uncurrying = function() {
        var self = this;
        return function() {
            var obj = Array.prototype.shift.call(arguments);
            return self.apply(obj, arguments);
        };
    };
    var push = Array.prototype.push.uncurrying();
    (function() {
        push(arguments, 7);
        console.log(arguments); //輸出[1,3,5,7]
    })(1,3,5);

uncurrying使Array.prototype.push方法變成了一個通用的push函數(shù),push即等價于Array.prototype.push.call麻裳。
在調(diào)用Array.prototype.push.uncurrying()時口蝠,self為Array.prototype.push,調(diào)用push(arguments, 7)時,obj為[1,3,5]津坑,uncurrying方法返回函數(shù)內(nèi)部的arguments為后文自執(zhí)行函數(shù)調(diào)用push傳入的7妙蔗,self.apply(obj, arguments)即等價于Array.prototype.push.apply([1,3,5], 7)。

函數(shù)節(jié)流

JavaScript中疆瑰,有某些函數(shù)是可能會被頻繁調(diào)用眉反,從而造成性能問題,甚至出現(xiàn)功能上的偏差穆役。如:

  • window.onresize事件寸五,在為window注冊了resize事件后,若頻繁的修改窗口大小耿币,就會頻繁的觸發(fā)resize事件梳杏,會非常消耗性能,容易造成瀏覽器卡頓甚至崩潰淹接。
  • mouseenter十性,mouseleave,mousemove等事件塑悼,這些事件由鼠標劃入劲适,劃出,移動觸發(fā)厢蒜,其觸發(fā)頻率可能非诚际疲快,特別是當我們在這是事件處理程序中定義了動畫處理時郭怪,問題尤其需要注意支示,我們知道刊橘,每一段動畫一般都有一個執(zhí)行周期鄙才,多個動畫都是壓入一個動畫隊列,一次執(zhí)行促绵,假如我們觸發(fā)事件的頻率非吃茆郑快嘴纺,動畫將重復觸發(fā)。

    <!doctype html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>無標題文檔</title>
        <script src="./js/jquery.min.js">
        </script>
    </head>
    <body>
        <div class="a1" style="width:100px; height:100px; background-color:#000;"></div>
        <div class="a2" style="width:1000px; height:200px; background-color:#F00; display:none;"></div>
        <div class="b1" style="width:100px; height:100px; background-color:#000;margin-top:20px;"></div>
        <div class="b2" style="width:1000px; height:200px; background-color:#F00; display:none;"></div>
        <script type="text/javascript">
            $('.a1').mouseenter(function(){
                $('.a2').fadeIn();
            });
            $('.a1').mouseleave(function(){ 
                $('.a2').fadeOut();
            });
            $('.b1').mouseenter(function(){
                $('.b2').fadeIn();
            });
            var timeoutId = null;
            $('.b1').mouseleave(function(){
                clearTimeout(timeoutId);
                timeoutId = setTimeout(function(){
                    $('.b2').fadeOut();
                }, 500);
                
            });
        </script>
    </body>
    </html>

代碼效果圖

代碼演示地址
如上浓冒,當我們快速多次劃過第一個小黑塊時栽渴,其動畫會重復執(zhí)行,在我們的鼠標動作停止后稳懒,還在進行動畫闲擦;而對于第二個小黑塊,則不會發(fā)生這種現(xiàn)象场梆。因為在第二個黑塊的mouseleave事件中設(shè)置了定時器墅冷,并且在每次動畫之前都清除之前的定時器,保證了最后只會有一個定時器或油,即一次動畫被執(zhí)行寞忿。

接下來,我們實現(xiàn)一個通用的節(jié)流函數(shù):

    
    var throttle = function(fn, context, interval) {
        clearTimeout(fn.tId);
        fn.tId = setTimeout(function() {
            fn.apply(context || null);
        }, interval || 500);
    };

將之前第一個黑塊的mouseleave事件修改成如下即可實現(xiàn)第二個黑塊的函數(shù)節(jié)流效果:


    var aFn = function() {
        $('.a2').fadeOut();
    };
    $('.a1').mouseleave(function(){ 
        throttle(aFn);
    });

分時函數(shù)

上節(jié)中顶岸,講述了函數(shù)節(jié)流方式用以解決某些函數(shù)被頻繁調(diào)用的問題腔彰,然而有些函數(shù)也會被重復調(diào)用,但這些函數(shù)執(zhí)行次數(shù)卻不能少辖佣,如何在不減少其執(zhí)行次數(shù)的前提下霹抛,把其對頁面性能的破壞降到最低呢?函數(shù)節(jié)流顯然不能解決這個問題卷谈,聰明的程序員提出了分時函數(shù)這一解決方法上炎。

現(xiàn)在企業(yè)內(nèi)部都很流行webIM,企業(yè)即時通訊雏搂,在打開頁面時藕施,需要加載員工列表,這個列表常常會是成百上千的凸郑,一個好友用一個div節(jié)點顯式的話裳食,那就意味著需要創(chuàng)建成百上千個節(jié)點并添加到頁面document,在短時間添加如此多節(jié)點顯然是會影響瀏覽器頁面性能的芙沥,如下:


    var arr = [];
    for (var i = 1; i < 1000; i ++) {
        arr.push(i);
    }
    var renderStaff = function(data) {
        for (var i = 0, l = data.length; i < l; i++) {
            var div = document.createElement('div');
            div.innerHTML = i;
            document.body.appendChild(div);
        }
    };
    renderStaff(arr);

解決問題的方法之一就是使用分時函數(shù)诲祸,如下b把1000個節(jié)點分批進行:

    
    var timeChunk = function(arr, fn, count) {
        var obj, t;
        var len = arr.length;
        var start = function() {
            for (var i = 0; i < Math.min(count || 1, arr.length); i ++) {
                var obj = arr.shift();
                fn(obj);
            }
        };

        return function() {
            t = setInterval(function() {
                if (!arr.length) {
                    return clearInterval(t);
                }
                start();
            }, 200);
        };
    };

于是之前加載1000節(jié)點的代碼重構(gòu)如下,分批創(chuàng)建節(jié)點而昨,每隔200ms創(chuàng)建8個節(jié)點timeChunk接收三個參數(shù)救氯,第一個為節(jié)點數(shù)據(jù),第二個為創(chuàng)建節(jié)點業(yè)務(wù)邏輯歌憨,第三個為每批所創(chuàng)建節(jié)點的個數(shù):


    var arr = [];
    for (var i = 1; i < 1000; i ++) {
        arr.push(i);
    }
    var renderStaff = timeChunk(arr, function(data) {
        var div = document.createElement('div');
        div.innerHTML = i;
        document.body.appendChild(div);
    }, 8);
    renderStaff(arr);

惰性加載函數(shù)

由于瀏覽器間的行為差異着憨,在JavaScript的代碼中,為了達到不同瀏覽器的兼容务嫡,經(jīng)常需要寫入大量判斷語句甲抖,對于執(zhí)行不同代碼塊漆改,比如要實現(xiàn)一個在諸瀏覽器間通用的事件綁定函數(shù)addHandler,可以參考如下代碼實現(xiàn):


    var addHandler = function(elem, type, handler) {
        if (window.addEventListener) {
            return elem.addEventListener(type, handler);
        }else if (window.attachEvent) {
            return elem.attachEvent('on' + type, handler);
        }else {
            return elem['on' + type] = handler;
        }
    }

如上代碼准谚,在每次執(zhí)行時都需要重新做條件判斷挫剑,我們要如何才能做到在每個環(huán)境下只做一次判斷呢?addHandler依然聲明為一個普通函數(shù)柱衔,在第一次進入條件分支時樊破,函數(shù)內(nèi)部會重寫這個函數(shù),重寫的就是符合當前環(huán)境的addHandler函數(shù)唆铐,當再次進入addHandler函數(shù)時捶码,函數(shù)里不再存在條件分支語句:


    var addHandler = function(elem, type, handler) {
        if (window.addEventListener) {
            addHandler = function(elem, type, handler) {
                elem.addEventListener(type, handler); 
            }
        }else if (window.attachEvent) {
            addHandler = function(elem, type, handler) {
                elem.attachEvent('on' + type, handler);
            }
        }else {
            addHandler = function(elem, type, handler) {
                elem['on' + type] = handler;
            }
        }
        addHandler(elem, type, handler);
    };
    //測試一下
    var div = document;
    addHandler(div, 'click', function() {
        console.log('add handler 1');
    });
    addHandler(div, 'click', function() {
        console.log('add handler 2');
    });
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市或链,隨后出現(xiàn)的幾起案子惫恼,更是在濱河造成了極大的恐慌,老刑警劉巖澳盐,帶你破解...
    沈念sama閱讀 211,496評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祈纯,死亡現(xiàn)場離奇詭異,居然都是意外死亡叼耙,警方通過查閱死者的電腦和手機腕窥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來筛婉,“玉大人簇爆,你說我怎么就攤上這事∷觯” “怎么了入蛆?”我有些...
    開封第一講書人閱讀 157,091評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長硕勿。 經(jīng)常有香客問我哨毁,道長,這世上最難降的妖魔是什么源武? 我笑而不...
    開封第一講書人閱讀 56,458評論 1 283
  • 正文 為了忘掉前任扼褪,我火速辦了婚禮,結(jié)果婚禮上粱栖,老公的妹妹穿的比我還像新娘话浇。我一直安慰自己,他們只是感情好闹究,可當我...
    茶點故事閱讀 65,542評論 6 385
  • 文/花漫 我一把揭開白布幔崖。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪岖瑰。 梳的紋絲不亂的頭發(fā)上叛买,一...
    開封第一講書人閱讀 49,802評論 1 290
  • 那天砂代,我揣著相機與錄音蹋订,去河邊找鬼。 笑死刻伊,一個胖子當著我的面吹牛露戒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捶箱,決...
    沈念sama閱讀 38,945評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼智什,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了丁屎?” 一聲冷哼從身側(cè)響起荠锭,我...
    開封第一講書人閱讀 37,709評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晨川,沒想到半個月后证九,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,158評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡共虑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,502評論 2 327
  • 正文 我和宋清朗相戀三年愧怜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妈拌。...
    茶點故事閱讀 38,637評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡拥坛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尘分,到底是詐尸還是另有隱情猜惋,我是刑警寧澤,帶...
    沈念sama閱讀 34,300評論 4 329
  • 正文 年R本政府宣布培愁,位于F島的核電站惨奕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏竭钝。R本人自食惡果不足惜梨撞,卻給世界環(huán)境...
    茶點故事閱讀 39,911評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望香罐。 院中可真熱鬧卧波,春花似錦、人聲如沸庇茫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至查坪,卻和暖如春寸宏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背偿曙。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評論 1 266
  • 我被黑心中介騙來泰國打工氮凝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人望忆。 一個月前我還...
    沈念sama閱讀 46,344評論 2 360
  • 正文 我出身青樓罩阵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親启摄。 傳聞我的和親對象是個殘疾皇子稿壁,可洞房花燭夜當晚...
    茶點故事閱讀 43,500評論 2 348

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