前端常见问题总结

补:get请求传参长度的误区

  • 实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制了url的长度。

  • 不同的浏览器和WEB服务器,限制的最大长度不一样要支持IE,则最大长度为2083byte,若只支持Chrome,则最大长度 8182byte

补:get和post请求在缓存方面的区别

  • get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存
  • post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存。

1.三次握手and四次挥手

  • 三次握手
    详细描述:
    客户端发送连接请求报文,服务器接受连接后回复ACK报文,并为这次连接分配资源。客户端接收到ACK报文后也向服务器发生ACK报文,并分配资源,这样TCP连接就建立了。
    简单的理解:

    • 客户端看到服务器,打声招呼(发送syn);
    • 服务器收到客户端的招呼,也向客户端打招呼,表示他看到了(发送syn+ack
    • 客户端看到服务器的回应,相当建立沟通(发送ack),表示很开心

    详细过程:

    • 1)第一次握手:A的TCP客户进程也是首先创建传输控制块TCB,然后向B发出连接请求报文段(首部的同步位SYN=1,初始序号seq=x)
    • 2)第二次握手:B收到连接请求报文段后,如同意建立连接,则向A发送确认,在确认报文段中(SYN=1,ACK=1)
    • 3)第三次握手:TCP客户进程收到B的确认后,要向B给出确认报文段(ACK=1)
image.png
  • 四次挥手
    TCP断开链接的过程和建立链接的过程比较类似,只不过中间的两部并不总是会合成一步走,所以它分成了4个动作。
    简单理解:
    • 客户端挥手(fin)
    • 服务器伤感地微笑(ack)
    • 服务器挥手(fin)
    • 客户端伤感地微笑(ack)。
      详细描述:
    • 1)客户端发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,客户端进入FIN-WAIT-1(终止等待1)状态
    • 2)服务器收到连接释放报文,发出确认报文,ACK=1,服务端就进入了CLOSE-WAIT(关闭等待)状态
    • 3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态。
      服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1。服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
    • 4) 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1。此时,客户端就进入了TIME-WAIT(时间等待)状态。
      注意此时TCP连接还没有释放,必须经过2个MSL(最长报文段寿命)的时间后(即两分钟),当客户端撤销相应的TCB后,才进入CLOSED状态
      服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
  • 总的说就是:
    客户端要断开,告诉服务器,服务器同意断开连接。
    服务器发送完最后数据,服务器要断开,告诉客户端,客户端同意断开连接。
    客户端同意断开连接,服务器立马close。但是客户端还要等待两分钟。
image.png
  • 为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:中间的两个动作没有合并,是因为tcp存在「半关闭」状态,也就是单向关闭。
因为当Server端收到Client端的syn连接请求报文后,可以直接发送syn+ack报文。其中ack报文是用来应答的,syn报文是用来同步的。但是关闭连接时,当Server端收到fin报文时,很可能并不会立即关闭,所以只能先回复一个ack报文,告诉Client端,"你发的fin报文我收到了"。只有等到我Server端所有的数据报文都发送完了,我才能发送fin报文,因此不能一起发送。故需要四步握手。

  • 为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。


2.url到页面渲染完成的经过

大致分为三步:

  • 1. 域名解析
    • 浏览器会将输入的域名解析成相应的ip地址
      1. 查看浏览器内部缓存
      1. 查看本机的host文件,会查看本机的host文件下,是否存了对应的ip地址
      1. 本地路由器的DNS解析
      1. 查看网络服务DNS
      1. 查询到ip地址后,开始建立TCP三次握手,与服务器建立连接
      1. 通过协议(http)向目标主机发送请求
  • 2. 服务器接收请求并返回数据
      1. 服务器接收到了浏览器发送的请求后,根据某个协议,通过web-server把浏览器发送的数据进行打包(包含请求头,ip地址,请求路径和查询参数等)
      1. web-server把数据打包后,发送给网站代码(比如django、flask、node.js等后端服务)
      1. 后端服务软件会根据路径和查询参数进行相应处理,返回给浏览器对应的数据包(包括http协议组成的代码。里面包含页面的布局、文字。数据也可能是图片、脚本程序,反应头,反应数据,请求头等)
  • 3. 浏览器接收数据并渲染页面
      1. 浏览器接收到返回的数据包,根据浏览器的渲染机制对相应的数据进行渲染。
      1. 渲染后的数据,进行相应的页面呈现和脚步的交互。

