2018-02-27 js笔记

Number:

javascript不区分整数和浮点数,统一用number表示。可以直接做四则运算。

{

124,

0.345,

1.23,

-99,

NaN,

Infinity //表示无限大,当数值超过了javascript的Number所能表示的最大值是,就显示Infinity

}

字符串是以单引号‘’或双引号“”括起来的任意文本。‘’或“”本身只是一种表示方式,不是字符串的一部分。

布尔值只有true或false

运算符==,它会自动转换数据类型再比较,很多时候会得到非常诡异的结果

运算符===,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较

因此,不要使用==比较,始终坚持使用===比较

另一个例外是NaN,这个特殊的Number与其他值都不相等,包括它自己:

NaN == NaN //false

唯一等判断NaN的方法是通过isNaN()函数:

isNaN(NaN); //true

最后要注意浮点数的相等比较:

1/3 == (1-2/3);//false

这不是javascript的设计缺陷,浮点数在运算工程中会产生误差,因为计算机无法精确表示

无限循环小数,要比较两个浮点数是否相等,只能计算它们之差的绝对值,看是否

小于某个阈值:

Math.abs(1/3 == (1-2/3)) < 0.0000001; //true

null 和 undefined

null 表示一个‘空’的值,它和0以及空字符串‘’不同,0是一个数值,''表示长度为0的字符串,而null表示‘空’

null 表示一个空的值,而undefined表示值未定义。大多数情况下,我们都应该用null。undefined 仅仅在判断函数参数是否传递的情况下有用。

数组

数组是一组按顺序排列的集合,集合的每个值称为元素。javascript的数组可以包括任意数据类型。

[1,2,4,56]

另一种创建数组的方法是通过Array()函数实现:

new  Array(1,2,34)

然而,处于代码的可读性考虑,强烈建议直接使用[]

数组的元素可以通过索引来访问。索引的起始值为0

对象

javascript 的对象是一组由键-值组成的无序集合:

var person = {

name: 'xiaoxia',

age: '25',

city:'hz'

}

javascript对象的键都是字符串类型,值可以使任意数据类型。每个键又称为对象的属性

要获取一个对象的属性,我们用对象变量.属性名的方式

person.name; // xiaoxia

变量

在javascript中,使用等号=对变量进行赋值,可以把任意类型赋值给变量,同一个变量可以反复赋值,

而且可以是不同类型的变量,但是要注意只能用var申明一次

javascript严格模式:

'use strict';

避免不用var申明的变量会被视为全局变量的缺陷。

模板字符串

要把多个字符串连起来,可以用+号链接:

var name = '小明'

var age = 20

var message = name + age;

es6语法:

var message = '${name},${age}'

操作字符串的方法:

var s = 'hello xiaoxia';

s.length;//13

要获取字符串某个指定位置的字符,使用类似Array的下标操作,

s[0];//h

s[33];//undefined超出范围的索引不会报错,但一律返回undefined

特别注意的是:字符串是不可变的,如果对字符串的某个索引值赋值,不会有任何错误,但是,

也没有任何效果

toUpperCase//把一个字符串全部变为大写

var s = 'hexiaoxia';

s.toUpperCase();

toLowerCase//把一个字符串全部变为小写

s.toLowerCase();

indexOf()//会搜索指定字符串出现的位置

s.indexOf('xiao');//2

s.indexOf('Xiao');//返回-1,没有找到指定的子串

s.substring(7)//索引7开始到结束

s.substring(0,5)//从索引0开始到5(不包括5)

数组的方法


splice()改变了数组结构。

var arr = [1,24,4,5,7,8];

arr.length;

indexOf()//Array也可以通过indexOf()来搜索一个指定的元素的位置

arr.indexOf(24)//1

slice()//就是对应String的substring()版本,它截取Array的部分元素,然后

返回一个新的Array:

arr.slice(0,3);//1,24,4

如果不给slice()传递任何参数,它就会从头到尾截取所有元素,利用这一点,

我们可以很容易地复制一个Array:

var aCopy = arr.slice();

push和pop

push()向Array的末尾添加若干元素,pop()则把Array的最后一个元素删除掉

unshift和shift

如果要往Array的头部添加若干元素,使用unshift()方法,shift()方法则把Array的第一个元素删掉

sort()可以对当前Array进行排序,它会直接修改当前Array的元素位置,直接调用时,按照默认顺序排序

reverse

reverse()把整个Array的元素给掉个个,也就是反转

splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素:

var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];

