面向对象之原型对象的继承day03

JavaScript面相对象的继承

一.in操作符与hasOwnProperty的用法和区别

in操作符:

①遍历对象

②判断(检查)对象中是否存在指定的属性(实例成员 + 原型成员)
语法:'属性' in 对象

hasOwnProperty:

检查对象是否拥有这个属性(只检查自己的成员,实例成员)

语法:对象.hasOwnProperty(属性|方法);

    <script>
//1.创建一个空对象
var o = {};

//2.提供一个已经有的对象obj
var obj = {
    name:'对象的属性',
    age:20,
    demo:{nme:"lalala"},
    sayHello:function (){
        console.log('hello');
    }

};

//3.混入式继承(把原有对象的所有属性和方法都拷贝给新的对象)
for (var k in obj){
    if(obj.hasOwnProperty(k)) {
        o[k] = obj[k];
    }
}

//注意:利用for...in赋值和直接赋值不一样,for...in赋值只有引用类型的属共享,其他的值类型不共享,

//直接赋值的话,直接赋值:完全共享.赋值的是地址指针,所得属性都是共享的.

//4,打印查看o对象

console.log(o.des);
console.log(o);//object
console.log(obj.des);//undefined



obj.sayHello = function (){
    console.log('改变了');
};


//5.问题:新对象的引用类型属性和旧对象中的对应属性是否相等
console.log(o.sayHello == obj.sayHello,"___");//true
console.log(o.sayHello == obj.sayHello);//false
//注意:在修改方法的时候,这里的方法是使用函数声明了.重新设置了一个声明的函数,重新定义了一个函数的地址空间,所以这里的函数方法不是共存的所以方法不相等.

console.log(o.sayHello);
console.log(obj.sayHello);
//问题:那么两个对象中的其中某个修改了该属性,则另一个对象会受到影响

console.log(o.demo == obj.demo);
o.demo.nme = "nnnn";
console.log(o.demo == obj.demo);

</script>

补充说明:

eg:<script>
function Person(){
    this.name = "默认"
}

Person.prototype.hi = "hi";
var p1 = new Person();
var o = {};

/*for (var k in p1)
{
    if(p1.hasOwnProperty(k))
    {
        o[k] = p1[k];
    }

}

console.log(o.hi);*/

</script>

<script>
var obj = {
    name:"123",
    showName:function(){
        console.log("12345");
    }
}

   /* var obj2 = obj;*/
    var obj2 = {};

//直接赋值:完全共享
 /*   obj.name = "sss";
    console.log(obj2.name);*/
    for(var k in obj){
        if(obj.hasOwnProperty(k)){
            obj2[k] = obj[k];
        }
    }
    console.log(obj.showName == obj2.showName);//true
    obj.showName = function (){
        console.log('改变了');
    }
    console.log(obj.showName == obj2.showName);

</script>

图形解析:
(1)



(2)



(3)

二.原型对象的补充说明

1.构造函数有一个相关联的原型对象,这个原型对象默认是一个空对象{}(实际上这个原型对象拥有一个属性为constructor属性的对象).

2.构造函数的原型对象本身是一个Object类型的,Person.prototype (原型对象)是Object,他的构造函数是Object

3.使用构造函数创建出来的对象会拥有一个构造器属性(constructor),该属性指向创建当前对象的构造函数.

4.对象本身没有构造器属性,这个属性是从原型对象上继承来的.

eg:

<script>
    function Person(){

    }
    var p1 = Person();

   // console.log(p1.constructor == Person);//报错
    console.log(Person.prototype.constructor == Person);//true
    
</script>
console.log(Person.prototype);//Object
var o = {};
console.log(o);

console.log(Person.prototype.constructor);//Person这个对象的(访问的是自己的实例属性)
delete Person.prototype.constructor;
console.log(Person.prototype.constructor);//Object这个对象的(访问的是原型对象上面的属性)

问题???

