JavaScript面试题

错误之处,欢迎指正,持续更新中。


1. 基础

1. =====的区别是什么?

console.log(1 == '1'); //true
console.log(1 === '1'); //false

使用===进行比较时,如果等号两边的数据类型不同,直接返回false
使用==进行比较,会先进行类型转换,再进行比较。

2. 运行下列代码在控制台输出的结果是?

for(var index = 0; index < 5; index ++){
  var result = index + '';
}
console.log(result);
console.log(index);
console.log((1 - 'result') == (1 - 'result'));

输出结果为'4'5false

3. "2" + 3 + 4的结果为?

结果为"234"

4. 以下哪些数据经过fn处理后,返回的是false

function fn(a) {
  return !!a;
}

A. NaN
B. -1
C. ""
D. "0"
答案为A、C选项。

5. 下列代码的输出结果为?

var a = new Boolean(false);
console.log(typeof a)

输出结果为object

6. 怎样找出xy哪个数值最大?

A. Math.ceil(x, y);
B. top(x, y);
C. ceil(x, y);
D. Math.max(x, y);
E. max(x,y);
正确选项为D。

7. 下列结果为true的表达式是?

A. null instanceof Object
B. NaN == NaN
C. null == undefined
D. false == undefined
正确选项为C。

8. 将字符串转换为JSON对象的方法是?

A. var obj = JSON.parse(str);
B. var obj = eval('(' + str + ')');
C. var obj = str.parseJSON();
D. 都是。
正确选项为A和B。

9. 如何翻转字符串?

const str = '123456';
const arr = str.split('');  //["1", "2", "3", "4", "5", "6"]
const newArr = arr.reverse(); //["6", "5", "4", "3", "2", "1"]
const newStr = newArr.join('');
console.log(newStr);  //654321

10. 如何分割字符串?

  1. slice方法
    按照索引值来截取字符串,左开右闭区间。
var str = '123-1234-124';
console.log(str.slice(4, 8)); //1234
  1. split方法
var str = '123-1234-124';
console.log(str.split('-'));  //["123", "1234", "124"]

按照指定的字符分割字符串。

11. 如何删除字符串中的空格?

  1. split方法和join方法
const str = '1 2 345 6789 ';
const arr = str.split(' '); //["1", "2", "345", "6789", ""]
const newStr = arr.join('');
console.log(newStr);  //123456789
  1. 正则表达式和replace方法
const str = '1 2 345 6789 ';
const reg = /\s/g;  //匹配到所有空白符
const newStr = str.replace(reg,''); //将空白符替换为空字符串
console.log(newStr); //123456789
  1. trim方法
    只能去掉字符串首尾两端的空格。
const str = '  1 2 345 6789 ';
const newStr = str.trim();
console.log(newStr);  //1 2 345 6789

12. 如何返回下列数组的第一个值?

var myArr = [1, 2, 3, 4, 5];

A. myArr[1];
B. myArr.pop();
C. myArr[0];
D. myArr.unshift();
E. myArr.shift();
正确选项为C、E。

13. 如何区别数组和对象?

  1. 查询构造函数
const arr = [1,2,3,4,5];
const obj = {
  name: 'chris'
}
console.log(arr.__proto__.constructor); //Array()
console.log(obj.__proto__.constructor); //Object()
  1. instanceof
const arr = [1,2,3,4,5];
const obj = {
  name: 'chris'
}
console.log(obj instanceof Array); //false
console.log(obj instanceof Object); //true
  1. isPrototypeOf
const arr = [1,2,3,4,5];
const obj = {
  name: 'chris'
}
console.log(Array.prototype.isPrototypeOf(arr)); //true
console.log(Array.prototype.isPrototypeOf(obj)); //false
  1. isArray静态方法
const arr = [1,2,3,4,5];
const obj = {
  name: 'chris'
}
console.log(Array.isArray(arr)); //true
console.log(Array.isArray(obj)); //false

14. 如何翻转数组?

var arr = [1,2,3,4,5];
console.log(arr.reverse()); //[5, 4, 3, 2, 1]
console.log(arr); //[5, 4, 3, 2, 1]