// 从索引2开始删除3个元素,然后再添加两个元素:

arr.splice(2, 3, 'Google', 'Facebook'); // 返回删除的元素 ['Yahoo', 'AOL', 'Excite']

arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']

// 只删除,不添加:

arr.splice(2, 2); // ['Google', 'Facebook']

arr; // ['Microsoft', 'Apple', 'Oracle']

// 只添加,不删除:

arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因为没有删除任何元素

arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']

concat

concat()方法把当前的Array和另一个Array连接起来,并返回一个新的Array

join()方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串:

var arr = ['A', 'B', 'C', 1, 2, 3];

arr.join('-'); // 'A-B-C-1-2-3'

Javascript 的对象是一种无序的集合数据类型。

访问属性是通过.操作符完成的,但这要求属性名必须是有效的变量名。如果属性名

包含特殊字符,就必须用‘’括起来:

var xiaoxia = {

name: 'xiaoxia',

'family': 'kkk'

};

xiaoxia['family'] // 'kkk'

javascript 对象的所有属性都是字符串,不过属性对应的值可以是任意数据类型

如果访问一个不存在的属性会返回undefined

由于javascript对象是动态类型,可以自由地给一个对象添加或删除属性

var xiaobin = {

name: 'xiaobin'

}

xiaobin.age = 21

delete xiaobin.age

xiaobin.age // undefined

要检测对象是否拥有某一属性,可以用in 操作符:

'name' in xiaobin //true

'age' in xiaobin //false

不过要小心,如果in判断一个属性存在,这个属性不一定是xiaobin的,它可能是xiaobin

继承得到的。

'toString' in xiaobin //true

要判断一个属性是否是xiaobin自身拥有的,而不是继承得到的,可以用hasOwnProperty()方法:

xiaobin.hasOwnProperty('toString');//false

Javascript 把null,undefined,0,NaN和空字符串''视为false,其他值一概视为true

for...in

for循环的一个变体是for...in 循环,它可以把一个对象的所有属性依次循环出来

var o = {

name: 'xiaobin',

age: 21,

city:'beijing'

}

for(var key in o) {

console.log(key); // name,age,city

}

Map

Map是一组键值对的结构

初始化Map需要一个二维数组,或者直接初始化一个空Map

var m = new Map();

m.set('Xiaobin',21);

m.get('Xiaobin');//21

m.has('Xiaobin');

m.delete('Xiaobin');

m.get('Xiaobin');//undefined

函数:

函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。

因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。

如果没有return 语句,函数执行完毕后会返回结果,

只是结果为undefined.function abs(x) { if (x >= 0) { return x; } else { return -x; }}

由于Javascript的函数也是一个对象,上述定义的abs()函数名abs可以视为指向该函数的变量

var abs = function(x) { for (var i=0; i= 0) {

return x;

} else {

        return -x;

    }

}

abs(4);//4

abs(-1);//-1

在这种方式下,function(x) {...} 是一个匿名函数,它没有函数名,但是,这个匿名函数赋值给了

变量abs,所以,通过abs就可以调用该函数。

为了避免函数的参数收到undefined,计算结果为NaN,可以对参数进行检查:

function abs(x) {

if(typeof x !== 'number') {

throw 'Not a number';

}

}

arguments

Javascript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前的调用者

传入的所有参数。arguments类似Array 但它不是Array:

for (var i=0; i < arguments.length; i++) { console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30 }

由于Javascript引擎在行末自动添加分号的机制,return语句需要注意了。

所以正确的多行写法是:

return {

}

全局作用域

不在任何函数内定义的变量就具有全局作用域。实际上,javascript默认一个全局对象window,

全局作用域的变量实际上被绑定到window的一个属性。

var course = 'Learn Javascript';

window.course ;//'Learn Javascript'

由于函数定义有两种方式,以变量方式var foo = function () {}定义的函数实际上也是一个全局变量,因此,顶层函数的定义也被视为一个全局变量,并绑定到window对象:

'use strict';

function foo() {

    alert('foo');

}

foo(); // 直接调用foo()

window.foo(); // 通过window.foo()调用

名字空间:全局变量会绑定到window上,不同的javascript文件如果使用了相同的全局变量,

或者定义了相同名字的顶层函数,都会造成命名冲突,减少冲突的一个方法是把自己的所有

变量和函数全部绑定到一个全局变量中。

例如:

var MYAPP = {}

MYAPP.name = 'xiaobin';

MYAPP.version = 1.0;