构造函数的原型对象(空对象|Object类型),他的构造函数是Object,那么他的构造器属性难道不应该是Object吗?

解答:

构造器的原型对象身上其实有两个(constructor)属性(实例属性 + 构造函数的原型对象的原型对象上面的属性)

图形解析:

image

三.继承的几种实现方案

  1. 属性拷贝(浅拷贝)
  2. 原型式继承(A.B.C)
  3. 原型链继承
  4. 借用构造函数
  5. 组合继承
  6. (深拷贝 + 原型式)组合继承

知识点1:属性拷贝和直接赋值的区别:

01 属性拷贝:

引用类型: (数组):引用会共享,如果重新设置,那么会切断联系
引用类型:(函数):函数会共享,如果重新设置,那么会切断联系.

==注意==
属性拷贝的包括成员和原型对象

02 直接赋值:

直接赋值:完全共享!

数组: 数组会共享,如果重新设置,那么另一个对象会受影响.
函数: 函数会共享,如果重新设置,那么另一个对象会受影响.

==1.属性拷贝继承:==


eg1:
<script>
var obj1 = {
    arr :[1,2,3],
    show:function (){
        console.log('show');
    }
}

var o = {};
//属性拷贝
for(var i in obj1){
    o[i] = obj1[i];
}
console.log(o);
console.log(o.arr);
console.log(obj1.arr);

//重新设置值
obj1.arr = ['demo1','demo2'];
console.log(o.arr);
console.log(obj1.arr);//受影响
</script>

eg2:
<script>
function Person(){
    this.name = '默认的名称';
    this.friends = ['123','456','789'];
}
Person.prototype.hi = 'hi';
var p1 = new Person();
var o = {};
//属性拷贝
for(var k in p1){
    if(p1.hasOwnProperty(k)){//排除了拷贝原型对象
        o[k] = p1[k];
    }
}
console.log(o);
console.log(p1);
o.name = '我是一个数字';
console.log(p1.name);//默认名称
p1.friends.push('我给改变了');
console.log(o.friends);
console.log(p1.hi);
console.log(o.hi);//undefined
</script>

图像解析1:

image

图形解析2:
image

==直接赋值拷贝==

eg1:
<script>
var demo1 = {
    arr:[1,2,3],
    show:function (){
        console.log('show');
    }
};
//直接赋值
var demo2 = demo1;
console.log(demo1.arr);
console.log(demo2.arr);

demo1.arr = ['test1','test2'];
console.log(demo1.arr);
console.log(demo2.arr);

demo1.show();
demo2.show();
demo1.show = function (){
    console.log('hahaha');
}
demo1.show();
demo2.show();
</script>

图形解析:

image

==2.原型式继承==

A 利用对象的动态特性 (对象-原型)

B 字面量直接替换 (对象-原型)

C 设置子构造函数的原型对象 = 父构造函数的原型对象 (子构造函数-父构造函数)

问题:可以获得父构造函数原型对象上面的属性和方法,但是无法获得父构造函数的实例对象上的属性和方法.

eg:
A 利用对象的动态特性 对象-原型
<script>
function Person (name){
    this.name = name;
}
Person.prototype.des = '描述信息';
var p1 = new Person('张三');
</script>

B 字面量直接替换     对象-原型
<script>
function Person(name){
    this.name = name;
}
Person.prototype = {
    constructor:Person,
    des:'默认的描述信息'
}
var p1 = new Person('张三');
</script>


C 设置子构造函数的原型对象=父构造函数的原型对象  子构造函数-父构造函数
<script>
function Person(){
    this.name = '张三';
}
Person.prototype = {
    constructor:Person,
    des:'默认的描述信息',
    showDes:function (){
        console.log(this.des);
    }
}

function Boy() {
    this.lol = function (){
        console.log('lol');
    }
}


//设置子构造函数的原型对象为父构造函数的原型对象,便可以继承父构造函数的原型对象的属性和方法
Boy.prototype = Person.prototype;