3.js引擎的执行机制

(1) JS是单线程语言
(2) JS的 Event Loop是JS的执行机制。

  • js为什么是单线程的呢?
    因为,如果是多线程,若几个线程同时操作dom的话,浏览器该怎么执行呢。

  • js为什么需要异步呢?
    js中不存在异步,是从上而下顺序执行的,但是这样很容易阻塞,若某一句代码解析执行时间很长,那用户就需要等待很长时间,所以需要异步执行。

  • js怎么实现异步呢?
    就是通过本节的核心事件循环(Event Loop)了,那事件循环具体是什么呢?
    比如:

cosole.log(1);
setTimeOut(function(){
    cosole.log(2);
},0);
cosole.log(3);
执行的输出顺序是: 1  3  2

js是顺序从上到下执行,但是setTimeOut是最后才执行的,就证明了异步的存在。js也就将任务分为:同步任务和异步任务。

  • 那事件循环具体怎么循环?
    • 1.js判断是同步事件还是异步事件,同步就进入执行栈,异步事件被挂起
      1. 异步事件返回结果后,就进入消息队列
      1. 同步任务进入执行栈后一直执行,直到执行栈为空时,才会去消息队列中查看是否有可执行的异步任务,如果有就推入执行栈中

循环执行上述三步,直到执行栈为空,就是事件循环了

所以上面例子的执行顺序分析是怎样的呢?