MYAPP.foo = function() {

return 'foo';

}

方法:

在一个对象中绑定函数,称为这个对象的方法。

function getAge() {

var y = new Date().getFullYear();

return y-this.birth;

}

var xiaobin = {

name: 'xiaobin',

birth: 1996,

age: function() {

var y = new Date().getFullYear();

return y-this.birth;

},

age1: getAge

};

xiaobin.age();

一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是xiaobin

这个变量。

如果以对象的方法形式调用,比如xiaobin.age(),该函数的this指向被调用的对象。

如果单独调用函数,比如getAge(),此时,该函数的this指向全局变量,也就是window.

apply

在一个独立的函数调用中,还是可以控制this的指向的,

要指定函数的this指向哪个对象,可以用函数本身的apply方法,第一个参数就是需要绑定的

this变量,第二个参数是Array,表示函数本身的参数。

用apply修复getAge()调用:

function getAge() {

var y = new Date().getFullYear();

return y-this.birth;

}

var xiaobin = {

name: 'xiaobin',

birth: 1996,

age:getAge

};

xiaobin.age();//21

getAge.apply(xiaobin,[]);//21,this指向xiaoming,参数为空

call() 与 apply()类似,唯一区别是:

apply()把参数打包成Array再传入;

call()把参数按顺序传入

Math.max.apply(null, [3, 5, 4]); // 5

Math.max.call(null, 3, 5, 4); // 5

高阶函数

既然变量可以指向函数,函数的参数能接收变量,那个一个函数就可以接收另一个函数作为参数,

这种函数就称之为高阶函数

map()方法定义在Javascript的Array中,我们调用Array的map()方法,传入我们自己的函数,就得到了一个

新的Array作为结果。

'use strict';

function pow(x) {

return x*x

}

var arr = [1,2,3,4,5,6,7,8];

var results = arr.map(pow);//1,4,9,16,25,36,49,64

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

arr.map(String); // ['1', '2', '3', '4', '5', '6', '7', '8', '9']

filter()用于把Array的某些元素过滤掉,然后返回剩下的元素。和map()不同的是,

filter()把传入的函数依次作用于每个元素,然后根据返回值true还是false决定保留还是

丢弃该元素。

var arr = [1,3,4,5,6,7];

var r = arr.filter(function(x) {

return x % 2 !== 0;

});

//只保留基数

filter()接收的回调函数,可以有多个参数,通常仅使用第一个参数,表示Array的某个元素,回调函数还可以

接收另外两个参数,表示元素的位置和数组本身:

var r = arr.filter(function(element,index,self) {

console.log(element);//1,3,4,5,6,7

console.log(index);//0,1,2,3,4,5

console.log(self);//arr

return true;

});

利用filter可以巧妙的去除Array的重复元素:

var r = arr.filter(function(element,index,self) {

return self.indexOf(element) === index;

})

闭包:函数作为返回值。

typeof 操作获取对象的类型,它总是返回一个字符串

包装对象:

var n = new Number(124);//124

var b = new Boolean(true);//true

var s = new String('str');//'str'

虽然包装对象看上去和原来的值一模一样,显示出来也一模一样,但他们的类型已经变为object了。

如果我们在使用Number、Boolean和String时,没有写new会发生什么情况?

此时,Number()、Boolean和String()被当做普通函数,把任何类型的数据转换为number、boolean和string类型(注意不是其包装类型):

总结一下,有这么几条规则需要遵守:

不要使用new Number()、new Boolean()、new String()创建包装对象;

用parseInt()或parseFloat()来转换任意类型到number;

用String()来转换任意类型到string,或者直接调用某个对象的toString()方法;

通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...};

typeof操作符可以判断出number、boolean、string、function和undefined;

判断Array要使用Array.isArray(arr);

判断null请使用myVar === null;

判断某个全局变量是否存在用typeof window.myVar === 'undefined';

函数内部判断某个变量是否存在用typeof myVar === 'undefined'。

任何对象都有toString()方法吗?null和undefined就没有!确实如此,这两个特殊值要除外,虽然null还伪装成了object类型。

Date对象用来表示日期和时间

var now = new Date();

第二种创建一个指定日期和时间的方法是解析一个符合ISO 8601格式的字符串:

var d = Date.parse('2015-06-24T19:49:22.875+08:00');

d; // 1435146562875

var d = new Date(1435146562875);

d.toLocaleString(); // '2015/6/24 下午7:49:22',本地时间(北京时区+8:00),显示的字符串与操作系统设定的格式有关