要注意的是,该方法会改变原数组。

15. 简要说明splice的用法。

splice方法可以用来删除数组中的某些值,或者添加一些值,返回值为被删除的项目,该方法会改变原数组。
参数分别为:

  • 删除的起始位置(负数是指从数组结尾开始)
  • 要删除的数量
  • 添加的新内容
var arr = [0, 1, 2, 3, 4, 5];
arr.splice(0, 2, 1);  //[0, 1]
console.log(arr); //[1, 2, 3, 4, 5]

16. 如何实现数组去重?

  1. indexOfincludes
var arr = [1,2,3,4,5,1,5];
var newArr = [];
for (let index = 0; index < arr.length; index++) {
  if(newArr.indexOf(arr[index]) == -1){
    newArr.push(arr[index]);
  }
}
console.log(newArr);  //[1, 2, 3, 4, 5]

无论是使用indexOf还是includes,原理都是遍历旧数组,然后查找新数组是否已存在该项,不存在时进行push

  1. SET
var arr = [1,2,3,4,5,1,5];
var newArr = Array.from(new Set(arr));
console.log(newArr);  //[1, 2, 3, 4, 5]

17. 如何实现对数组和对象的深浅拷贝?

  1. 浅拷贝
var arr = [1,2,3,4,5];
var newArr = arr;
newArr[0] = 0; 
console.log(newArr);  //[0, 2, 3, 4, 5]
console.log(arr); //[0, 2, 3, 4, 5]
//arr和newArr共用同一块内存。  
  1. 深拷贝
var arr = [1,2,3,4,5];
var newArr = [];
for (let index = 0; index < arr.length; index++) {
  newArr.push(arr[index]);
}
newArr[0] = 0; 
console.log(newArr);  //[0, 2, 3, 4, 5]
console.log(arr); //[1, 2, 3, 4, 5]

18. 如何实现一个递归阶乘?

function getResult(num) {
  if(num === 0) {
    return 0;
  }
  if(num === 1){
    return 1;
  }else{
    return num * getResult(num - 1);
  }
}
console.log(getResult(5));  //120

19. touchclick以及mousedown有什么区别?

  1. 触发点不同
    touch(不包括touchstart)事件不一定发生在所监听的DOM元素上,mouse事件必须发生在所监听的DOM元素上。
  • touch
    touchstart触发后,即使鼠标移出监听的DOM区域,touchendtouchmovetouchend依然可以触发。
  • mouseclick
    mousedown触发后,鼠标移出监听的DOM区域,mouseup不会触发。click也是如此,按下之后,离开目标区域,抬起鼠标,click事件不会触发。
  1. 触发的先后顺序
boxDom.addEventListener('mousedown', () => {
  console.log('mousedown发生了');
})
boxDom.addEventListener('mouseup', () => {
  console.log('mouseup发生了');
})
boxDom.addEventListener('click', () => {
  console.log('click发生了');
})
boxDom.addEventListener('touchstart', () => {
  console.log('touchstart发生了');
})
boxDom.addEventListener('touchend', () => {
  console.log('touchend发生了');
})

发生顺序

综上,touch事件的发生时间是早于mouse事件和click事件的。

20. 事件有哪几个阶段?

  1. 捕获阶段
    事件从最不精确的对象到最精确的对象。
    当我们在DOM树上某个节点设置并发生了一些操作后,就会有一个事件触发,这个事件从Window发出,到目标节点结束。
  2. 目标阶段
    事件经过捕获阶段,直至目标节点,捕获阶段结束,在目标节点触发事件,此时就是目标阶段。
  3. 冒泡阶段
    事件从最精确的对象到最不精确的对象。
    事件经过目标阶段,由目标节点开始,逐级向上传递。
    DOM的树形结构决定了子元素肯定在父元素之中,所以点击子元素就同时点击了子元素和父元素,以及父元素的父元素,以此类推,那么子元素的父级上的绑定事件,都会由于子元素的点击而执行。
    可以通过调用stopPropagation方法来阻止事件冒泡。