console.log(1) 是同步任务,放入主线程(执行栈)里
setTimeout() 是 异步任务,被挂起, 0秒之后被推入消息队列里
console.log(3 是同步任务,放到主线程(执行栈)里

当 1、 3输出后,主线程去消息队列(事件队列)里查看是否有可执行的函数,执行setTimeout里的函数,输出2

以上就是event loop 的简单分析了。但是只是很浅的一部分,因为还有下面这样情况:

setTimeout(function(){
     console.log('定时器')
 });
 
 new Promise(function(resolve){
     console.log('开始for循环');
     for(var i = 0; i < 10000; i++){
         i == 99 && resolve();
     }
 }).then(function(){
     console.log('执行then')
 });
  console.log('执行结束');

对于这样多个异步的事件,按照之前的分析应该输出:开始for循环 --> 执行结束 --> 定时器 --> 执行then
但是实际的输出却是: 开始for循环 --> 执行结束 --> 执行then --> 定时器

会发现 是 先执行promise 再执行的setTimeOut ,那难道是异步任务的执行顺序,不是前后顺序,而是另有规定? 事实上,按照异步和同步的划分方式,并不准确。

而准确的划分方式是:

  • macro-task(宏任务):包括整体代码script,setTimeout,setInterval
  • micro-task(微任务):Promise,process.nextTick

按照这种分类方式:JS的执行机制

  • 执行一个宏任务,过程中如果遇到微任务,就将其放到微任务的【事件队列】里

  • 当前宏任务执行完成后,会查看微任务的【事件队列】,并将里面全部的微任务依次执行完

重复以上2步骤,再结合前面的事件循环,就是更为准确的JS执行机制了。

所以上面例子的执行顺序分析是怎样的呢?

先执行script宏任务
遇到 setTimeOut 是宏任务,将其放入宏任务队列
遇到 new Promise直接执行,打印  "开始for循环"
遇到 then 是微任务,将其放入微任务队列
打印 "执行结束"
本轮宏任务(script)执行完毕,检查微任务队列,遇到then,执行输出 " 执行then",就只有这一个微任务,所以执行结束
本轮 event loop 执行结束
进入下一轮 
执行宏任务 setTimeOut,打印 "定时器"
再查看微任务队列,没有微任务
执行完毕

4.hash与history的区别

  • hash模式

    • hash就是指url尾巴后的#号以及后面的字符,hash值变化不会导致浏览器向服务器发出请求,而且hash改变会触发hashchange事件,浏览器的进后退也能对其进行控制,所以人们在html5的history出现前,基本都是使用hash来实现前端路由的。
    • hash出现url中,但不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面
    • hash 本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了。其次,hash的传参是基于url的,如果要传递复杂的数据,会有体积的限制
  • history模式

    • history模式不仅可以在url里放参数,还可以将数据存放在一个特定的对象中。
      history——— 利用了HTML5 History Interface 中新增的 pushState()和replaceState()方法。
      (需要特定浏览器的支持)history不能运用与IE8一下
  • pushState()和 replaceState()的区别:

    • pushState 是创建新的历史纪录
    • replaceState是修改当前历史纪录
window.history.pushState(state,title,url)
  state:需要保存的数据,这个数据在触发popstate事件时,可以在event.state里获取
  title:标题,基本没用,一般传null
  url:设定新的历史纪录的url。新的url与当前url的origin必须是一样的,否则会抛出错误。url可以时绝对路径,也可以是相对路径。
  如 当前url是 https://www.baidu.com/a/,执行history.pushState(null, null, './qq/'),则变成       https://www.baidu.com/a/qq/,
  执行history.pushState(null, null, '/qq/'),则变成 https://www.baidu.com/qq/

window.history.replaceState(state,title,url)
  与pushState 基本相同,但她是修改当前历史纪录,而 pushState 是创建新的历史纪录

window.addEventListener("pospstate",function(){
   监听浏览器前进后退事件,pushState与replaceState方法不会触发
})
window.history.back()   后退
window.history.forward()   前进
window.history.go(1)   前进一部,-2回退两不,window.history.lengthk可以查看当前历史堆栈中页面的数量

这两个方法应用于浏览器的历史纪录站,在当前已有的back、forward、go 的基础之上,他们提供了对历史纪录进行修改的功能,只是当他们执行修改使,虽然改变了当前的url,但你的浏览器不会立即像后端发送请求

  • 404错误

1、hash模式下,仅hash符号之前的内容会被包含在请求中,如 http://www.abc.com 因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误;
2、history模式下,前端的url必须和实际后端发起请求的url一致,如http://www.abc.com/book/id 。如果后端缺少对/book/id 的路由处理,将返回404错误。


5.vue钩子函数

(1)与生命周期有关的生命周期函数: beforeCreatecreatedbeforeMountedmountedbeforeUpdateupdatedbeforeDestorydestoryed
(2)computedwatchfilter
(3)自定义指令directive的钩子函数

  • bind : 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作
  • inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document)
  • update: 被绑定元素所在的模板更新时调用,而不论绑定值是否
  • componentUpdated: 被绑定元素所在模板完成一次更新周期时调
  • unbind: 只调用一次,指令与元素解绑时

常用参考链接:https://www.jianshu.com/p/8314ccd03fa9


6.vue常用指令

  • v-for v-for="字段名 in(of) 数组json" 循环数组或json
  • v-model 数据的双向绑定
  • v-if 显示与隐藏 ,是创建和删除元素
  • v-else-if 必须和v-if连用
  • v-else 必须和v-if连用 不能单独使用 否则报错 模板编译错误
    • v-show 显示内容,只是切换display值
    • v-hidden 隐藏内容
  • v-bind 动态绑定
  • v-bind:class 3种绑定方法
    • 1.对象型 {red:isred}
    • 2.三元型 isred?"red":"blue"
    • 3.数组型 [{red:"isred"},{blue:"isblue"}]
  • v-on 监听dom事件,可以缩写为@,例如绑定一个点击函数 ,函数必须写在methods里面
  • v-text 解析文本
  • v-html 解析html标签
  • v-once 进入页面时 ,只渲染一次,不在进行渲染

