前端面试资料总结(持续更新)

CSS盒模型

盒模型包含了content,padding,border,margin

1.一个是标准模型:盒模型的宽高只是content的宽高
2.一个是IE模型(又叫怪异模型):盒模型的宽高是内容(content)+填充(padding)+边框(border)的总宽高。
如何统一模型:将模型的宽高都统一为内容(content)+填充(padding)+边框(border)的总宽高。

div{
    box-sizing: border-box;
}
两种盒模型

DOM事件流

JS中事件分为三个阶段: 事件捕获 --> 事件目标 --> 事件冒泡

dom事件流图示

栗子:给目标元素(text)绑定click事件,实际的(text)元素在捕获阶段不会接收到事件,意味着在捕获阶段,事件从document到<body>再到<div>后就停止了。下一个阶段是“处于目标阶段”,于是事件在(text)上发生,并在事件处理中被看成是冒泡阶段的一部分。最后,冒泡阶段发生,事件又传播回文档。
DOM层级越小,事件传播的消耗越小,在一定情况下也可以视为一种优化性能的手段

比较常见的冒泡现象:

<a href="http://www.sina.com" id='test'>sina</a></body>
<script>
    document.onclick = function() {
        alert('doc click');
        return false;
    }
    var a = document.getElementById('test');
    a.onclick = function() {
        alert('a click');
    }
</script>

正常执行顺序
1.从document慢慢找下去,判断当前元素是否是时间的触发源
2.找到事件源,执行a元素上的onclick事件
2.事件进入冒泡阶段,包含a元素的document的onclick事件
3.事件完成,进入浏览器默认行为,即跳转。

PS:如果当使用return false会打断后续行为,所以这里不会跳转
使用event.preventDefault取消浏览器默认行为
使用event.stopPropagation会取消冒泡,但不取消浏览器默认行为。

CSS层叠规则(视图上的显示层级)

显示的层级

元素居中

  • 水平居中
    行内元素: text-align: center
    块级元素: margin: 0 auto
    absolute + transform
    flex + justify-content: center

  • 垂直居中
    line-height: height
    absolute + transform
    flex + align-items: center
    table

  • 水平垂直居中
    absolute + transform
    flex + justify-content + align-items

CSS选择器问题

优先级:!important > 行内样式 > #id > .class > tag > * > 继承 > 默认
css选择器原理:采用递归方式,从右往左找,如body #box1 .box2 div span a
1.浏览器会先找所有的a标签
2.从这些a标签中找到父元素是span
3.从这些span中找父元素是div
4.从这些div中找父元素是.box2
........
优化问题:
1.层级越多需要找的时间越久,耗时,尽量直接写class或者id来找,层级顶多3层。
2.尽量不要直接写div span a,因为页面上可能有很多a标签,spandiv,会更耗时。

清除浮动

只介绍以下两种我用的,其他不赘述
1.(推荐)给浮动元素的父元素加上clearfix

.clearfix{*zoom:1;}
.clearfix:after{display:block; content:"clear"; height:0; clear:both; overflow:hidden; visibility:hidden;}

2.给浮动元素结尾处添加一个空的div,并且clear:both;

link 与 @import 的区别

1.link功能较多,可以定义 RSS,定义 Rel 等作用,而@import只能用于加载 css
2.当解析到link时,页面会同步加载所引的 css,而@import所引用的 css 会等到页面加载完才被加载,从体验来说,link要由于@import
3.@import需要 IE5 以上才能使用
4.link可以使用 js 动态引入,@import不行

javascript数据类型

值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
区别:
1.值类型变量是存放在栈区的(栈区指内存里的栈内存)
2.引用类型顾名思义只是引用,数据是存在堆内存中,如果内存中的值变化,那么引用它的变量也会变化
看下面栗子

var a = [1,2,3];
var b = a;
a.push(4);
console.log(b);  // [1,2,3,4]

关于变量提升问题

JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。
函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上
来看这一段代码

console.log(a,fun); // undefiend undefiend
var a = 1;
function fun(){}

那么,JS执行以上代码时,实际执行顺序是这样的

function fun(){}
var a;
console.log(a,fun); 
a = 1;

函数声明和函数表达式的区别

  • 函数声明
fn()                    //不会报错
function fn(){}

// 实际执行顺序为
function fn(){}
fn() 
  • 函数表达式 会将变量和函数拆分开来执行,存在变量提升问题
fn()                    //Uncaught TypeError:fn is not a function 
var a = function(){}

// 实际执行顺序为
var a;
a();
a = function(){};

闭包

js常见面试题之闭包

script标签

1.<script defer>: 异步加载,元素解析完成后执行
2.<script async>: 异步加载,与元素渲染并行执行
对于大多情况来说,script标签尽量放在html最底部引入进来,防止影响html以及css的加载,影响页面呈现的速度。

对象的深拷贝浅拷贝问题

讲一下简单实现原理
1.浅拷贝:便利对象source的属性,然后赋值到新对象target上,如果source的某一个子属性是引用类型的,那么target复制的属性的内存地址与source的的子属性指向同一内存地址。会出现如下问题:

//浅拷贝
function shallow(target, source) {
    for (let i in source) {
        target[i] = source[i];
    }
    return target;
}
var obj1 = {
    name: 'obj1',
    arr: [1, 2, 3]
},
obj2 = {};
//浅拷贝一次
shallow(obj2, obj1);
obj1.arr.push(4);
console.log(obj2.arr); // [1,2,3,4]

一些简单的浅拷贝方式:

// Object.assign
let a = {
    age: 1
}
let b = Object.assign({}, a)

// ...运算符
let a = {
    age: 1
}
let b = {...a}

2.深拷贝:在浅拷贝基础上,遇到引用类型的值需要再次执行浅拷贝,也就是递归执行浅拷贝,就不会出现浅拷贝的问题

function deep(target, source) {
    for (var i in source) {
        // 含有引用类型
        if (typeof source[i] === 'object') {
            // 这里可能是数组或者对象
            if (source[i].constructor == Array) {
                target[i] = [];
            } else {
                target[i] = {};
            }
            //需要递归执行deep拷贝
            deep(target[i], source[i]);
        } else {
            target[i] = source[i];
        }
    }
}
var obj1 = {
    name: 'obj1',
    arr: [1, 2, 3]
},
obj2 = {};
//浅拷贝一次
deep(obj2, obj1);
obj1.arr.push(4);
console.log(obj1.arr,obj2.arr); // [1,2,3,4]  [1,2,3]

最简单的实现深拷贝

var obj1 = {
    name: 'jsonObj',
    arr: [1, 2, 3]
}
//先把对象序列化成一个字符串,再转成JSON对象,就新建了一份内存
//IE7不兼容
var obj2 = JSON.parse(JSON.stringify(obj1));
obj1.arr.push(4);
console.log(obj1.arr, obj2.arr); // [1,2,3,4] [1,2,3]

对于更多出现的情况请参考lodash拷贝

new到底干了什么

1.新生成一个对象obj
2.链接到原型: obj.__proto__ = 对应的构造函数.prototype
3.修改this执行: apply
4.返回新对象

function p(age){
    alert(123123);
    this.age = age;
    this.getAge = function(){
        alert(this.age);
    }
}

// 实现一个new
function create() {
    // 创建一个空的对象
    let obj = new Object();
    
    // 获得构造函数
    let Con = [].shift.call(arguments);
    
    // 链接到原型
    obj.__proto__ = Con.prototype;
    
    // 执行构造函数,修改this指向
    let result = Con.apply(obj, arguments)
    
    // 确保 new 出来的是个对象
    return typeof result === 'object' ? result : obj
}

var aa = create(p);

类型判断

