06.函数(function)

一.函数的介绍

函数:就是将一些功能或语句进行封装,在需要的时候,通过调用的形式,执行这些语句。

  • 函数也是一个对象。
  • 使用typeof( )函数检查一个函数对象时,会返回function
  • 函数的使用包含两个步骤
    • 定义函数 —— 封装 独立的功能
    • 调用函数 —— 享受 封装 的成果

1.2 定义函数

  • 定义函数的过程是对某些功能的封装过程
  • 在之后的开发中, 我们会根据自己的需求定义很多自己的函数

1.3 调用函数

  • 调用函数是让已存在的函数为我们所用
  • 这些函数可以是刚刚自己封装好的某个功能函数
  • 当然, 我们也可以去使用JavaScript或者其他三方库定义好的函数.(拿来主义)

1.4 函数的作用

  • ==将大量重复的语句写在函数里,以后使用这些语句的时候,可以直接调用函数,避免重复劳动。==
  • ==简化编程,让编程模块化。==

1.5 函数的例子

  • 计算1+2+3+4+5+6+7......+100?

  • var sum=0;
    function sumN(){
        for(var i=1;i<=100;i++){
          sum+=i;  
        }
        return sum;
    }
    console.log(sumN(100));//5050
    

二.函数的定义和调用

2.1 函数的定义方式

2.1.1 使用==函数声明==来调用一个函数。

  1. 语法:

       function 函数名([形参1,形参2,....]){//形参是可选的,备注:语法中的中括号表示“可选”
                   语句;
       } 
    
  2. 特点

    1. function:是一个关键字,中文是“函数”,"功能".

    2. 函数名字:命名规定和变量的规定一样。==只能是字母、数字、下划线、$,不能数字开头==

    3. 参数:可选。

    4. 大括号里面,是这个函数的语句。

    5. 方法定义是,形参的类型不用写,返回值类型也不写。

    6. 方法是一个对象,如果定义名称相同的方法,会覆盖

    7. 在JS中,方法的调用只与方法的名称有关,和参数列表无关

    8. 在方法声明中有一个隐藏的内置对象(数组),arguments,封装所有的实际参数

2.2.2 使用==函数表达式==来创建一个函数.

  • 之前定义的函数被称之为函数的声明,除了声明之外,还有其他函数形式:
    • 函数表达式:==匿名函数表达式和命名函数表达式==
  • 函数的name属性:所有的函数都有一个name属性用于获取函数的名称
    • *函数声明方式的name属性:函数名
    • 命名函数表达式的name属性:函数名
    • 匿名函数表达式的name属性:变量名
image-20210515023900311

语法:

  var 函数名=function([形参1,形参2,....]){//形参是可选的
              语句;
  } 
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>函数表达式写法</title>
  </head>

  <body>

  </body>
  <script>
    /*
    一.函数表达式写法 
      1.命名函数表达式
      2.匿名函数表达式
    二:函数的属性:name  
       3.1 函数声明方式的name属性:函数名
       3.2 命名函数表达式的name属性:函数名
       3.3 匿名函数表达式的name属性:变量名
    */
    //函数声明的方式
    function func() {
      console.log("我是函数声明的方式");
    }
    func();
    //1.命名函数表达式
    var hasName = function test() {
      console.log("我是一个有名的函数表达式");
    }
    hasName();

    //2.匿名函数表达式
    var noName = function () {
      console.log("我是一个匿名的函数表达式");
    }
    noName();

    //3.函数的属性:name  
    console.log(func.name); //func
    console.log(hasName.name); //test
    console.log(noName.name); //noName
  </script>

</html>

2.2.3 立即执行函数

 (function([形参1,形参2,....]){//形参是可选的
             语句;
           } )()
  • 类比函数表达式:==( 这个括号里面就相当于一个匿名函数)(此括号里就是传递形参)==
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>函数声明和调用</title>
  <script>
    /* 
    函数声明和调用
    1.函数声明的方式
      1.1 使用函数声明来创建一个函数
          语法:
          function 函数名(形参1,形参2,....){//形参是可选的
            语句;
          } 
      1.2 函数表达式
      1.3 立即执行函数    
    */
   function func1(){
     console.log("我是一个函数声明方式的函数");
   };
   var func2=function(){
     console.log("我是一个函数表达式形式的函数");
   };
   (function(){//注意函数结束需要加上分号,否则会导致立即执行函数出错
     console.log("我是一个立即执行函数");
   })();
   func1();
   func2();
  </script>
</head>
<body>
  
</body>
</html>

2.2 函数形参和实参