常用参考链接:https://blog.csdn.net/dz13271116886/article/details/99708315


7.vue常用修饰符

  • 事件修饰符(5个)
    • .stop:阻止事件冒泡
    • .prevent :阻止默认事件
    • .once :只执行一次
    • .capture :捕获事件,与冒泡相反
    • .self :只触发自身事件
  • 键盘修饰符(9个)
    • .enter:回车键
    • .tab:制表键
    • .delete:含delete和backspace键
    • .esc:返回键
    • .space: 空格键
    • .up:向上键
    • .down:向下键
    • .left:向左键
    • .right:向右键
  • v-modle修饰符(3个)
    • .number:将输出字符串转为Number类型
    • .lazy:在改变后才触发(也就是说只有光标离开input输入框的时候值才会改变)
    • .trim:自动过滤用户输入的首尾空格

详细参考链接:https://blog.csdn.net/qq_42238554/article/details/86592295


8.vue常用组件

  • vue-cli : 项目构建工具
  • vue-router:路由
  • vuex:状态管理
  • axios:http请求
  • 组件库的组件 eg:Element-ui 、iview

详细参考链接:sohu.com/a/328202078_120047065


9.vue 过滤器

在vue中提供了Vue.filter('filterName',fn)来定义一个过滤器。
过滤器可以在HTML代码中使用,对动态拿到的数据进行过滤
filter不会修改原始数据,它的作用是过滤数据。
通过|管道符来过滤前面数据

  • 过滤器参数:
    • 第一个参数 fliterName:是过滤器的名字
    • 第二个参数 fn :是过滤器功能函数(两个参数)
  • 过滤功能函数参数:
    • 第一个参数是传入的要过滤数据,即原数据。
    • 第二个参数开始就是html调用过滤器的时候传入的参数。

用法参考链接:https://blog.csdn.net/badmoonc/article/details/81485803


10.MVVM的理解

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。

响应式原理

观察者-订阅者(数据劫持):

  • vueObserver 数据监听器,把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用Object.defineProperty()方法把这些属性全部转成setter、getter方法。当data中的某个属性被访问时,则会调用getter方法,当data中的属性被改变时,则会调用setter方法。
  • Compile指令解析器,它的作用对每个元素节点的指令进行解析,替换模板数据,并绑定对应的更新函数,初始化相应的订阅。
  • Watcher 订阅者,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数。
  • Dep 消息订阅器,内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update 方法

实现方法:

  • 1.实现compile,进行模板的编译,包括编译元素(指令)、编译文本等,达到初始化视图的目的,并且还需要绑定好更新函数;
  • 2.实现Observe,监听所有的数据,并对变化数据发布通知;
  • 3.实现watcher,作为一个中枢,接收到observe发来的通知,并执行compile中相应的更新方法。
  • 4.结合上述方法,向外暴露mvvm方法。


    执行过程

过程描述:
(1) 当创建一个vue对象时,先进入初始化阶段:(两部分工作)
一方面:vue 会遍历data的所有属性,通过object.defineproprety()方法,将所有属性变成setter和getter。 另一方面:vue的指令编译器Complie会解析每个元素节点,初始化视图,然后由watcher(订阅者)更新视图,此时watcher会将自身添加到消息订阅器(Dep)中,初始化完毕。

(2) 当数据变化时:会触发 observer数据监听器中的setter方法,setter 会调用Dep中的方法,此时Dep会去遍历所有的订阅者,然后去调用订阅者的update方法,通知订阅者进行视图更新。

参考:https://segmentfault.com/a/1190000018399478


11.vue生命周期