var boy1 = new Boy();
console.log(boy1.des);//默认描述信息
boy1.showDes();
boy1.lol();
</script>

图形解析:

image

==3.扩展内置对象==

定义:
把需要共享的属性和方法写在内置构造函数的原型对象上.

问题:

01 原型对象上面所有的属性和方法都会被该构造函数创建出来的对象共享,共享可能会导致一些问题.

02 如果所有的开发人员都往内置构造函数的原型对象上面添加属性和方法,那么原型上面的属性和方法会越来越多,难以管理,难以维护,还可能会出现覆盖问题.

eg:
<script>
//需求:要求给arr1添加属性name|desLog
var arr1 = [1,2,3];
console.log(arr1);//arr1的构造函数为Array
console.log(arr1.constructor);

arr1.name = 'arr1的名称';
arr1.desLog = function (){
    console.log('arr1的des');
};

console.log(arr1);

//需求:要求给arr2添加属性name|desLog
var arr2 = ['demo1','demo2'];
arr2.name = 'arr2的名称';
arr2.desLog = function (){
    console.log('arr2的des');
}
console.log(arr2);

//需求:要求所有的数组都拥有name和desLog方法?
</script>
<script>
Array.prototype.name = '默认的名称';
Array.prototype.desLog = function (){
    console.log('默认的描述信息');
}

var arr1 = [1];
var arr2 = ['demo1'];
console.log(arr1.name);
console.log(arr2.name);
arr1.desLog();
arr2.desLog();
</script>
注意:共享可能会导致一些问题如下
<script>
Array.prototype.name = 'name';
var arr1 = [1,2,3,4];
for (var i = 0;i<arr1.length;i++){
    console.log(i,arr1[i]);
}
console.log('---------------');
for(var i in arr1){
    console.log(i,arr1[i]);//会打印出name name
}
//两次遍历打印的结果不一样
</script>

安全的扩展内置对象:

01 提供一个自定义的构造函数(空函数)(MyArray)

02 设置该构造函数的原型对象为内置构造函数的实例

03 在构造函数的原型对象上面添加属性和方法

04 使用自定义的构造函数来创建对象并且使用

 eg:
 <script>
//1.提供一个自定义的构造函数
function MyArray(){}
    //2.设置该构造函数的原型对象为内置构造函数的一个实例
    MyArray.prototype = new Array();//获得Array的所有的属性和方法
    //MyArray.prototype = Array.prototype;

    //3.设置原型对象
    MyArray.prototype.name = '默认名称';
    MyArray.prototype.desLog = function (){
        console.log('哈哈');
    }

    //4.使用自定义的构造函数来创建对象并且使用
    var myArr01 = new MyArray();
    myArr01.push('123','345');
    console.log(myArr01);
    console.log(myArr01.name);//默认名称
    myArr01.desLog();//哈哈

    var myArr02 = new MyArray();
    console.log(myArr02);

//其他的开发人员
function OtherArray (){};
OtherArray.prototype = new Array();
OtherArray.prototype.name = '默认名称++++++++++++';
OtherArray.prototype.desLog = function (){
    console.log('嘿嘿');
}

var other1 = new OtherArray();
other1.push('demo1','demo2');
console.log(other1);
console.log(other1.name);

var arr = new MyArray();
console.log(arr.name);//默认名称
</script>

图形解析:

image

原型链的结构

  1. 其实在js中所有的对象都是由构造函数创建出来的
  2. 所有的构造函数的原型对象所有一个相关联的原型对象
  3. 所有构造函数的原型对象本身也是一个对象,所以构造函数的原型对象也是由构造函数创建出来的
  4. 构造函数的原型对象的构造函数也有一个与之相关联的原型对象,这个原型对象本身也是一个对象
  5. 构造函数的原型对象的原型对象也有自己的构造函数
  6. 构造函数的原型对象的原型对象也有自己的原型对象.以上会形成一种链式结构,这个结构就是原型链.
  7. 在原型链的顶端(终点)Object.prototype
  8. Object.prototype本身也是一个对象,所以也有自己的构造函数===>Object
  9. Object.prototype的原型对象应该是它的构造函数的原型对象 Object.prototype (推理 不成立)