d.toUTCString(); // 'Wed, 24 Jun 2015 11:49:22 GMT',UTC时间,与本地时间相差8小时

JSON的字符串规定必须用双引号“”,Object的键必须用双引号“”

把任何Javascript对象变成JSON,就是把这个对象序列化成一个JSON格式的字符串,这样才能通过网络传递给其他计算机。

如果我们收到一个JSON格式的字符串,只需要把它反序列化成一个Javascript对象,就可以在Javascript中直接使用

这个对象了。

JSON.stringify();

JSON.stringify(xiaoming, ['name', 'skills'], '  ');

{

  "name": "小明",

  "skills": [

    "JavaScript",

    "Java",

    "Python",

    "Lisp"

  ]

}

拿到一个JSON格式的字符串,JSON.parse()把它变成一个Javascript对象

JSON.parse('[1,2,3,true]'); // [1, 2, 3, true]

Javascript不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程

var Student = {

name:'robot',

height:1.2,

run:function() {

console.log(this.name + 'is running...');

}

}

var xiaoming = {

name: '小明'

}

xiaoming._proto_=Student;

//xiaoming的原型指向了对象Student,看上去xiaoming仿佛是从Student继承下来的。

xiaoming.name;//'小明'

xiaoming.run();//小明is runing...

Javascript 的原型链和Java的Class区别就在,它没有“Class”的概念,所有对象都是实例,

所谓继承关系不过是把一个对象的原型指向另一个对象而已。

在编写Javascript代码时,不要直接用obj._proto_去改变一个对象的原型,并且低版本的IE

也无法使用_proto_。Object.create()方法可以传入一个原型对象,并创建一个基于该原型的新对象,

但是新对象什么属性都没有,因此,我们可以编写一个函数来创建xiaobin:

var Student = {

name:'Robot',

height: 1.2,

run: function() {

console.log(this.name + 'is running...');

}

}

function createStudent(name) {

var s = Object.create(Student);

s.name = name;

return s;

}

var xiaobin = createStudent('小宾');

xiaobin.run();

xiaobin._proto_=== Student;//true;

var arr = [1,2,3];

arr --->Array.prototype ---> Object.prototype --->null

Array.prototype 定义了indexOf()、shift()等方法

function foo() {

return 0;

}

foo ---> Function.prototype --->Object.prototype --->null

构造函数

Javascript可以用一种构造函数的方法来创建对象,它的用法是,先定义一个

构造函数:

function Student(name) {

this.name = name;

this.hello = function() {

alert('Hello' + this.name + '!');

}

}

var xiaoming = new Student('小明');

xiaoming.name;//'小明'

xiaoming.hello();

如果不写new,Student就是一个普通函数,它返回undefined.

如果写new,它就变成一个构造函数,它绑定的this指向新创建的对象,并默认返回this,

也就是说,不需要在最后写return this

用new Student()创建的对象还从原型上获得了constructor属性,它指向函数Student本身:

xiaobin.constructor === Student.prototype.constructor;//true

Student.prototype.constructor === Student;//true

Object.getPrototypeOf(xiaobin) === Student.prototype;//true

xiaobin.instanceof Student;//true

通过new Student()创建了很多对象,这些对象的hello函数实际上只需要共享同一次函数就可以了,

这样可以节省很多内存。

修改代码如下:

function Student(name) {

this.name = name;

}

Student.prototype.hello = function() {

alert('hello' + this.name);

}

按照约定,构造函数首字母应当大写,而普通函数首字母应当小写

Javascript可以获取浏览器提供的很多对象,并进行操作。

window对象不但充当全局作用域,而且表示浏览器窗口。

window对象有innerWidth 和 innerHeight属性,可以获取浏览器窗口的内部宽度和高度,用于

显示网页的净宽高。

IE<=8 不支持

navigator 对象表示浏览器的信息,最常用的属性:

navigator.appName:浏览器名称;

navigator.appVersion:浏览器版本;

navigator.language:浏览器设置的语言;

navigaotor.userAgent:浏览器设定的User-Agent字符串

screen对象便是屏幕的信息,常用的属性是:

screen.width;屏幕宽度,以像素为单位

screen.height;

screen.colorDepth

http://www.example.com:8080/path/index.html?a=1&b=2#TOP

location对象表示当前页面的URL信息。

location.href;//获取一个完整的URL

locaton.protocal;//'http'

location.host;//'www.example.com'

location.pathname;//'/path/index.html'

location.search;//'?a=1&b=2'