function add(a,b){//a,b就是形式参数
     return a+b;
   }
   //下面的add里面的为实参
   console.log(add(10,20));//30
   console.log(add("10","20"));//1020
   console.log(add("hello","World"));//helloWorld
   console.log(add(1,2,3,4,5));//3,只有两个参数,后面多余的参数无效

2.2.1 形参

  • 可以在函数的()中来指定一个或多个形参
  • 多个形参之间使用逗号隔开,声明形参就相当于在函数的内部声明了对应的变量,但是并不赋值

2.2.2 实参

  • 在调用函数时,可以在()中指定实参
  • 实参将会赋值给函数中对应的形参
2.2.2.1 实参的类型
  • 函数的实参可以是任意的数据类型
  • 用函数时解析器不会检查实参的类型,所以需要注意,是否有可能需要对参数进行类型的额检查
2.2.2.2 实参的数量

注意:JS里不会对函数实际传入的参数进行检测。可以传值,也可以不传值,也可以任意多个值

调用函数时,解析器也不会检查实参的数量:

  • ==多余实参不会被赋值==

  • ==如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined.==

  • 例如:

    image-20201026112537049

2.2.3 arguments

可以通过arguments获取所有实际传递的参数

案例:

 var total=0;
   var sum=function(){
       console.log(arguments);
       for(var i=0;i<arguments.length;i++){
          total+=arguments[i];
       }   
       return total; 
   }
   var result=sum(1,2,3,4,5,6);//21
   console.log(result);
image-20201026114145857

三.函数返回值

function sum(a,b){
          return a+b;
     }
     sum(10,20);

return的作用是结束方法.

注意:

  • return后的值将会作为函数的执行结果,可以定义一个变量,来接收该结果

  • 在函数中的return后的语句都不会执行(函数在执行完return语句之后停止并立即退出)

  • 如果return语句后不跟任何值,就相当于返回一个undefined

  • 如果函数中不写return,则也会返回undefined

  • 返回值可以是任意的数据类型,可以是对象,也可以是函数。

    • //函数的返回值可以是函数
           function sum(a,b){
             var add=function(){
                return a+b;
             }
             return add;//返回的整个add函数
             return add();//30,这是函数的调用
           }
           console.log(sum(10,20));
      

四.==函数名、函数体和函数加载问题(重要)==

  • 函数名==整个函数

    • //函数名其实就是函数本省
           var add=function(a,b){
             return a+b;
           }
           console.log(add)==console.log(function(a,b){
             return a+b;
           });
      
  • 我们知道,当我们在调用一个函数时,通常使用函数()这种格式;但此时,我们是使用函数这种格式,它的作用相当于整个函数。

  • 函数的加载问题:JS加载函数时,只加载函数名,所以如果像使用内部的成员变量,需要调用函数。

五. ==fn( )和fn的区别【重要】==

  • fn( ):调用函数,相当于获取了函数的返回值。
  • fn:函数对象,相当于直接获取了函数对象

六. 立即执行函数

  • 什么是立即执行函数?

    • 专业名字:Immediately-Invoked Function Expression(IIFE 立即调用函数表达式)
  • 表达的含义是一个函数定义完后被立即执行

    • 第一部分是定义了一个匿名函数,这个函数有自己独立的执行上下文环境。

    • 第二部分是后面的(),表示这个函数被执行了

      image-20210515020209670
  • 这个东西有什么用?

    • ==会创建一个独立的执行上下文环境,可以避免外界访问或修改内部的变量,也避免了对内部变量的修改==
    image-20210515022804280

6.1 立即执行函数其他写法

  • 立即执行函数必须是一个表达式,不能是函数声明:

    • 下面的这种写法会报错,因为是一个函数声明,不是一个函数表达式
    • 当圆括号出现在匿名函数的末尾想要调用函数时,它会默认将函数当成是函数声明。
    image-20210515022902350
  • 当圆括号包裹函数时,它会默认将函数作为表达式去解析,而不是函数声明。
    image-20210515023031129
  • 下面是一个函数表达式,所以可以执行
    image-20210515023106491
  • 声明式函数立即执行函数的两种写法

    • (function () {
            console.log("我是声明式函数");
      })()
      
    •  (function () {
            console.log("我是声明式函数");
       }());
      