最简单的typeof,但有时并不能准确的判断出数据的类型typeof [1,2]得到object,列出我自己常用的一套方法吧:Object.prototype.toString.call(要检查的数据),根本原理是利用借用objectprototype.toString方法

// 以下是11种:
var number = 1; // [object Number]
var string = '123'; // [object String]
var boolean = true; // [object Boolean]
var und = undefined; // [object Undefined]
var nul = null; // [object Null]
var obj = {
    a: 1
} // [object Object]
var array = [1, 2, 3]; // [object Array]
var date = new Date(); // [object Date]
var error = new Error(); // [object Error]
var reg = /a/g; // [object RegExp]
var func = function a() {}; // [object Function]
console.log(Object.prototype.toString.call(Math)); // [object Math]
console.log(Object.prototype.toString.call(JSON)); // [object JSON]
//查看参数的类型
//console.log(Object.prototype.toString.call(arguments)); // [object Arguments]

//封装一下
function checkType(obj){
    return Object.prototype.toString.call(obj);
}
console.log(checkType([1, 2, 3])) // [object Array]

防抖与节流

我的另一篇文章有简述这些原理简单的聊聊节流和防抖

this指向问题

this说简单点就是:谁调用了函数,this就指向谁,在箭头函数中会稍有区别。
箭头函数中的this指向:箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值,看下面的栗子:

function Person() {  
    this.age = 111;  
    setTimeout(() => {
        // 回调里面的 `this` 变量就指向了期望的那个对象了
        console.log(this)
    }, 1000);
}
Person() // Window  因为Person方法挂载到Window上了,上下文中的this也指向Window
var p = new Person() //Person {age: 111}  构造函数新生成的对象,上下文中的this指向p

修改this指向 call和apply和bind的区别

原方法fn(1,2),修改后fn中的this指向了target,修改this指向的方法如下,三种方式作用相同,只是调用方式不同:

  • call: fn.call(target, 1, 2)
  • apply: fn.apply(target, [1, 2])
  • bind: fn.bind(target)(1,2)
function a(){
    console.log(this.myName)
}
a() //undefined
var b = {
    myName:"我是b"
}
a.call(b) // 我是b
a.apply(b) // 我是b
a.bind(b)() // 我是b

函数柯里化

在一个函数中,首先填充几个参数,然后再返回一个新的函数的技术,称为函数的柯里化。通常可用于在不侵入函数的前提下,为函数预置通用参数,供多次重复调用。

const curry = function add(x) {
    return function (y) {
        return x - y
    }
}

// 通用参数1
const reduce = curry(1)
add1(2) === 1
add1(20) === 19

跨域问题

web前端跨域的一些解决方案

JavaScript 执行机制

这一次,彻底弄懂 JavaScript 执行机制

从输入 url 到展示的过程

  • DNS 解析
  • TCP 三次握手
  • 发送请求,分析 url,设置请求报文(头,主体),协商缓存问题
  • 服务器返回请求的文件 (html)
  • 浏览器渲染
    1.HTML parser --> DOM Tree。html解析,dom数构建
    2.CSS parser --> Style Tree。解析 css 代码,生成样式树
    3.attachment --> Render Tree。结合 dom树 与 style树,生成渲染树
    4.layout: 布局
    5.GPU painting: 像素绘制页面

重绘和重排(回流)

  • 重绘(repaint): 当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要UI层面的重新像素绘制,因此 损耗较少

  • 重排(回流)(reflow): 当元素的尺寸、结构或触发某些属性时,浏览器会重新渲染页面,称为重排(回流)。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。会触发重排(回流)的操作:

    1.页面初次渲染
    2.浏览器窗口大小改变
    3.元素尺寸、位置、内容发生改变
    4.元素字体大小变化
    5.添加或者删除可见的 dom 元素
    6.激活 CSS 伪类(例如::hover)
    7.查询某些属性或者使用某些方法

    clientWidth、clientHeight、clientTop、clientLeft
    offsetWidth、offsetHeight、offsetTop、offsetLeft
    scrollWidth、scrollHeight、scrollTop、scrollLeft
    getComputedStyle()
    getBoundingClientRect()
    scrollTo()
    