Object.prototype.__proto__=Object .prototype.constructor.prototype[Object.prototype]

  1. js处理:Object.prototype.__proto__ = null;
    图形解析:
    image

原型链中属性的搜索规则:

  1. 对象在访问属性的属性的时候,首先先查找实例对象的成员(属性|方法)

  2. 如果找到了,那么就直接使用,如果没有找到,那么就去它的原型对象上面查找,如果找到了就直接使用.

  3. 如果原型上面也没有找到,那么就继续搜索原型对象的原型对象,如果找到了就继续使用,如果没有找到,那么就继续上面的过程.

  4. ...重复上面的搜索过程

  5. 如果查找到Object.prototype也没有找到,那么句undefined或者是报错.

     eg:
     <script>
     function Person(){
         this.name = '默认'
     }
     Person.prototype.name = '原型上面的名称';
     Person.prototype.age = '原型上面的年龄';
    
     function Boy(){
         this.lol = 'lol';
         this.name = '男孩';
     }
    
     Boy.prototype = new Person();
     var boy = new Boy();
    
     console.log(boy.name);//男孩
     console.log(boy.age);//原型上面的年龄
     console.log(boy.des);//undefined
     </script>
    

==4.原型链继承==
形式: 子构造函数.prototype = new 父构造函数();

步骤:

  1. 提供构造函数

  2. 设置属性和方法

  3. 设置继承(原型链继承)

  4. 修正构造器属性

     eg:
     <script>
     function A(){
         this.a = 'a';
     }
     A.prototype.desA = 'desA';
    
     function B(){
         this.b = 'b';
     }
    
     //设置原型链继承
     B.prototype = new A();
     var b = new B();
     console.log(b.a);
     console.log(b.desA);
     </script>
    

使用注意点:

  1. 在设置完原型链接继承之后,要修正构造函数的原型对象的构造器属性
  2. 设置原型对象的属性和方法这个操作需要注意位置,建议在完成原型链继承之后再添加成员(属性和方法)
  3. 在设置完原型链继承之后,不能使用字面量的方式来替换当前构造函数的原型对象(如果替换,继承结构会丢失)

不足:

01 无法向父构造函数传递参数

02 父构造函数的实例属性变成了子构造函数创建出来的对象的原型属性

    eg:
<script>
function Person(name){
    this.name = name;
    this.friends = ['小花','哗啦','巴拉']
}

Person.prototype.hi = 'hi';
function Boy(){}
//设置原型链继承
Boy.prototype = new Person('张三');
Boy.prototype.constructor = Boy;

var boy = new Boy();
console.log(boy);

var boy2 = new Boy();
console.log(boy2);

console.log(boy.friends);//?
console.log(boy2.friends);//?

boy.friends.push('taotao');
console.log(boy.friends);
console.log(boy2.friends);

</script>

==5.Object.create的方法说明:==

  • Object是内置构造函数

  • Object.Create()静态方法(直接添加在构造函数上面的方法)

  • 作用:创建对象,并且指向原型对象

  • 注意点:该方法是ES5推出,所以有兼容性问题

      eg:
      <script>
      var obj = {
          name:'张三'
      }
    
     /* var o = {};
      o.__proto__ = obj;
      console.log(o.name);*/
    
      var o = Object.create(obj);//创建一个对象,并且指定这个对象的原型对象为obj
      console.log(o);
      </script>
    

兼容性处理:

1.先判断是否支持create方法,如果不支持,那么我们就是要临时的构造函数来设置原型对象并创建对象的实例

2.先判断是否支持,如果不支持,那么我们就为Object主动地提供create方法