<script>
    /* 
    立即执行函数:函数定义完后被立即执行
       特点:执行完后会立即销毁
     */

    //1.声明式函数
    /*
    function func() {
      console.log("我是声明式函数");
    } //(),后面会报错,因为这里不是表达式
   */
    //1.1 改进一:对函数加上();声明式函数立即执行函数调用
    /*
    (function func() {
      console.log("我是声明式函数");
    })()
    func(); //会报错,func is not defined,所以不要命名函数表达式]
    
    */
    //1.2 改进二:将函数和执行的()一起加上()
    (function () {
      console.log("我是声明式函数");
    }());
    (function () {
      console.log("我是声明式函数");
    })()
    //2.匿名函数表达式
    var test = function () { //变量test = undefined;因为函数默认返回undefined
      console.log("我是匿名函数表达式");
      return undefined;
    }(); //匿名函数表达式立即执行函数调用
    console.log(test);//undefined
  </script>

立即执行函数如下:

//立即执行函数
var result=(function(a,b){
  return a+b;  
})(10,20);
console.log(result);

七. 方法

函数也可以成为对象的属性,如果一个函数作为一个对象的属性保存,那么我们成为这个函数是这个对象的方法。调用这个函数就说调用对象的方法(method).相比于方法,它只是名称上的区别,并没有其他的区别。

函数举例:

//调用函数
fn();

方法举例:

//调用方法
obj.fn();

我们可以这样说,如果直接使用fn(),那就说明是函数调用。如果是发现XX.fn()这种方式,那就说明是方法调用

八.this关键字

解析器在调用函数每次都会向函数内部传递一个硬汉年的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称之为函数执行的上下文对象。

==根据函数的调用方式不同,this会指向不同的对象:==

  • 1.以函数的形式调用时,this永远是window。比如fun( );相当于Window.fun( );

  • 2.以方法的形式调用时,this是调用方法的那个对象

  • 3.以构造函数的形式调用时,this是新创建的那个对象

  • 4.使用call和apply调用时,this是指定的那个对象

    举例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<script>
  /* 
  this关键字
  - 1.以函数的形式调用时,this永远是window。比如fun( );相当于Window.fun( );
  - 2.以方法的形式调用时,this是调用方法的那个对象
  - 3.以构造函数的形式调用时,this是新创建的那个对象
  - 4.使用call和apply调用时,this是指定的那个对象

   */
   var Student={
     name:"jason",
     age:20,
     like:function(){
        console.log(this);//this就是Student对象
        console.log(this.name+"喜欢钓鱼");
     }
   }
   var fn=Student.like;
   var fn1=function(){
        console.log(this);//this就是Student对象
        console.log(this.name+"喜欢钓鱼");
     }
   console.log("-------------------------------");
   console.log(fn==fn1);//false,内幕才能地址不一样  
   console.log(fn==Student.like);//true 
   console.log(fn());
   console.log(Student.like());//this->Student
   Student.like();//this->window
</script>
<body>
  
</body>
</html>

8.1 改变this的指向

格式:

修改this的指针:
1.函数名.call(对象);
2.函数名.apply(对象);
3.bind();
  • 改变this指向有三种方式:apply,call,bind

  • apply和call的不同点在于传值不同:apply传值使用的是数组,call是直接写就可以

  • /* 
    修改this的指针:
    1.函数名.call(对象);
    2.函数名.apply(对象);
    3.bind();
     */
    var Student={
      name:"jason",
      like:function(){
       console.log(this);
       console.log(this.name+"钓鱼");
      }
    }
    //Student.like();//this指向Student对象
    var fn=Student.like;
    fn();//this指向window
    console.log(window.fn===fn);//true
    //改变this的指针
    var teacher={
      name:"老王",
    }
    //call;
    //fn.call(teacher);
    fn.apply(teacher)
    
  • image-20201027191615250

==apply,call,bind的使用案例:==

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    /* 
    修改this指针的异同点
    1.apply
    2.call
    3.bind:直接在对象上绑定,改变this指向
     */
     
     var Student={
       name:"小王",
       like:function(){
         console.log(this.name+"钓鱼");
         for(var i=0;i<arguments.length;i++){
               console.log(arguments[i]);
         }
       }.bind(Teacher),
     }
     var Teacher={
       name:"老王",
     }
    //apply和call的不同:调用方式不一样,传值方式也不一样
     //Student.like.call(Teacher,"唱","跳","rap");
     //Student.like.apply(Teacher,["唱","跳","rap"]);
     Student.like("唱","跳","rap");
  </script>
</head>
<body>
  
</body>
</html>
image-20201027191933284

九.arguments

在调用函数时,浏览器每次都会传递两个隐含的参数:

  • 1.函数的上下文对象 this
  • 2.封装实参的对象 arguments

例如:

var abc=function(){
   console.log(arguments);
   console.log(typeof arguments);
 }
 abc();
image-20201027134011814

arguments是一个类数组对象,它可以通过索引来操作数据,也可以获取长度。