重绘的开销较小,重排(回流)的开销较高。
一些优化的操作:

  • 避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局
  • 将CSS动画效果(transform)应用到position属性为absolute或fixed的元素上(定位元素修改不影响页面结构)
  • JS中避免频繁操作样式,可汇总后统一 一次修改
  • JS中尽量使用class进行样式修改,尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。
  • 减少dom的增删次数,可使用拼接好的字符串append或者documentFragment一次性插入
  • 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流
  • 避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。

前端存储

  • cookie: 通常用于存储用户身份,登录状态等,http 中自动携带, 体积上限为 4K, 可自行设置过期时间
  • localStorage / sessionStorage: 长久储存/窗口关闭删除, 体积限制为 4~5M
  • indexDB

js内存问题

内存泄漏:不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。
V8垃圾回收机制:将内存中不再使用的数据进行清理,释放出内存空间。
常见内存泄漏的原因以及解决办法(让垃圾回收机制认为其不会再被使用):
1.全局变量,不会被回收。解决:用完需要手动赋值为null
2.定时器:没有被清理。解决:用完需要clear
2.闭包常驻内存引起
3.dom元素被清空或删除时,其绑定的事件未清除 被清空或删除的元素。解决:手动解绑事件removeEventListener

常见状态码

  • 1xx: 接受,继续处理
  • 200: 成功,并返回数据
  • 201: 已创建请求
  • 202: 服务端已接受请求
  • 203: 成为,未授权
  • 204: 成功,无内容
  • 205: 成功,重置内容
  • 206: 成功,部分内容
  • 301: 永久移动,重定向
  • 302: 临时移动,可使用原有URI
  • 304: 资源未修改,可使用缓存
  • 305: 需代理访问
  • 400: 请求语法错误
  • 401: 要求身份认证
  • 403: 拒绝请求
  • 404: 资源不存在
  • 500: 服务器错误

get / post区别和相同

  • GET在浏览器回退时是无害的,而POST会再次提交请求。

  • GET产生的URL地址可以存书签,而POST不可以。

  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。

  • GET请求只能进行url编码,而POST支持多种编码方式。

  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。因为参数直接暴露在URL上,所以不能用来传递敏感信息,POST比GET安全

  • GET请求在URL中传送的参数是有长度限制的,而POST么有。GET参数通过URL传递,POST放在Request body中

  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

  • GET产生一个TCP数据包;POST产生两个TCP数据包。
    对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
    而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。也就是说,GET只需要跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。在网速快时,多跑一趟消耗的时间可以忽略不计的。并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

  • GET/POST最底层都是TCP链接,底层相同
    HTTP定义了好几个不同的请求方式名:GET, POST, PUT, DELETE等等都有其独特的意义。但HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。就像校规规定了不能抽烟,但我依然可以偷偷的抽。要给GET加上request body,给POST带上url参数,技术上是完全行的通的。

前端安全问题

  • XSS攻击: 注入恶意代码

    • cookie 设置 httpOnly
    • 转义页面上的输入内容和输出内容 如<>转义为&lt &gt
  • CSRF: 跨站请求伪造,防护:

    • get 不修改数据
    • 不被第三方网站访问到用户的 cookie
    • 设置白名单,不被第三方网站请求 如服务端CORS设置请求头Access-Control-Allow-Origin: 域名白名单
    • 请求校验,如token

双向绑定之Proxy

目前,Vue 的反应系统是使用数据劫持 Object.definePropertygettersetter。 但是,Vue 3 将使用 ES2015 Proxy 作为其观察者机制。两者的区别 。这消除了以前存在的警告,使速度加倍,并节省了一半的内存开销。理解Proxy