3.抽取一个函数,把设置原型的过程封装起来

eg:
<script>
var demo = {
    name:'demo'
}
if(typeof Object.create == 'function'){
    var o = Object.create(demo);
}else{
    //var o = {};
    //o.__proto__ = demo;   //不推荐这样写  换一种写法
    //设置原型对象
    //访问原型对象的几种方法
    //01 构造函数.prototype
    //02 对象.__proto__
    //03 Object.getPrototypeOf
    function F(){}
    F.prototype = demo;
    var o = new F();
}
</script>

<script>
    var demo = {
        name:'demo'
    }
    if(typeof Object.create == 'function'){
        var o = Object.create(demo);
    }else{
        Object.create = function (){
            function F(){}
            F.prototype = demo;
            var o = new F();
        }
    }
</script>
<script>
    function Create(obj){
        if(typeof Object.create == 'function'){
            var o = Object.create(obj);
        }else{
            function F(){}
            F.prototype = obj;
            return new F();
        }
    }

    var obj = {age:23};
    var o = Create(obj);
</script>

==6.Object.assign()方法==

作用: 拷贝多个对象的属性(不会拷贝对象的原型成员)而利用for...in...拷贝会拷贝原型成员

语法:Object.assign(目标对象,要拷贝的对象...);

eg:
<script>
var obj1 = {
    name:'默认的名称'
}

var obj2 = {
    age:23
}

var obj3 = {
    book:'小说'
}

var obj = {};
Object.assign(obj,obj1,obj2,obj3);
console.log(obj);
</script>
<script>
function Person (){
    this.name = '张三'
}
Person.prototype.hi = 'hi';

var p1 = new Person();
var o = {};
Object.assign(o,p1);
console.log(o);
console.log(o.hi);//undefined
</script>

==7.call和apply的用法说明==

call和apply是js中所有对象都拥有的两种方法

作用:借用对象的方法
call和apply的作用一模一样

区别:传递参数不一样

call:
第一个参数:谁调用(借用)就传递谁,传递的是谁,那么函数内部的this就指向谁

其他参数:参数列表的方式传递
对象.方法.call(this绑定的对象,参数1,参数2,参数3,...)

apply:
第一个参数:谁调用(借用)就传递谁,传递的是谁,那么函数内部的this就指向谁

其他参数:数组元素
对象.方法.apply(this绑定的对象,[参数1,参数2,参数3,...])

eg:
<script>
var obj1 = {
    name:'张三',
    showName:function (param1,param2){
        console.log(this.name + param1 + param2);
    }
}

var obj2 = {
    name:'李四'
}

/*obj1.showName();
obj2.showName();*///obj2要使用obj1的showName方法

obj1.showName.call(obj2,'demo1','demo2');
//obj1.showName.apply(obj2);
obj1.showName.apply(obj2,['demo1','demo2']);
</script>

==8.this.的指向说明详解:==

this 指向的永远都是一个对象(在非严格模式下)
函数的调用

  • 01 以普通函数方式调用 this -->window

  • 02 以对象的方法来调用 this --->对象

  • 03 new 构造函数的方式来调用 this--->指向内部新创建的对象

  • 04 函数上下文的方式来调用(call|apply) this--->绑定的第一个参数 如果不传递参数那么默认指向window

      eg:
      <script>
      function func(){
          console.log(this);
      }
    
      //1.以普通函数调用
      func();//window
    
      var obj = {name:'test'};
      obj.funcTest = func;
      //2.以对象的方法来调用
      obj.funcTest();//obj
    
      var o = {
          test:function (){
              console.log(this);
          }
      }
      o.test.call();//window
      </script>
    

==9.借用构造函数继承的基本写法.==

借用构造函数继承的基本写法:

通过借用父构造函数获得父构造函数的实例属性
思考:无法获得父构造函数的原型成员