arguments代表的是实参。在函数调用时,我们所传递的实参都会在arguments中保存,它只能在函数中使用

4.1 返回函数实参的个数:arguments.length

arguments.length可以用来获取实参的长度。

4.2 返回正在执行的函数:arguments.callee

arguments里面有一个属性叫callee,这个属性对应的函数对象,就是当前正在指向的函数对象。

在使用函数递归调用时,推荐使用arguments.callee代替函数名本身。

4.3 arguments可以修改元素

之所以说arguments是伪数组,是因为:arguments可以修改元素,但不能改变元素数组的长短。

举例:

/* 
函数的arguments对象
 */
 var abc=function(a,b,c,d){
   console.log(arguments);
   console.log(typeof arguments);//Object
   //长度
   console.log(arguments.length);//4
   console.log(arguments.callee);//
   //修改元素
   if(arguments[0]){
      arguments[0]=100;
   }
   console.log(arguments);
   console.log(a);//100,同时也修改了实参
 }
 abc(1,2,3,4);
image-20201027141502286

3.1 Function:函数(方法)对象

      //当形式参数与实际参数长度不一致时
      function fun4(a,b,c){
          //document.write(a+b+c);
          document.write(c);//当实际参数长度小于形式参数长时,形式参数默认为undefined类型
      }
      //fun4(1,2);
      
      function fun5(a,b){
         document.write(arguments[2]);//当实际参数长度大于形式参数时,在方法声明里内置对象(数组),arguments,封装所有实际参数
      }
      //fun5(1,2,3);
   ```
   //例:求不定长度的和
   
   function sum(){
       var total=0;//注意这里一定后面赋值0要加上
       for (var i = 0; i <arguments.length ; i++) {
           total += arguments[i];
       }
       return total;
   }
   document.write(sum(1,2,3,4,5));
   ```

十.函数练习题

10.1 练习一:实现一个加法计算器

 function addCalculate() {
      var total = 0;
      for (var i = 0; i < arguments.length; i++) {
        total += arguments[i];
      }
      return total;
    }
    console.log(addCalculate(10, 30, 60));

10.2 练习二:定义一个函数,传入宽高,计算矩形区域的面积

<script>
    /**
     * 练习二:定义一个函数,传入宽高,计算矩形区域的面积
     */
    var square = function (width, height) {
      return width * height;
    }
    var s = square(30, 10);
    console.log(s);
  </script>

10.3 练习三:定义一个函数,传入半径,计算圆形的面积

<script>
    /**
     * 练习三:定义一个函数,传入半径,计算圆形的面积
     */
    var circleSquare = function (radius) {
      return radius * radius * Math.PI
    }
    console.log(circleSquare(1));
  </script>

10.4 练习四:定义一个函数,传入n(n为正整数),计算1~n数字的和

<script>
    /* 
  练习四:定义一个函数,传入n(n为正整数),计算1~n数字的和
  */
    function getNumberSum(num) {
      var total = 0;
      for (var i = 1; i <= num; i++) {
        total += i;
      }
      return total;
    }
    console.log(getNumberSum(10)); //55
  </script>

10.5 练习五:定义一个函数,传入一个数组,对数组进行翻转

<script>
    /* 
  练习五:定义一个函数,传入一个数组,对数组进行翻转
  */
    var reverseArray = function (arr) {
      var temp;
      for (let i = 0; i < arr.length / 2; i++) {
        temp = arr[i];
        arr[i] = arr[arr.length - 1 - i];
        arr[arr.length - 1 - i] = temp;
      }
      return arr;
    }

    var arr = [10, 1, 3, 50, 6];
    arr = reverseArray(arr);
    console.log(arr); //[6,50,3,1,10]
  </script>

10.6 练习六:定义一个函数,传入一个数字数组,对数组中的数字进行排序

<script>
    /* 
    练习六:定义一个函数,传入一个数字数组,对数组中的数字进行排序
    */
    var arraySort = function (arr) {
      var temp;
      //冒泡排序,从小到大排列
      for (let j = 0; j < arr.length - 1; j++) {
        for (let i = 0; i < arr.length - 1; i++) {
          if (arr[i] >= arr[i + 1]) {
            temp = arr[i];
            arr[i] = arr[i + 1];
            arr[i + 1] = temp;
          }
        }
      }
      return arr;
    }
    var arr = new Array(20, 5, 30, 1, 6);
    arr = arraySort(arr);
    console.log(arr); //[1,5,6,20,30]
  </script>

10.7 练习七:定义一个函数,传入一个数字,求对应的菲波那切数列