AMD和CMD的区别

  • AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
  • CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

关于vue或者react组件中需要写key的必要性

vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点。

<ul>
<li v-for="i in 10" :key="i">{{i}}</li>
</ul>

没有key:当其中一个li发生变化时,会便利所有li,找出其中变化的项
有key:会通过对应的key值去映射,不用便利所有节

JS运算符优先级问题,以及函数声明优先级问题

运算符优先级
  function Foo () {
    getName = function () { alert(1) }
    return this
  }
  Foo.getName = function () { alert(2) }
  
  Foo.prototype.getName = function () { alert(3) }

  var getName = function () { alert(4) }

  function getName () { alert(5) }

//输入的值
  Foo.getName();
  getName();
  Foo().getName();
  getName();
  new Foo.getName();
  new Foo().getName();
  new new Foo().getName();

  // 结果
  Foo.getName(); //2
  getName(); //4
  Foo().getName(); //1
  getName();//1
  new Foo.getName(); //2
  new Foo().getName(); //3
  new new Foo().getName(); //3

上题主要测试了JS运算符优先级问题,以及函数声明优先级问题,参考文章:一道被前端忽略的基础题

var和let和const的区别

  • var存在变量提升问题,可以重复声明
  • const不能被修改,不能被重复声明
  • let以下
// 同一作用域下,已经被声明的变量不能再被声明
let a = 0;
let a = 1; //Identifier 'a' has already been declared

// 暂时性死区问题,即不存在变量提升问题
b = 111;
let b; // b is not defined

// 经典面试题
for ( var i=1; i<=5; i++) {
    setTimeout( function timer() {
        console.log( i );
    }, i*1000 );
}

// 使用let之后
for ( let i=1; i<=5; i++) {
    setTimeout( function timer() {
        console.log( i );
    }, i*1000 );
}
// 相当于
{ // 形成块级作用域
  let i = 0
  {
    let ii = i
    setTimeout( function timer() {
        console.log( ii );
    }, i*1000 );
  }
  i++
  {
    let ii = i
  }
  i++
  {
    let ii = i
  }
  ...
}

同步和异步的区别是什么

js单线程语言(不能同时干两件事),异步:定时器,ajax
以下代码,从上往下执行:
1.同步队列---打印1
2.发现定时器,把2加入到异步队列
3.同步队列---打印3
4.发现定时器,把3加入到异步队列,发现3等待的时间比2短,3插队,排在2之前
5.同步队列---打印5
6.同步任务全部执行完成,开始执行异步队列
7.按照队列 ----- 3 ----- 2

console.log(1)

setTimeout(function(){
    console.log(2)
},1000)

console.log(3)

setTimeout(function(){
    console.log(4)
},0)

console.log(5)

Date的方法

Date.now() //获取当前时间毫秒数
  
var dt = new Date()
dt.getTime()        //获取毫秒数
dt.getFullYear()    //年
dt.getMonth()       //月(0-11)
dt.getDate()        //日(0-31)
dt.getHours()       //小时(0-23)
dt.getMinutes()     //分钟(0-59)
dt.getSeconds()     //秒(0-59)

获取2016-06-10格式的日期

function formatDate(dt){
    if(!dt){
        dt = new Date()
    }

    var year  = dt.getFullYear()
    var month = dt.getMonth() + 1
    var date  = dt.getDate()

    if(month < 10){
        //强制类型转换
        month = '0' + month 
    }

    if(date < 10){
        //强制类型转换
        date = '0' + date
    }
    //强制类型转换
    return year + '-' + month + '-' + date
}

Array的方法

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

// forEach不会对空数组进行检测。
arr.forEach( function(item,index){ 
    // 无法break
    console.log(index,item); 
});

// every不会对空数组进行检测。
// every不会改变原始数组。
var result = arr.every(function(index,item){
//所有成员都满足一个条件才为true
    if(item<6) 
        return true
});