eg:
<script>
function Person(name){
    this.name = name;
}
Person.prototype.hi = 'hi';

function Boy(name,lol){
    //在构造函数内部默认会创建空对象并且赋值给this
    this.lol = lol;
    //获取Person构造函数的实例属性
    Person.call(this,name);
}

var boy = new Boy('张三','英雄联盟');
console.log(boy.name);

var boy2 = new Boy('李四','CF');
console.log(boy2.name);
console.log(boy.lol);
console.log(boy2.lol);

console.log(boy.hi);//undefined
console.log(boy2.hi);//undefined

</script>

组合构造函数继承的基本写法:

eg:
<script>
function Person(name){
    this.name = name;
}
Person.prototype.hi = 'hi';

function Boy(name,lol){
    //在构造函数内部默认会创建空对象并且赋值给this
    this.lol = lol;
    //获取Person构造函数的实例属性
    Person.call(this,name);
}

//设置原型链继承
Boy.prototype = Person.prototype;//原型式继承C(继承原型对象)

var boy = new Boy('张三','英雄联盟');
console.log(boy.name);

var boy2 = new Boy('李四','CF');
console.log(boy2.name);
console.log(boy.lol);
console.log(boy2.lol);

console.log(boy.hi);//hi
console.log(boy2.hi);//hi

console.log(boy);
</script>

==10.深拷贝和浅拷贝:==

浅拷贝:for...in obj[k] = obj1[k] 引用类型会分享

深拷贝:对浅拷贝的方式进行改进

eg:
<script>
var o = {
    name:'张三',
    friends:['demo1','demo2'],
    car:{
        type:'奔驰'
    }
}

function deepCopy(obj1,obj2){
    obj1 = obj1 || {};
    for(var k in obj2){
        if(obj2.hasOwnProperty(k)){
            //判断是值类型还是引用类型
            if(typeof obj2[k] == 'object'){
                //如果是引用类型,那么就再次循环
                //注意:obj1[k]要做初始化处理 ES5
                obj1[k] = Array.isArray(obj2[k]?[]:{}); //检查是什么类型的?如果是数组[],如果是对象{}
                deepCopy(obj1[k],obj2[k]);
            }else{
                obj1[k] = obj2[k];//值类型
            }
        }
    }
}

var demo  = {};
deepCopy(demo,o);
console.log(demo);
demo.car.type = '奥迪';
console.log(o.car.type);
console.log(o);
console.log(demo);
</script>

==11.深拷贝与借用构造函数实现继承==

01 通过借用父构造函数获得父构造函数的 实例属性

02 思考:无法获得父构造函数的原型成员

eg:
<script>
function deepCopy(obj1,obj2) {
    obj1 = obj1 || {};
    for(var k in obj2)
    {
        if (obj2.hasOwnProperty(k)){
            //判断是值类型还是引用类型
            if (typeof obj2[k] == "object")
            {
                //如果是引用类型,那么就再次循环
                //注意:obj1[k]要做初始化处理 ES5
                obj1[k] = Array.isArray(obj2[k])?[]:{};   //检查是什么类型的?如果是数组[],如果是对象{}
                deepCopy(obj1[k],obj2[k]);
            }else
            {
                obj1[k] = obj2[k];  //值类型
            }
        }
    }
}
function Person(name){
    this.name = name;
}
Person.prototype.hi = 'hi';
Person.prototype.car = {
    type:'飞船'
}

function Boy(name,lol){
    //在构造函数内部默认会创建空对象并且赋值给this
    this.lol  = lol;
    //获取Person构造函数中的实例属性
    Person.call(this,name);
}

//设置原型链继承
//Boy.prototype = new Person();
//Boy.prototype = Person.prototype;     //原型式继承C
deepCopy(Boy.prototype,Person.prototype);

var p1 = new Person();
var boy = new Boy('李四','CF');
console.log(p1.car);//飞船
console.log(boy.car);//飞船

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

推荐阅读更多精彩内容