location.hash;//'TOP'

加载一个新页面

location.reload()

document对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,

document对象就是整个DOM树的根节点。

操作DOM

要改变HTML的结构,就需要通过Javascript来操作DOM

更新,遍历,添加,删除

最常用的方法是document.getElementById()和document.getElementsByTagName(),以及CSS选择器document.getElementsByClassName()

querySelector() 和 querySelectotAll()

// 通过querySelector获取ID为q1的节点:

var q1 = document.querySelector('#q1');

// 通过querySelectorAll获取q1节点内的符合条件的所有节点:

var ps = q1.querySelectorAll('div.highlighted > p');

低版本的IE<8不支持querySelector和querySelectorAll。IE8仅有限支持。

更新DOM:innerHTML,innerText

p.innerHTML = 'love'

插入DOM:appendChild(),insertBefore()

var js = document.getElementById('js'),

    list = document.getElementById('list');

    list.appendChild(js);

var list = document.getElementById('list'),

    ref = document.getElementById('python'),

    haskell = document.createElement('p');

haskell.id = 'haskell';

haskell.innerText = 'Haskell';

list.insertBefore(haskell, ref); 

删除DOM

要删除一个节点,首先要获得该节点本身以及它的父节点,然后,

调用父节点的removeChild把自己删掉

var self = document.getElementById('to-be-removed');

var parent = self.parentElement;

var removed = parent.removeChild(self);

removed === self //true

用Javascript操作表单和操作DOM是类似的,表单本身也是DOM树

操作文件:在HTML表单中,可以上传文件的唯一控件就是表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才能正确编码并以multipart/form-data格式发送表单的数据

node.js在Node环境中,一个.js文件就称之为一个模块。

使用模块大大提高了代码的可维护性、避免函数名和变量名冲突。

module.exports = great;

把函数greet作为模块的输出暴露出去,这样其他模块就可以使用greet函数了;

//引用这个模块var greet = require('./hello');

Javascript有且仅有一个全局对象,在浏览器中,叫window对象,

在Node.js环境中,也有唯一的全局变量,叫global,这个对象的属性和方法也和浏览器环境的window不同。

判断Javascript执行环境

if(typeof(window) === 'undefined') {console.log('node.js');}

else{console.log('browser');}

fsNode.js内置的fs模块就是文件系统模块,负责读写文件,同时提供了异步和同步的方法。

js正则表达式

通常用于两个字符串方法:search() 和 replace();

search()用于检索字符串中指定的子字符串,或检索与正则表达式匹配的子字符串,

并返回子串的起始位置。

var str = 'visit you';

var n = str.search(/you/i);

//6

search方法可以使用字符串作为参数:

var str = 'visit you';

var n = str.search('you');

//6

replace()使用正则表达式且不区分大小写将字符串aaa替换为bbb

var text = str.replace(/aaa/,'bbb');

test()方法用于检测一个字符串是否匹配某个模式,如果字符串中含有

匹配的文本,则返回true,否则返回false.

exec()方法用于检索字符串中的正则表达式的匹配

/e/.exec("The best things in life are free!");

//e

^匹配一个输入或一行的开头,/^a/匹配'an A',而不匹配'An'

$匹配一个输入或一行的结尾,/a$/匹配'an a',而不匹配'an A'

*匹配前面元字符0次或多次,/ba*/将匹配b,ba,baa,baaa

+匹配前面元字符1次或多次,/ba+/将匹配ba,baa,baaa

?匹配前面元字符0次或1次,/ba?/将匹配b,ba

(x|y)匹配x或y

{n}匹配n次以上

{n,m}匹配n-m次

[xyz]字符集,匹配这个集合中的任一一个字符

[^xyz]不匹配这个集合中的任何一个字符

[\b]匹配一个退格符

\b匹配一个单词的边界

\B匹配一个单词的非边界

\cX,X是一个控制符,匹配Ctrl-X

\d匹配一个字数字符,/d/ == /[0-9]/

\D匹配一个非字数字符,/d/ == /[^0-9]/

\n匹配一个换行符

\r匹配一个回车符

\s匹配一个空白字符,包括\n,\r,\f,\t,\v

\S匹配一个非空白字符,等于[^\n\r\f\t\v]

\t匹配一个制表符

\v匹配一个垂直制表符

\w匹配一个可以组成单词的字符,等于[a-zA-Z0-9]

\W匹配一个不可以组成单词的字符,等于[^a-zA-Z0-9]

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

推荐阅读更多精彩内容