21. 为什么要使用事件委托?

事件委托是利用了事件冒泡的原理。例如有100li标签,每一个都需要点击事件,那么就把这个点击事件委托给他的父元素ul
事件委托可以减少重复代码量,减少了事件注册,从而降低了DOM操作,提升性能。其次就是对于新添加的子元素,无需再次绑定事件。

22. 分别说明querySelectorquerySelectorAll的作用。

  1. querySelector
    document.querySelector("p");选中文档中的第一个p标签元素。
    document.querySelector("h2, h3");此时要看文档中的第一个h2标签和第一个h3标签哪一个在前面,谁在前面就选中谁。
  2. querySelectorAll
    document.querySelectorAll(".example");选中文档中所有类名为example的元素。

23. 简要描述闭包是什么,有什么特性,如何创建一个闭包?

首先,javascript中允许在函数中声明函数:

function main() {
  function help() {
  }
}

存在一种场景,有一个主函数,需要复杂的运算和逻辑,所以为了后期的维护性,以及代码可读性,会拆分主函数,把一些运算单独抽离出来封装成函数,然后这些抽离出来的函数,仅仅是对这个主函数有用,在这种情况下,我们会把这些抽离出来的函数,写在主函数内部,可以避免全局对象污染。
这种写在函数内部的函数(嵌套函数),就称之为闭包函数,例如上述代码中的help函数。

function a() {
  var num = 10;
  function b() {  //闭包函数
    console.log(num);  //内部函数可以访问到外部函数的作用域
  }
  return b;  
}
var fo = a(); //a函数执行,把a的执行结果赋给fo
fo();  //10

所谓闭包,就是这种外部环境能够访问内部函数作用域的变量的现象。
闭包的缺点是会造成内存泄露,可以理解为,本来a函数执行完毕要释放内存,但是由于闭包,存放num的内存不能被释放,那么如果有新的数据就不能存进来,就会被泄露。

24. 请完善下列代码,使控制台输出chris@123

function Person(name) {
  this.name = name;
}
var person = new Person('chris');
person.run();

添加代码:

Person.prototype.run = function () {
  console.log(`${this.name}@123`);
}

这里考察的是原型的问题。

25. 什么是原型和原型链?

  1. 原型
    对象都有__proto__这个属性,这个属性指向该对象的构造器的原型。
    函数都有prototype这个属性,这个属性指向该函数的原型,原型是一个对象格式。
var a = 123;
console.log(a.__proto__ === Number.prototype); //true

例如上述代码,a的原型就是Number.prototype
要注意的是:

console.log(Function.__proto__ === Function.prototype); //true
console.log(Object.prototype.__proto__ === null); //true
  1. 原型链
    当调用一个对象或者函数上的属性时,先去自身找,如果自身没有,去原型上找,如果原型上没有,去原型的原型上找,一直到找到,或者返回null为止,形成了一种链式结构,称之为原型链。

26. 运行下列代码,控制台会输出什么?

var x = { foo: "A" };
x.constructor.prototype.foo = 'B';
var y = {};
console.log(x.foo);
console.log(y.foo);

输出结果为AB

27. 如果对象obj包含一个非继承的名为propertyName的属性,下面正确的是?

A. obj.doesPropertyExist('propertyName');
B. obj.hasProperty('propertyName');
C. obj.exists('propertyName');
D. obj.contains('propertyName');
E. obj.hasOwnProperty('propertyName');
正确选项为E。

28. 请选择下列正确选项。

function People(name) {
  this.name = name;
}
var stu = new People("chris");

A. stu.__proto__ === People.prototype;
B. stu.prototype === People.__proto__;
C. People.__proto__ === Object.__proto__;
D. People.prototype === Object.prototype;
E. People.__proto__ === Function.prototype;
正确选项为A和E。

29. 简要说明javascript事件循环机制。

  1. 执行同步代码。
  2. 遇到宏任务放到宏任务队列。
  3. 遇到微任务放到微任务队列。
  4. 同步代码执行完毕。
  5. 执行微任务队列,微任务队列执行完毕。
  6. 执行宏任务队列,宏任务队列执行完毕。