Vue实例有一个完整的生命周期,也就是说从开始创建、初始化数据、编译模板、挂在DOM、渲染-更新-渲染、卸载等一系列过程

  • beforeCreate :创建之前,在实例初始化之后,数据观测和事件配置之前被调用。
  • created: 创建完成,实例已完成以下配置:数据观测、属性和方法的运算,watch/event事件回调,完成了data 数据的初始化,el没有。此时dom还没渲染,可以在此处进行ajax请求。
  • beforeMount : 挂载之前,相关的render函数首次被调用(虚拟DOM),实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂在html到页面上。
  • mounted:挂载完成,此时dom已渲染完成,可以访问dom元素,只在挂载到vue 对象上执行一次,而后每次更新执行的都是update
  • beforeUpdate:在数据更新之前被调用
  • updated:数据更新之后,该钩子在服务器端渲染期间不被调用
  • beforeDestroy:销毁之前,此时vue实例依然可以使用
  • destroyed:销毁,所有的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用

详细参考连接:https://www.jianshu.com/p/672e967e201c


12.vue动态路由

在vue项目中,使用vue-router如果进行不传递参数的路由模式,则称为静态路由;
如果能够传递参数,对应的路由数量是不确定的,此时的路由称为动态路由。

比如在写商品详情页面的时候,页面结构都一样,只是商品id的不同,所以这个时候就可以用动态路由动态。

冒号后面就是动态的参数
路由配置:
const router = new VueRouter({
    routers:[
      {
        path:'/home:id'
        name:'home'
        component:home
      }
    ]
});

使用:
<template>
  <div>
    <router-link to="/home/10">衣服</router-link>
    <router-link to="/home/11">麻辣火锅</router-link>
    <router-link to="/home/12">肉夹馍</router-link>
  </div>
</template>

实现参数传递的方法:

  1. 使用query传参,name属性为要跳转的组件所对应的name,query为要携带的参数
<router-link :to="{name:'main','query':{data:'allData'}}"></router-link>
  1. 使用params传参,name属性为要跳转的组件所对应的name,params为要携带的参数
<router-link :to="{name:'main','params':{data:'allData'}}"></router-link>
  • 使用params传参时,url中不会出现参数,页面刷新后参数会消失
  • 使用query传参时,url中会出现参数,页面刷新后参数不会消失

3.设置页面默认的路由参数(query/params):

 this.$router.push( {name: 'main', 'query': {data: 'allData'} } )
this.$router.push( {path: '/main', 'query': {data: 'allData'} } )
  • 在组件中接受参数 : this.$route.query.data || this.$route.params.data

13.post、get、put、delete

post、get、put、delete就像对应着数据库的CRUD(增、删、改、查)

    post             /url          创建
    delete           /url/xxx       删除
    put              /url/xxx       更新或创建
    get              /url/xxx       查询

(1) get请求,请求会向数据库发索取数据的请求,从而来获取信息,该请求就像数据库的select操作一样,只是用来查询一下数据,不会修改、增加数据,不会影响资源的内容,即该请求不会产生副作用。无论进行多少次操作,结果都是一样的,具有幂等性。

(2) put 请求,求是向服务器端发送数据的(与get不同)从而改变信息,该请求就像数据库的update操作一样,用来修改数据的内容,但是不会增加数据的种类等,也就是说无论进行多少次put操作,其结果并没有不同,具有幂等性。

(3) post 请求,与put请求类似。都是向服务器端发送数据求会改变数据的种类等资源,就像数据库的insert操作一样,会创建新的内容。几乎目前所有的提交操作都是用POST请求的。不具有幂等性。

(4) delete 请求,用来删除某一资源,该请求就像数据库的delete操作。