<script>
    /* 
    练习七:定义一个函数,传入一个数字,求对应的菲波那切数列
    斐波那契数列指的是这样一个数列:
          0,1,1,2,3,5,8,13,21.......
    这个数列从第3项开始,每一项都等于前两项之和。
    */
    //var temp = 0;
    var arr = [];
    var fArr = function (n) {
      for (let i = 0; i < n; i++) {
        if (i == 0) {
          //temp = 0;
          arr.push(0);
        } else if (i == 1) {
          //temp = 1;
          arr.push(1);
        } else {
          if (i <= n) {
            // temp += 0 + 1;
            //arr.push(temp);
            arr[i] = arr[i - 2] + arr[i - 1]; //这个表达式就已经有将数值推进到数组里面的功能,不需要下面特意push()方法,如果有会重复
            //arr.push(arr[i]);
          } else {
            break;
          }
        }
      }
      return arr;
    }
    console.log(`传入${10},求对应的菲波那切数列`, fArr(10));
  </script>
image-20210514160648409
image-20210514160656174
<script>
    function f(n) {
      var sum = 1;
      for (let i = 0; i < n; i++) {
        if (i == 0) {
          var num1 = 0;
        } else if (i == 1) {
          var num2 = 1;
        } else {
          sum = num1 + num2;
          num1 = num2;
          num2 = sum;
        }
      }
      return sum
    }
    console.log(f(6));//5

十一.递归

 <script>
    /* 
   递归调用
      1.1 一个函数可以调用另一个函数
      1.2 一个函数调用自己就是递归
      1.3  在开发中尽量避免使用递归:
             1.3.1 递归如果没有写好结束条件,意味着无线循环调用
             1.3.2 递归调用非常占用栈空间内存

 */
    //1.1 一个函数可以调用另一个函数
    function test01() {
      console.log("test01函数");
      test02();
    }
    test01();

    function test02() {
      console.log("test02函数");
    }
    //1.2 一个函数调用自己就是递归
    function test() {
      //console.log('test函数');没有结束条件会造成内存耗尽
      test();
    }
    test();
  </script>
<title>斐波那契数列递归调用</title>
  <script>
    function f(n) {
      if (n === 1) {
        return 0
      } else if (n === 2) {
        return 1;
      } else {
        return f(n - 1) + f(n - 2);
      }
    }
    console.log(f(6)); //5
  </script>

十二.函数的调用栈

image-20210514174712397

十三.全局变量和局部变量

  • 在JavaScript(ES5之前)中没有块级作用域的概念,但是函数可以定义自己的作用域。
  • 什么是全局变量和局部变量?
    • ==定义在函数内部的变量,被称之为局部变量。==
    • ==定义在script标签中的变量,被称之为全局变量。==
  • 在函数中,访问变量的顺序是什么呢?
    • ==优先访问自己函数中的变量,没有找到时,在全局中访问。==
image-20210515002132715
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>变量作用域</title>
  </head>

  <body>

  </body>
  <script>
    /* 
    1.变量作用域:变量能在哪个范围内被使用,这个范围就是变量作用域
    2.在JavaScript(ES5之前)中没有块级作用域的概念,
    3.但是函数可以定义自己的作用域。
    4.什么是全局变量和局部变量?
          定义在函数内部的变量,被称之为局部变量。
          定义在script标签中的变量,被称之为全局变量。
    5.在全局中默认是不能访问局部变量的
    5.在函数中,访问变量的顺序是什么呢?
         优先访问自己函数中的变量,没有找到时,在全局中访问      

    */
    //1.块没有自己的作用域
    var age = 18; {
      var name = "jason";
    }
    console.log(name, age);

    //2.只有函数才有作用域
    //优先访问自己函数中的变量,没有找到时,在全局中访问  
    function getName() {
      var name = "tom";
      var age = 20;
      console.log(age); //20
    }
  </script>

</html>

十四.值传递和引用传递

1.在 JavaScript 中数据类型可以分为两类:

  • 原始数据类型值 primitive type,比如Undefined,Null,Boolean,Number,String。
  • 引用类型值,也就是对象类型 Object type,比如Object,Array,Function,Date等。

2.声明变量时不同的内存分配

  • 原始值:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。这是因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。
  • 引用值:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

14.1 按值传递

 //1.值传递
     function test(n) {
      n = "kobe";
    }
    var name = 'why';
    test(name);
    console.log(name); //why 
image-20210515180954318

14.2 按引用传递

 //2.引用传递
    function func(arr) {
      arr[0] = "jason";
    }
    var array = [1, 2, 3];
    func(array)
    console.log(array); //['jason',2,3]
image-20210515182559155
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容