30. javascript是如何处理异步的?

由于javascript是单线程的,只能每次做一件事情,只有当前的事情做完,才可以做下一件事,因此javascript提供了一些异步解决方案(回调、Promise),来提高执行效率。
javascript中只有同步代码都执行完毕,执行栈为空的时候,才会执行异步代码。
异步有两个队列,微任务队列(relovereject)和宏任务队列(setTimeout),微队列执行优先于宏任务队列。

31. 请根据下列要求实现一个函数getSum

  1. 该函数接收两个参数。
  2. 第一个参数为长度不定的arr数组,且数组元素均为number类型。
  3. 第二个参数为number类型的变量sum 如果数组arr中的任意两个元素之和等于sum,则返回true否则返回false
function getSum(arr, sum) {
  for (let index = 0; index < arr.length; index++) {
    if(arr.indexOf(sum - arr[index]) !== -1 && arr.indexOf(sum - arr[index]) !== index){
      return true;
    };
  }
  return false;
}
var arr = [1,2,3,4,5];
var sum = 5;
getSum(arr, sum);

32. 请选择下列正确选项。

A. 除非抛出异常,否则foreach方法无法终止。
B. typeof NaN === 'NaN'
C. javascript中只有变量会提升,函数则不会。
D. 数组方法shift会在数组头部添加一个新元素。
选择A选项。

33. 下列代码,调用output时入参是什么?

var item;
var obj = {
  name: 'chris',
  email: 'chris@example.com',
  sendMail: function () {}
}
for(item in obj) {
  ouput(item);
}

A. 类型错误。
B. name, "email", "sendMail"
C. name, "email"
D. chris, chris@example.com, undefined
E. chris, chris@example.com, null
正确选项为B。

34. cookielocalStoragesessionStorage有什么区别?

  1. 每次http请求都会携带cookie数据,而sessionStoragelocalStorage不会。
  2. cookie存储的数据不能超过4KBsessionStoragelocalStorage存储大小一般为5MB或者更多。
  3. cookie只在设置的cookie过期时间之前有效,localStorage始终有效,窗口或浏览器关闭也一直保存。
    sessionStorage仅在当前浏览器窗口关闭之前有效。
  4. sessionStorage在不同的浏览器窗口中不共享,即使是同一个页面,localstorage在所有同源窗口中都是共享的,cookie在所有同源窗口中也是共享的。

35. 下列哪些关于cookie的描述是正确的?

A. cookie必须要在https下传输,而不能在http下传输。
B. cookie的有效期,不能被设为浏览器关闭时自动删除。
C. cookie是存储在客户端的。
D. 全部正确。
正确选项是D。

36. 简要描述javascript语言的特性。

javascript是一种解释型单线程弱类型的语言。

  1. 解释型
    解释型语言可以通俗的理解为一个会中文的人读一本英文书籍,读到不会的地方,就去查中英字典,如果一个西班牙人来进行阅读,那么就使用中西字典。诸如javascriptPHP语言都是解释型序言。
  • 解释型语言的优点:适应各种环境。
  • 解释型语言的缺点:执行速度稍慢。
    编译型语言可以通俗的理解为将一本英文书籍翻译成中文书籍,然后在进行阅读,但是如果此时一个西班牙人来阅读,还需要再次翻译成西语书籍才可以。诸如CC++Java都是编译型语言。
  • 编译型语言的优点:执行速度快。
  • 编译型语言的缺点:难以适应各种环境。
  1. 单线程
    单线程,可以理解为有一堆物品,但是只能由一个人运输。相反的,多线程,就是可以由多个人来运输这堆物品。
    单线程会带来同步现象:当前的事情没有做完,就不能做下一件事,只能阻塞在这里,只有当前的事情做完,才可以做下一件事。但是,javascript中会有一些异步的解决方案,来避免这些阻塞,从而提高单线程的执行效率。
  2. 弱类型
    通俗的来说弱类型就是存放的数据类型灵活可变,但是与此同时,带来了数据不严谨的缺点。
    反之,强类型就是存放的数据类型不可变,虽然不灵活,但是很严谨。
    比如在javascript中,可以让一个数字和字符串相加,结果会是一个新的字符串,javascript会把数字转换成字符串类型,然后再相加。