// some不会对空数组进行检测。
// some不会改变原始数组。
var result = arr.some(function(index,item){ 
//一个满足条件就为true
    if(item<5) 
        return true;
}); 
console.log(result);

// 返回一个数组,原数组会被改变
var arr2 = arr.sort(function(a,b){ 
    //从小到大排序 return a-b; 
    //从大到小排序 return b-a;
})

// map不会对空数组进行检测。
// map 不会改变原始数组。
arr.map(function(item,index){
    // 每位数都X2
    return item*2
});

// filter不会对空数组进行检测
// filter不会改变原始数组
var arr2 = arr.filter(function (item,index){ 
    //通过某一个条件过滤数组,返回新数组
    return item > 3
})

join: 通过指定连接符生成字符串
push / pop: 末尾推入和弹出,改变原数组, 返回推入/弹出项
unshift / shift: 头部推入和弹出,改变原数组,返回操作项
sort(fn) / reverse: 排序与反转,改变原数组
concat: 连接数组,不影响原数组, 浅拷贝
slice(start, end): 返回截断后的新数组,不改变原数组
splice(start, number, value...): 返回删除元素组成的数组,value 为插入项,改变原数组
indexOf / lastIndexOf(value, fromIndex): 查找数组项,返回对应的下标

事件代理

需求:点击li时,得到对应的数字
为每个li绑定事件(绑定多次事件)是没必要的,使用代理:

<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
document.querySelector('ul').onclick = function(event){
    // 通过event.target得到对应的li
    alert(event.target.innerTxt);
}
</script>

关于0.1 + 0.2 != 0.3的解决办法

parseFloat((0.1 + 0.2).toFixed(10))

关于['1','2','3'].map(parseInt)

console.log(['1','2','3'].map(parseInt)); // 1 NaN NaN

基于map方法,默认回传数组的(item,index,Arrar)。相当于执行了以下函数:
parseInt('1',0,['1','2','3'])
parseInt('2',1,['1','2','3'])
parseInt('3',2,['1','2','3'])
来看parsInt:

image.png

  • 第一次,当我我们第一次调用的时候 是这样的:parseInt('1',0) 这个是没问题的 转十进制的 看我红框的图片返回 1

  • 第二次,调用第二个index参数是1,也是说1作为数值的基础。规范里说的很清楚了,如果基础是非0或者小于2,函数都不会查询字符串直接返回NaN。

  • 第三次,2作为基数。这就意味着字符串将被解析成字节数,也就是仅仅包含数值0和1。parseInt的规范第十一步指出,它仅尝试分析第一个字符的左侧,这个字符还不是要求基数的有效数字。这个字符串的第一个字符是“3”,它并不是基础基数2的一个有效数字。所以这个子字符串将被解析为空。函数将返回为NaN。

cookies与session有什么区别

由于http请求是无状态的,需要cookie来做身份验证
1.cookies由服务端创建,发送给浏览器端,当用户发出请求后,带上cookie发送给服务端做验证。
2.来回传递过程中,占用带宽,消耗网络资源,并且容易被中间人获取或浏览器端用户篡改十分不安全
3.cookies大小只有4k

1.session主要存在于服务端,不会被发送到浏览器所以很安全
2.如果没有设置过期时间,在会话结束后session会自动消失
3.session主要用于服务端保存请求信息的机制

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

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,406评论 1 45
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,725评论 1 92
  • 请参看我github中的wiki,不定期更新。https://github.com/ivonzhang/Front...
    zhangivon阅读 7,097评论 2 19
  • $HTML, HTTP,web综合问题 1、前端需要注意哪些SEO 2、 的title和alt有什么区别 3、HT...
    Hebborn_hb阅读 4,573评论 0 20
  • $HTML, HTTP,web综合问题 1、前端需要注意哪些SEO 3、HTTP的几种请求方法用途 4、从浏览器地...
    peng凯阅读 768评论 0 1