put 与post 的共同点及区别?

  • put和post 都是向服务器发送数据
  • post 主要是在一个集合资源之上(url),put 主要作用在一个具体的资源之上(url/xxx)
  • put 通常指定了资源的存放位置,而post没有。post的数据存放位置由服务器自己决定,如果url可以在客户端确定,那么可使用put,否则用post
  • put 有等幂性,而post没有。
    幂等性:幂等意味着对同一个URL的多次请求会返回一样的结果

14.跨域方法

  • jsonp
  • CORS
  • webSocket
  • postMessage

详情链接:http://www.imooc.com/article/40074


15.vue插件(图表,excel)


16.callback、promise、async-await

请参考链接


17.map、reduce、filter、forEach

  • map、filter、reduce会返回新数组,返回值是新数组或结果
  • forEach会改变原来数组,forEach没有返回值
  • map:用来迭代对数组进行统一的操作(运算),返回一个新数组
  • reduce: 用来迭代一个数组,并且把它累积到一个值中
  • filter:用来迭代一个数组,并且按给出的条件过滤出符合的元素

18.for、forEach、 for-in 、 for-of

  • for循环
    遍历数组

  • forEach循环
    遍历数组,对象(不包括原型上的属性)
    循环不能中途退出,不能使用break,return

  • for-in
    这个循环是特别针对遍历对象属性的。
    会遍历对象的所有属性,包括原型上的属性和自定义属性
    对象的属性是没有顺序的,所以for-in遍历属性输出也是没有顺序的
    若对象是null或undefined有可能会报错

  • for-of
    这个循环是最棒的,不仅支持数组,还支持遍历类数组对象和其他可迭代对象。
    可以使用 break、continue、return
    for-of循环也支持字符串遍历,将字符串视为一系列的Unicode字符来进行遍历
    for-of也支持Map和Set遍历。
    for-of不遍历普通对象。

小总结:

  • for-in循环的每次迭代操作会同时搜索实例或者原型属性,for-in循环的每次迭代会产生很多开销。除非明确要迭代一个属性数量未知的对象,否则应该避免使用。 for-in 并不适合用来遍历数组中的元素,其更适合遍历对象中的属性。
  • forEach循环不会遍历原型链上的属性,不能break和return。
  • for-of 循环这是最直接、最简洁的遍历数组的方法。这个方法避开了for-in循环的所有缺陷
  • forEach 的速度不如 for
  • for in循环出的是key,for of循环出的是value
    for-in 、for-of遍历普通对象
let  arr = {
  name:'aaa',
  age:23,
  sex:'女'
}
普通对象要加可枚举的属性Object.keys(),不然报错
for(let i of Object.keys(arr)){
  console.log(i);
}  //name age sex

for(let i in arr){
  console.log(i);
}  //name age sex

for-of 遍历 Map ,初始是一个二维数组,对应的键值匹配

let test = new Map([['name','aaa'],['age',12],['sex','女']]);
for (var [key, value] of test) {
  console.log(key +" is "+ value);
}
//name is aaa
//age is 12
//sex is 女

for-of 遍历 Set ,遍历同时会进行数组的去重

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

推荐阅读更多精彩内容

  • 一、深复制和浅复制的区别? 1、浅复制:只是复制了指向对象的指针,即两个指针指向同一块内存单元!而不复制指向对象的...
    iOS_Alex阅读 1,314评论 1 27
  • 前端目录 HTML相关 CSS相关 JAVASCRIPT相关 DOM相关 HTTP相关 VUE相关 算法相关 网络...
    keyuan0214阅读 435评论 0 2
  • 前端开发面试知识点大纲: HTML&CSS: 对Web标准的理解、浏览器内核差异、兼容性、hack、CSS基本功:...
    秀才JaneBook阅读 2,251评论 0 25
  • 面试题链接地址 https://juejin.im/post/5cbff661e51d456e693f48ec#h...
    祝家庄打烊阅读 498评论 0 1
  • 1,java堆,分新生代老年代,新生代有Eden,from surviver,to surviver三个空间,堆被...
    城市里永远的学习者阅读 891评论 0 49