37. 执行下列代码控制台的输出内容是什么?

let a = 5;
console.log(a);
console.log(a++);
console.log(a); 
console.log(++a); 
console.log(a);

a++是先输出后运算,++a是先运算后输出。
控制台输出内容为:55677

38. javascript有哪些数据类型?

  1. 基础类型
    NumberStringBooleanundefinednull(注意,nulltypeof输出类型为Object
    通俗的讲,可以用占座的方式来理解undefinednull,当座位没被占的时候就是undefined,当座位被占用了,但是占座的人还没来,这种情况是null
  2. 引用类型
    ObjectFunctionArray

39. 函数字面量和函数表达式有什么区别?

console.log(test1);  //test1函数体
console.log(test2);  //not define
console.log(test3);  //not define
function test1() {
    console.log('test1');
}
(function test2() {
    console.log('test2');
})
var a = function test3() {
    console.log('test3')
}
test1();                    //test1
console.log(window.test1);  //test1函数体
test2();                    //not define
console.log(window.test2);  //undefined
a();                        //test3
test3();                    //not define
console.log(window.a);      //test3函数体
console.log(window.test3);  //undefined
  1. 函数字面量
    上述代码的test1函数就是通过函数字面量方式进行声明的,这种方法:
  • 会让函数进行提升。
  • 会污染全局对象。
  1. 函数表达式
    上述代码中的test2test3都是通过函数表达式的方式进行声明的,这种方法:
  • 不会让函数进行提升。
  • 不会污染全局对象。

40. 简单介绍函数内的变量声明。

function test() {
  console.log(a);  //undefined
  console.log(b);  //not define
  var a = 1;
  b = 2;
  console.log(a);  //1
  console.log(b);  //2
}
test();
console.log(a);  //not define
console.log(b);  //2
  • 函数内用var声明的变量会被提升到函数体顶部var a;
  • 函数内直接进行赋值的变量会成为全局对象上的一个属性。
  • 函数体外部不能拿到函数体内部的变量。

41. 简单介绍return关键字。

  • return会结束函数的运行。
  • return默认返回undefined
function test() {
  return;
}
console.log(test());  //undefined
  • 不手动添加return,函数会在末尾自动书写return
function test() {}
console.log(test());  //undefined

42. 简单介绍作用域。

  1. 全局作用域
var a = 1;  
var b = 2;
function test() {
  var c = 3;
}

可以理解为,直接在script标签下声明的是处于全局作用域。
此时全局作用域中有:变量a,变量b,函数test

  1. 函数作用域
    以上述代码为例,变量c就处于test函数作用域。
  2. 区别
  • 全局作用域只能访问处于全局作用域的变量。
  • 函数作用域可以访问函数作用域内的变量和外部作用域的变量。

43. 简单介绍this关键字。

  1. 全局作用域
    this关键字指向window对象。
  2. 函数作用域
const obj = {
    foo: function () {
        console.log(this);
    }
}
obj.foo();

如果直接使用test()这种方式调用函数,函数中的this指向window对象;如果像上述代码,this指向obj

44. callbindapply有什么区别?

const obj = {
  name: "chris",
  age: "18",
  print(job){
    console.log(`${this.name} + ${this.age} + ${job}`);
  }
}
const newObj = {
  name: "john"
}
obj.print() //chris + 18 + undefined
obj.print.call(newObj, "engineer");  //john + undefined + engineer
obj.print.apply(newObj, ["engineer"]);  //john + undefined + engineer
obj.print.bind(newObj, "engineer")();  //john + undefined + engineer

45. 如何创建一个文档片段?

createdocumentfragment方法创建了一虚拟的节点对象,也就是文档片段,也可理解为一个虚拟的父元素,将其他新创建的多个子元素添加到此父元素下,然后只需要通过一次操作将父元素添加到body下即可时效最终效果,减少了对于DOM的操作。

const d = document.createDocumentFragment();
const arrElement = new Array(10);
for (let index = 0; index < arrElement.length; index++) {
  const element = document.createElement("input");
  d.appendChild(element);
}
document.body.appendChild(d);

2. 进阶

1. 什么是防抖函数和截流函数?

  1. 防抖函数
    直白来说,就是过一段时间以后再去执行。
    例如:电梯门在有人通过之后,隔一段时间之后才会进行关门,如果此时又有人进入,继续等一段时间(重新计时)后再进行关门。例如某些搜索框也是如此,在输入完搜索内容后,过一段时间才会展示内容,如果在展示内容之前,又进行了输入,那么就会再次重新等待一段时间。
const input = document.getElementsByClassName('input')[0];
const handle = debunce();  //把return的返回函数给handle
input.oninput = (val) => {
    handle(() => {console.log(val)});
    //每次输入框输入时,就调用handle,并把打印val的函数传递过去
}
function debunce() {
    let timer; //每次return函数都使用这个timer
    return function (callback) {  //这里callback接受了打印val的函数
        clearInterval(timer);  //清除定时器
        timer = setTimeout(() => {  //1s之后执行打印val函数
            callback();
        }, 1000);
    }
}

如果在等待这1s时,再次输入,就会清除上一次的定时器,不会进行打印,然后创建一个新的计时器,如果再次输入,就会重复流程,如果没输入,等待1s后输出val
防抖函数使用了高阶函数(在函数内部返回一个新的函数),闭包(外部操作timer),定时器来实现。

  1. 截流函数
  • 规定时间内无论触发多少次,只在规定时间结束后执行一次。
const inputDom = document.getElementById('input');
const handle = throttle();
inputDom.oninput = (value => {
    handle(value.data);
})
function throttle() {
    let timer = null;
    return function (value) {
        if(timer){  //判断此时是否有定时器,如果有就直接return
            return
        }
        timer = setTimeout(() => {
            console.log(value)
            timer = null;
        }, 1000);
    }
}
  • 马上触发一次,然后规定时间结束后才会被第二次触发(利用时间戳)。
const inputDom = document.getElementById('input');
const handle = throttle();
inputDom.oninput = (value => {
    handle(value.data);
})
function throttle() {
    let time = null;
    return function (value) {
        if (!time || Date.now() - time > 1000) {
            console.log(value);
            time = Date.now();  //得到当前的时间戳
        }
    }
}

如果是一定要等某个动作结束后才触发,那么就使用防抖函数;
如果是规定时间内只能触发一次,那么就使用截流函数。

2. 如何进行性能优化?

  1. 减少http请求
    http请求文件需要时间,尤其在网速不好的情况下,会消耗大量时间,而且每一次请求都需要建立连接、释放连接,会对浏览器以及服务器产生性能消耗。
    尽量合并jscss文件,这样就可以减少文件请求的数量。
    减少对于图片的请求,使用css sprites或者进行懒加载处理,或者对图片进行压缩。
  2. 减少重排和重绘
    重绘:重绘仅仅是外观改变,例如背景颜色、文字颜色等改变,对性能影响不大。
    重排:例如当元素的大小改变时,浏览器会重新渲染当前的元素,以及计算被该元素大小改变影响的元素,会造成比较多的性能消耗。
    例如可以使用absolute定位,这样当元素大小改变时不会影响其他元素,减少性能消耗。
  3. 减少DOM操作
    操作DOM会消耗比较可观的性能,我们可以这样理解:
    DOM是一座岛屿,javascript是另一座岛屿,两者之间以一座桥梁连接,那么每次的DOM操作都要通过这座桥梁。
    DOM操作是避免不了的,我们只能通过一些变通的办法来进行优化,例如查询DOM时,可以赋值给变量,这样就不需要每次都进行查询。

3. 浏览器缓存是如何实现的?

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