前端面试【有感而发】

前端面试【有感而发】

2015/09/16 · HTML5,
JavaScript · 1
评论 ·
面试

原文出处:
聂微东(@聂微东)   

首先,这篇没有具体的面试题;

其次,这篇仅是我个人的面试态度;

最后,在这金三银四的跳槽季里,祝愿各位找到好工作。

俺第一次做面试官是2011年,想起那时自己真的很紧张(不管做什么头几次都紧张哈),可是还是在希望在面试者面前留个比较专业的印象,所以总是装作很淡定,记得那时总会放一件修身小西装放公司,专门用来面试的时候穿的,装成熟,你懂得。现在回忆起那时的点滴,不由自主的会嘴角上扬:)

图片 1

——————————- 低调的分割线 ——————————-

 

“全世界都缺前端” ——
这话总会被提起,PM尤其是喜欢这么说,而且还是在工作推动的过程中(我会告诉你我这是在黑PM么)

面试一直是俺工作中重要的一块,而且自己也喜欢去参与面试(工作忙爆的时间除外)。原因究竟为甚其实我自己也说不上来,可能是因为心里希望在工作时可以与聪明的人合作吧;也可能是希望通过面试push自己去主动了解行业新的技术…Anyhow,也就一头扎进了面试官的行列,且乐此不疲。

图片 2

前端回忆录  

8年前的前端做些什么?页面重构(HTML+CSS)和实现页面交互(JS+CSS);jQuery也是在8年前诞生(06年8月发布V1.0);

4年前业内提出大前端,这直接让前端职位在产品和业务中变得更加重要,甚至是最重要的存在,在以前的技能基础上又需要掌握一门服务端语言和少量数据库的经验(从那时开始身边经常有朋友由后端转前端);

2年前的前端界Node开始疯狂火热,且一扫各种前端论坛、开源项目,狂热者更提出“JS一统WEB开发”的头号,数据结构简单点的网站建设只需要一个工程师即可搞定,那就是前端,叼炸天呀;

Now,全端工程师???maybe…

移动互联网风光依旧,前端更是无处不在。

可是… …

招人真心难,招前端更难,招个好前端难上加难有木有~~

图片 3

主观意识 & 经验主义  

工程师每轮面试时间一般为一小时左右,除非面试官对你没有兴趣,否则不会十几分钟就打发走你(我厂要求面试至少20分钟)。而且就在这差不多一小时,面试官要判断你是否符合招聘的岗位,这本身就是一件非常挑战的事情。正因为这样,所以面试官的决定都有一定的风险和主观意识,这不可避免。

许久以前看过一篇跟面试相关的文章,具体内容说什么忘记了,不过里面有一句话给我印象深刻,大概意思是:“很多面试官希望能招到个像自己的人,和自己类似的人”。很容易理解这句话,因为和自己类似所有更容易引起自身的关注,而且记忆会更深刻。这个“类似”俩字我理解应该至少包括几个方面:技术方向、性格、思维方式等。

我也同意会带着主观意识去面试,但我认为这并不是什么糟糕的事情。

具体点说,我会考虑你是否会push甚至引导团队的成长、与你合作是否会愉快,这也是我参与面试的原因之一。在此,希望你静静思考下,你在团队中是否属于这类人,至于是与不是由看官您自己评判了:)

图片 4

技术一面  

通常情况下工程师面试都有几轮?不管几轮都很正常,反而很少有听说只有一轮面试的,所以这里说的一面是纯技术的面试。

有时我会为面试面到一名优秀的同学而高兴不已,因为聊天会很畅快,而且决定很明朗。

更多时候我会比较纠结,因为我需要考虑给不给面试者通过我这关。正因如此,其实很多时候我做的每个选择都有一定的运气成分。

俺初期做面试官的时候,基本都是我主动来发问和出题,用自己的主观意识去考察面试者的方方面面。那时想当然的认为,这份岗位需要这些XX技能和用到这些XX技巧,所以如果面试者具备这些知识点就可以通过。

再后来面试的经验提升了,想明白了学习能力、思维方式和技术能力同样非常重要,所有会主要针对面试者比较擅长的领域来【交流、讨论】。

在面试这个过程里,我现在总会在正式面试之前,和面试者说句话:“面试就是聊天,我们简单聊聊吧”。

图片 5

本来想随便配个图,可是看到这个图片突然想起一首儿歌:丢肥皂 丢肥皂
轻轻的放在小基友的后面 大家不要告诉他 快点快点捉住他,快点快点捉住他…

好吧,节操碎了一地。

 

我的期待  

下周已经安排有六个面试。请思考,作为一名面试官应该对你又有怎样的期待?

俺的面试时的问题一般不固定,因为我不喜欢背题的做法。

有一定工作经验最好,当然没有也同样有机会,而且有工作经验对于面试也不一定都是好事。

PS:工作年限和项目经验决定了你的知识储备,所以也会有针对性的调整难度和问题。

 

在我看来评价一名同事是否优秀其实很简单, 看看他是否够【专业】就行了。那么合计合计,你自己对待工作是否对得住专业俩字。至于怎么理解专业俩字,还是见仁见智吧。

简历造假或者过分夸大。夸大自己的工作确实也属正常,可是如果夸大、夸大程度都需要有底线可言。经常会看到简历上写着精通XX,比如jQuery,然后面试的一问没有读过源码,对其细节原理说不出所以然来,这还不如不写。

记得前不久在微博上看 @朴灵 说过:“如果你的GitHub上没有任何项目和代码,简历上还是别填GitHub地址了,没啥好处的。”

期待你不要紧张、而且自信,让自己好的一面尽量的展现出来,努力把面试官当成你的同事,你只是与他探讨工作中的问题。甚至可以多提些自己觉得有意思的想法,如果能够和面试官一直存于一个较愉快的谈话环境,相信你的面试结论上,面试官一定不会吝啬对你进行正面的评价。

图片 6

总结  

面试其实也是修心的过程。

我毕业初期时找工作也并不顺利,不过多次在找工作面试的过程中经常会遇见很好的面试官,就算你没有达到他们的岗位要求,他们还是会中肯的给你一些靠谱的建议。这些面试过程就非常的美好,其实结果不一定是最重要的,过程也一样美妙,不是吗。

最后,请带着你积极的心态,好好享受每一次面试。

祝好

2 赞 3 收藏 1
评论

图片 7

目录

  • CSS相关
    • 选择器
      • 属性选择器

1.箭头函数使用需要注意的地方
this、new、arguments

***1.准备充分
2.知识系统
3.沟通简洁
4.内心诚实
5.态度谦虚
6.回答灵活

1、数据双向绑定

http://jixianqianduan.com/frontend-javascript/2015/11/29/js-data-two-ways-binding.html

实现方式:
(1)发布-订阅模式(backbone.js)
http://www.html-js.com/article/Study-of-twoway-data-binding-JavaScript-talk-about-JavaScript-every-day

(2)脏值检查(angular 1.0)
最简单就是使用 setInterval() 定时轮询检测数据变动,Google
是在指定的事件发生时进行检测,如DOM事件,XHR响应事件,Timer事件

(3)数据劫持(+发布-订阅模式)(Vue.js)
Object.defineProperty() 对数据对象做get和set的监听

https://segmentfault.com/a/1190000006599500

CSS相关

  • this对象的指向是可变的,但在箭头函数中是固定的,指向定义时所在的对象,而非调用时所在的对象
  • 不可以做构造函数,也就是不能使用new,否则抛出一个错误
  • 不可以使用arguments,因为它在函数体内不存在,可以用rest代替
    2.将arguments转换为数组

一面:
1.页面布局
H5最大的特点就是标签语义化,可以使我们和浏览器更好的理解结构与阅读

2、https的过程?https将什么加密了?

http://blog.csdn.net/wangjun5159/article/details/51510594

  • 客户端发送请求到服务器
  • 服务器返回证书和公开密钥,公开密钥作为证书的一部分而存在
  • 客户端验证证书和公开密钥的有效性,如果有效,则生成共享密钥并使用公开密钥加密发送到服务器
  • 服务器使用私有密钥解密数据,并使用收到的共享密钥加密数据,发送到客户端
  • 客户端使用共享密钥解密数据
  • SSL加密建立

https 加密了共享密钥和数据

对性能的影响:

  • 加密解密消耗了计算机的CPU资源
  • 连接过程中客户端与服务器的通信次数比三次握手多,建立连接的时间花销较大

选择器

图片 8

3、实现 remove 删除 object 的属性

// 如果键名不是字符串,则用一个变量保存键名
Object.prototype.remove = function (attr) {
    delete this[attr];
}

属性选择器

~=

空格分割的值包含某值

.target[xxx~=yyy]{}

<div kk="aaa bbb yyy ccc"></div>

|=

连字符的值包含某值([lang~=en], 如<div lang=”en-us”>)

.target[lang~=en]{}

<div lang="en-us">

^=

以”xxx”开头

.target[attr1^=xxx]{}

$=

以”xxx”结尾

.target[attr1$=xxx]{}

\=*

包含”xxx”

.target[attr1*=xxx]{}

var arr = Array.prototype.slice.apply(arguments);

%`FOJEK0)}L)$5{BP(XDW4C.png

4、实现 map

Array.prototype.myMap = function (callback, context) {
    context = context || window;

    var newArray = [];

    if (typeof callback === 'function') {
        for (i = 0; i < this.length; i++) {
            var val = callback.call(context, this[i], i, this);
            newArray[i] = val;
        }
    }

    return newArray;
}

伪类选择器

:link :visited :hover :active

<a></a>的样式顺序

:focus

表单获得焦点的样式

:first-child

如p:first-child, 指的是第一个p, 不是p的第一个元素.
必须声明<!DOCTYPE>,这样:first-child才能在IE中生效

:last-child

类似:first-child

:lang

q:lang(no), <lang=”no”>

:first-of-type

选择属于其父元素的首个 <x> 元素的每个 <p>
元素。与:first-child的不同在于它是区分类型的

:last-of-type

类似:first-of-type

:only-of-type

选择属于其父元素唯一的 <x> 元素的每个 <x> 元素。

:only-child

选择属于其父元素的唯一子元素的每个 <x> 元素。Internet Explorer
不支持 :only-child 选择器

:nth-child(n)

你懂的

:nth-last-child(n)

你懂的

:nth-of-type(n)

:nth-child在基础上多了类型限制

:nth-last-of-type(n)

:nth-last-child在基础上多了类型限制

:root

选择文档的根元素

:empty

选择没有子元素的每个元素(包括文本节点)

:target

(选择当前活动的 锚 元素)

:enabled

(如input的disabled=”disabled”)

:disabled

(如input的disabled=”disabled”)

:checked

(如input的checked=”checked”)

:not

(selector) (selector可以为一般选择器)

::selection

(选择被用户选取的元素部分。例如文本.)

可以理解为arguments.slice()(当然arguments里面没有slice方法)

解决方式:5种
1.float 2.position 3.flexbox 4.table 5.网格布局
1.float详解

5、实现 compose

// 自左到右
var flow = function (...funcs) {
    var length = funcs.length;
    var index = length;

    while (index--) {
        if (typeopf funcs[index] !== 'function') {
            throw new TypeError('Expected a function');
        }
    }
    return function (...args) {
        var index = 0;
        var result = length ? funcs[index].apply(this, args) : args[0];

        while (++index < length) {
            result = func[index].call(this, result);
        }

        return result;
    }
}

// 自右到左
var flowRight = function (...funcs) {
    return flow(funcs.reverse());
}

其他选择器

+

相邻

h1+p{}

~

后面兄弟

h1~p{}
var arr = [...arguments];
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Layout</title>
        <style media="screen">
                        html *{
                margin: 0;
                padding: 0;
            }
            .layout article div{
                min-height: 100px;
            }
            .layout.float .left{
                float: left;
                width: 300px;
                background: red;
            }
            .layout.float .right{
                float:right;
                width: 300px;
                background: blue;
            }.layout.float .center{
                background: yellow;
            }   
        </style>
    </head>
    <body>
        <section class="layout float">
            <article class="left-right-center">
                <div class="left"></div>
                <div class="right"></div>
                <div class="center">
                    <h1>浮动解决方案</h1>
                    1.这是三栏布局中间部分
                    1.这是三栏布局中间部分
                </div>
            </article>
        </section>
    </body>
</html>

6、浏览器缓存

http://web.jobbole.com/82997/

<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">

3.rest参数
用于获取函数的多余参数,它是一个数组

优点:兼容性很好
缺点:浮动是脱离文档流,如果处理不好,会产生很多的局限。
文档流详解:本来这个标签是属于文档流管理的,那么它应该按照文档流的正常布局方式从左至右从上之下,并且符合标签本身的含义。
脱离文档流是指,这个标签脱离了文档流的管理。不受文档流的布局约束了,并且更重要的一点是,这个标签在原文档流中所占的空间也被清楚掉了。
2.position

7、移动端点击事件的300ms延时

http://blog.csdn.net/qq\_34986769/article/details/62046696

  • 禁用缩放
  • 更改视口宽度
  • 使用指针事件(IE10+):touch-action(非标准css)
  • FastClick

点击穿透(使用touchstart代替click时会出现的情况):

假如页面上有两个元素A和B。B元素在A元素之上。我们在B元素的touchstart事件上注册了一个回调函数,该回调函数的作用是隐藏B元素。我们发现,当我们点击B元素,B元素被隐藏了,随后,A元素触发了click事件。

这是因为在移动端浏览器,事件执行的顺序是touchstart > touchend >
click。而click事件有300ms的延迟,当touchstart事件把B元素隐藏之后,隔了300ms,浏览器触发了click事件,但是此时B元素不见了,所以该事件被派发到了A元素身上。如果A元素是一个链接,那此时页面就会意外地跳转。

add(...values){ } //values获取的是add的全部参数
add(arr, ...values){ }//values获取的是剩余的参数
        <section class="layout absolute">
            <style>
                .layout.absolute .left-right-center>div{
                    position: absolute;
                }
                .layout.absolute .left{
                    left: 0;
                    width: 300px;
                    background: red;
                }
                .layout.absolute .right{
                    right: 0;
                    background: blue;
                    width: 300px;
                }
                .layout.absolute .center{
                    left: 300px;
                    right: 300px;
                    background: yellow;
                }
            </style>
            <article class="left-right-center">
                <div class="left"></div>
                <div class="right"></div>
                <div class="center">
                    <h1>绝对定位解决方案</h1>
                    1.这是三栏布局中间部分
                    1.这是三栏布局中间部分
                </div>
            </article>
        </section>

8、HTTP状态码

http://www.runoob.com/http/http-status-codes.html

  • 1** :信息,服务器收到请求,需要请求者继续执行操作
  • 2** :成功,操作被成功接收并处理
  • 3** :重定向,需要进一步的操作以完成请求
  • 4** :客户端错误,请求包含语法错误或无法完成请求
  • 5** :服务器错误,服务器在处理请求的过程中发生了错误

200:请求成功

301:永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替

302:临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI

304:未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源

307:临时重定向。与302类似。使用GET请求重定向

400:客户端请求的语法错误,服务器无法理解

401:请求要求用户的身份认证

403:服务器理解请求客户端的请求,但是拒绝执行此请求

404:服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置”您所请求的资源无法找到”的个性页面

410:客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置

500:服务器内部错误,无法完成请求

501:服务器不支持请求的功能,无法完成请求

注意:rest参数只能是最后一个参数,否则报错;
rest参数可替代arguments

好处:快捷,不容易出问题
缺点:因为绝对定位本身脱离了文档流,这就要求下面的子元素也要脱离文档流,它的有效性不是很好
3.flexbox

9、原型链

对象的原型指向原型对象,原型对象的原型又指向其父类的原型…

obj.__proto__ = Object.prototype

//arguments变量的写法
const sortNum = () => Array.prototype.slice.call(arguments).sort();
//rest参数的写法
const sortNum = (...numbers) => numbers.sort();
        <section class="layout flexbox">
            <style>
                .layout.flexbox{
                    margin-top: 150px;
                }
                .layout.flexbox .left-right-center{
                    display: flex;
                }
                .layout.flexbox .left{
                    width: 300px;
                    background: red;
                }
                .layout.flexbox .right{
                    background: blue;
                    width: 300px;
                }
                .layout.flexbox .center{
                    flex: 1;
                    background: yellow;
                }
            </style>
            <article class="left-right-center">
                <div class="left"></div>
                <div class="center">
                    <h1>flexbox解决方案</h1>
                    1.这是三栏布局中间部分
                    1.这是三栏布局中间部分
                </div>
                <div class="right"></div>
            </article>
        </section>

10、babel配置, webpack配置,gulp配置

http://www.ruanyifeng.com/blog/2016/01/babel.html

webpack配置:

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  devtool: '#eval-source-map'   // 包含dataURL
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'   // 只在末尾加上sourcemap文件的地址,需要请求
  module.exports.plugins = [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    })
  ]
}

"scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}

// 导入模块
var gulp = require('gulp');
var cssmin = require('gulp-cssmin');
var uglify = require('gulp-uglify');
var htmlmin = require('gulp-htmlmin');
var rename = require('gulp-rename');    // 改名

// 配置任务
gulp.task('uglify:css', function() {
    gulp.src('css/*.css')
        .pipe(cssmin())        // 压缩
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('build/css'))    // 输出
});
gulp.task('uglify:js', function() {
    gulp.src('js/*.js')
        .pipe(uglify())                    // 压缩
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('build/js'))    // 输出
});
gulp.task('uglify:html', function() {
  gulp.src('*.html')
      .pipe(htmlmin({                    // 压缩
          collapseWhitespace: true,
          removeComments: true
      }))
      .pipe(gulp.dest('build'))        // 输出
});

gulp.watch('*.*', ['uglify:css', 'uglify:js', 'uglify:html']);

gulp.task('default', ['uglify:css', 'uglify:js', 'uglify:html']);

4.扩展运算符…
作用:将数组转换为一个参数序列

移动端很多都使用,基本比较完美
4.table

11、同源策略,跨域方式,手动实现jsonp

同源策略
对于绝对的URIs,源就是{协议,主机,端口}定义的。只有这些值完全一样才认为两个资源是同源的。

同源策略可以保护用户信息,防止用户在A网站的信息被B网站获取到

cookie只有同源的网站可以访问到,可设置document.domain设置同源获取cookie,localstorage和IndexDB不可以通过这种方式获取
cookie 可设置所属域名为一级域名,其二级域名,三级域名等就可以直接获取

iframe和window.open可以通过片段识别符(即url的#后面的内容)修改和获取

window.postMessage可以跨文档通信

http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

跨域方法:

  • jsonp

  • document.domain设置同源

    使用条件:

    • 有其他页面 window 对象的引用。
    • 二级域名相同。
    • 协议相同。
    • 端口相同。
  • window.name

    https://segmentfault.com/a/1190000003642057

  • window.postMessage(HTML5)

  • websocket(里面发出的请求头包含了Origin,指定了请求源)

  • CORS(允许任何类型的转换)

    IE10+

    简单请求和非简单请求,跟正常的ajax调用差不多,关键是服务器实现CORS接口

    http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

手动实现jsonp

function addScriptTag (src) {
    var scriptTag = document.createElement('script');
    scriptTag.setAttribute('type', 'text/javascript');
    scriptTag.src = src;
    document.body.appendChild(scriptTag);
}

window.onload = function () {
    addScriptTag('http://example.com/ip?callback=foo');
}

function foo(data) {
    console.log('Your public Ip address is: ' + data.ip);
}

服务器返回的信息

foo({
    'ip': '8.8.8.8'
});
//ES5的写法
var arr1 = [0,1,2];
var arr2 = [3,4,5];
Array.prototype.push.apply(arr1,arr2);
console.log(arr1);
        <section class="layout table">
            <style>
                .layout.table .left-right-center{
                    width: 100%;
                    display: table;
                    height: 100px;
                }
                .layout.table .left-right-center>div{
                    display: table-cell;
                }
                .layout.table .left{
                    width: 300px;
                    background: red;
                }
                .layout.table .right{
                    background: blue;
                    width: 300px;
                }
                .layout.table .center{
                    background: yellow;
                }
            </style>
            <article class="left-right-center">
                <div class="left"></div>
                <div class="center">
                    <h1>表格解决方案</h1>
                    1.这是三栏布局中间部分
                    1.这是三栏布局中间部分
                </div>
                <div class="right"></div>
            </article>
        </section>

12、手动实现ajax

http://www.jb51.net/article/104873.htm

function ajax ({url, type = 'GET', data = {}, success, error}) {
    type = type.toUpperCase();
    data = formatData(data);
    var xhr = null;
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else {
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            var status = xhr.status;
            if (status >= 200 && status < 300) {
                var response = '';
                var type = xhr.getResponseHeader('Content-type');
                if (type.indexOf('xml') !== -1 && xhr.responseXML) {
                    response = xhr.responseXML;
                } else if (type == 'application/json') {
                    response = JSON.parse(xhr.responseText);
                } else {
                    response = xhr.responseText;
                }
                success && success(response);
            } else {
                error && error(response);
            }
        }
    }

    if (type === 'GET') {
        xhr.open(type, url + '?' + data, true);
        xhr.send();
    } else {
        xhr.open(type, url, true);
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
        xhr.send(data);
    }

    function formatData (data) {
        var arr = [];
        for (var name in data) {
            arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
        }
        // 加上一个随机数,防止缓存
        arr.push('v=' + random());

        return arr.join('&');
    }

    function random () {
        return Math.floor(Math.random() * 10000 + 500);
    }
}

打印: [0, 1, 2, 3, 4, 5]

优点:兼容性很好
缺点:当3栏布局中,有一栏的布局,高度增加的时候,其他2个也会同步增加。这个也不算缺点,只是有点局限,根据情况自行使用。
5.grid(网格)

13、渐进增强和优雅降级

渐进增强:一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验

优雅降级:一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用css3的特性构建了一个应用,然后逐步针对各大浏览器进行hack使其能在低版本浏览器上正常浏览。

http://www.jianshu.com/p/d313f1108862

//使用ES6
var arr1 = [0,1,2];
var arr2 = [3,4,5];
arr1.push(...arr2);

//ES5的写法
var arr1 = [0,1,2];
var arr2 = [3,4,5];

console.log(arr1.concat(arr2));
        <section class="layout grid">
            <style>
                .layout.grid .left-right-center{
                    display: grid;
                    width: 100%;
                    grid-template-rows:100px;
                    grid-template-columns:300px auto 300px ;
                }
                .layout.grid .left{
                    background: red;
                }
                .layout.grid .right{
                    background: blue;
                }
                .layout.grid .center{
                    background: yellow;
                }
            </style>
            <article class="left-right-center">
                <div class="left"></div>
                <div class="center">
                    <h1>网格解决方案</h1>
                    1.这是三栏布局中间部分
                    1.这是三栏布局中间部分
                </div>
                <div class="right"></div>
            </article>
        </section>

14、HTTP长连接,keep-alive

Connection: keep-alive
keep-alive: 20ms

保持TCP的长连接不断开,20ms
后断开连接,TCP的keep-alive是检查当前TCP连接是否还活着,两者概念不一样,使用Content-Length(静态)或Transfer-Encoding(动态,chunk模式)判断消息内容的大小

http://www.cnblogs.com/skynet/archive/2010/12/11/1903347.html

打印: [0, 1, 2, 3, 4, 5]

相当于栅格布局,还是比较完美,

15、从输入url到看到页面发生了什么

http://www.cnblogs.com/xianyulaodi/p/6547807.html

  • 输入地址
  • 浏览器查找域名的IP地址
  • 浏览器向web服务器发送一个HTTP请求
  • 服务器的永久重定向响应
  • 浏览器跟踪重定向地址
  • 服务器处理请求
  • 服务器返回一个HTTP响应
  • 浏览器显示HTML
  • 浏览器发送请求获取嵌在HTML中的资源(如图片,音频,视频,JS,CSS等)
var arr1 = [0,1,2];
var arr2 = [3,4,5];
[arr1,...arr2];

question2:
如果去掉高度已知,哪个布局不再适用:
float position 网格

16、前端性能优化

https://www.cnblogs.com/liulilin/p/7245125.html

应用:

页面布局小结:
1.语义化掌握到位
2.页面布局理解深刻
3.css基础知识扎实
4.第思维灵活 积极上进
5.代码书写规范

17、深拷贝

http://blog.csdn.net/sysuzhyupeng/article/details/70340598

  • 解构赋值

2.CSS盒模型
2.1基本概念:标准模型+IE模型
2.2标准模型和IE模型的区别

18、前端安全

http://blog.csdn.net/fengyinchao/article/details/52303118

http://www.cnblogs.com/vajoy/p/4176908.html

图片 9

19、类数组

具有length属性,其他属性为非负整数,不具备数组所具有的方法

类数组:arguments,以及DOM操作返回的结果

const [first, ...rest] = [1,2,3,4,5];
first //1
rest //[2,3,4,5]

image.png

20、for…in..

  • 循环计数器是字符串,不是数字
  • 会遍历原型上的方法和属性,不适合遍历数组

*将字符串转换成真正的数组

标准模型是content的width height
IE模型是 border+padding+content

21、forEach

forEach 无法使用return终止

[...'hello']
//['h','e','l','l','o']

2.3CSS如何设置这两种模型
通过设置box-sizing:content-box;(标准,浏览器默认)
box-sizing:border-box; (IE)
来区分两种模型

22、HTML5 新特性

http://blog.csdn.net/gane\_cheng/article/details/52819118

注意:扩展运算符也只能放在最后一位,否则报错
5.当new Foo()时发生了什么

2.4JS如何获取盒模型对应的宽和高

23、IE盒子和W3C盒子

IE5.5以下:width = content + padding + border

W3C: width = content

避免IE盒子的方法:头部加上 <!DOCTYPE html>

  • 创建了一个新对象
  • 将this指向这个新对象
  • 执行构造函数里面的代码
  • 返回新对象(this)
    6.你做过哪些性能优化
  • 网页内容
    1.减少http请求(通过 合并图片,合并CSS和JS文件)
    2.减少DNS的查询(DNS预解析)
    3.使用CDN
  • CSS
    1.将样式表置顶
    2.少用@import
  • js
    1.使用外部js和css(因为可以被缓存)
    2.减少dom操作
    7..前端路由的原理
    什么是路由?
    简单的说,路由是根据不同的 url 地址展示不同的内容或页面
    原理:在 HTML5 的 history API 出现之前,前端的路由都是通过 hash
    来实现的,hash 能兼容低版本的浏览器。
  • HTML5 History
    两个新增的API: history.pushState 和 history.replaceState,两个 API
    都会操作浏览器的历史记录,而不会引起页面的刷新。
  • Hash
    就是url 中看到 # ,我们需要一个根据监听哈希变化触发的事件(
    hashchange) 事件。我们用 window.location
    处理哈希的改变时不会重新渲染页面,而是当作新页面加到历史记录中,这样我们跳转页面就可以在
    hashchange 事件中注册 ajax 从而改变页面内容。
    8.call,apply和bind的区别
    它们在功能上是没有区别的,都是改变this的指向,它们的区别主要是在于方法的实现形式和参数传递上的不同
    ①:函数.call(对象,arg1,arg2….)
    ②:函数.apply(对象,[arg1,arg2,…])
    ③:var ss=函数.bind(对象,arg1,arg2,….)
    我们通过代码来更加明显的区别一下:
  1. dom.style.width/height (只能取到内联样式)
  2. dom.currentSytle.width/height
    这个是等到浏览器渲染后,再去取当前dom节点的宽和高,这个是比较准确的,但是有一个缺点,现在只有IE支持。
    3.window.getComputedStyle(dom).width/height
    原理相似,只是这个兼容性更好
    4.dom.getBoundingClientRect().width/height
    同2,3 计算一个元素的绝对位置 能拿到4个 left top width height

24、实现斐波那契序列

// 递归,时间复杂度O(2^n),空间复杂度O(n)
function fib (n) {
    if (n == 1 || n == 2) {
        return 1;
    }

    return fib(n - 1) + fib(n - 2);
}

// 非递归,时间复杂度O(n),空间复杂度O(n)
function fib (n) {
    var ret = [1, 1];
    if (n == 1 || n == 2) {
        return 1;
    }
    for (var i = 2; i < n; i++) {
        ret[i] = ret[i - 1] + ret[i - 2];
    }

    return ret[n - 1];
}

// 非递归,时间复杂度O(n),空间复杂度O(1)
function fib (n) {
    var res, a, b;
    a = b = 1;
    if (n == 1 || n == 2) {
        return 1;
    }
    for (var i = 3; i <= n; i++) {
        res = a + b;
        a = b;
        b = res;
    }

    return res;
}

2.5实例题 根据盒模型解释边距重叠

25、盒子模型的折叠问题

http://blog.csdn.net/zerlinda\_c/article/details/50054639

margin塌陷:http://www.cnblogs.com/hugejinfan/p/5901320.html

水平方向不会坍塌

 function show(sex){  
            console.log("普通函数"+sex);  
        }  
        var person={  
            name:"aa",  
            age:14  
        };  
        show.call(person,"男");  
        show.apply(person,["女"]);  
        //对于bind来说,用法更加的灵活  
        var ss=show.bind(person,"不明");  
        ss();  

图片 10

26、块级元素和行级元素

http://www.cnblogs.com/asqq/archive/2012/10/04/3194956.html

通过观察上面的代码,很明显的就可以得出它们三者的区别,仅仅是函数传递的不同以及bind方法可以更加的方便的使用

image.png

27、Less特性

http://blog.csdn.net/u014695532/article/details/50957356

9.闭包的应用
闭包+函数重写

100px 为子元素的高度
问父模型的高度
父模型的高度是100px 还是110px?
这个还是要看父模型的盒模型

28、git 命令

http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html

function foo() {  
     var context=1;
     console.log(context);
     context=2;
      foo = function() {
        console.log(context);
     }
}

foo();
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            html *{
                padding: 0;
                margin: 0;
            }
        </style>
    </head>
    <body>
        <section id="sec">
            <style media="screen">
                #sec{
                    background-color: #0000FF;
                }
                .child{
                    height: 100px;
                    margin-top: 10px;
                    background: yellow;
                }
            </style>
            <article class="child"></article>
        </section>
    </body>
</html>

30、面经回答

http://blog.csdn.net/bossmango/article/details/77369805

https://segmentfault.com/a/1190000008644536

第一次打印1,之后都打印2

这种情况父元素的height为100px;
如果在#sec中加了overflow:hidden;
父元素的height变成了110px;

31、行内元素设置行高

display或者float

// 判断element是否匹配选择器selector
function matchSelector(element, selector) {
    var match = 
        document.documentElement.webkitMatchesSelector || 
        document.documentElement.mozMatchesSelector || 
        document.documentElement.msMatchesSelector ||
        // 兼容IE8及以下浏览器
        function(selector, element) {
            // 这是一个好方法,可惜IE8连indexOf都不支持
            // return Array.prototype.indexOf.call(document.querySelectorAll(selector), this) !== -1;

            if (element.tagName === selector.toUpperCase()) return true;

            var elements = document.querySelectorAll(selector),
            length = elements.length;

            while (length--) {
            if (elements[length] === this) return true;
            }

            return false;
        };

    // 重写函数自身,使用闭包keep住match函数,不用每次都判断兼容
    matchSelector = function(element, selector) {
        return match.call(element, selector);
    };

    return matchSelector(element, selector);
}

BFC的概念 块级格式化上下文
IFC 内联元素的格式化上下文(问的比较少)

32、requireJS 解决循环依赖

http://www.cnblogs.com/terrylin/p/3347073.html

BFC的原理就是BFC渲染规则:
1.在BFC这个元素的垂直方向的边距会发生重叠
2.BFC的这个区域不会与浮动元素的box重叠 (这个是用来清除浮动 和布局的)
3.BFC在页面上是个独立的容器,里面的不会影响外面,外面的不会影响里面。
4.计算BFC元素高度时,浮动元素也会参与计算

33、实现垂直居中

http://blog.csdn.net/wolinxuebin/article/details/7615098

  • 行内文字:line-height
  • display:table-cell;vertical-align:middle;
  • position和margin(负数)
  • position和stretch
  • 设置相同padding-top和padding-bottom
  • display:flex;aling-items:center;

如何创建BFC:
overflow:hidden
1.float值不为none 设置浮动–>创建BFC
2.position值不为position: relative或者position: static;
–>就为创建了BFC
3.display为

34、伪类和伪元素

http://www.cnblogs.com/ihardcoder/p/5294927.html

display: table;
display: table-caption;
display: inline-table;

35、AMD 和 CMD的区别

http://blog.csdn.net/jackwen110200/article/details/52105493

或者table-其他的 都为创建了BFC
4.只要不是overflow:visible;其他的都视为创建了BFC

36、event loop

http://www.ruanyifeng.com/blog/2014/10/event-loop.html

2.6BFC(边距重叠解决方案)
BFC使用场景:
在这里,因为父元素是BFC:overflow:hidden,所以在BFC这个元素的垂直方向的边距会发生重叠。如何解决?

37、DOCTYPE

<!DOCTYPE> 声明不是 HTML 标签;它是指示 web 浏览器关于页面使用哪个
HTML 版本进行编写的指令

<!--BFC垂直方向边距重叠问题-->
        <section id="margin">
            <style>
                #margin{
                    background-color: pink;
                    overflow: hidden;
                }
                #margin>p{
                    margin: 5px auto 25px;
                    background-color: red;
                }
            </style>
            <p>1</p>
            <div style="overflow: hidden;"><p>2</p></div>
            <p>3</p>
        </section>

38、强缓存和协商缓存

浏览器的协商缓存与强缓存

这里给p元素加一个父盒子,然后在父盒子中加了overflow:hidden
让父元素成为了BFC 可以解决p标签垂直方向边距重叠问题

39、https与http

https比http长3倍的时间

优化:

  • CDN加速,拉进节点
  • 服务器硬件加速,释放CPU
  • 远程解密,使用CPU负载较低的服务器

http://blog.csdn.net/hherima/article/details/52469787

<!--设置BFC   不与float重叠-->
        <section id="layout">
            <style>
                #layout{
                    background-color: green;
                }
                #layout .left{
                    float: left;
                    width: 100px;
                    height: 100px;
                    background-color: palegoldenrod;
                }
                #layout .right{
                    height: 110px;
                    background-color: aqua;
                    overflow: hidden;
                }
            </style>
            <div class="left"></div>
            <div class="right"></div>
        </section>

这里将right div变为BFC float就不会重叠 跑过去 填左边那缺少的10px

<!--BFC 子元素即使是float  也会参与高度计算-->
        <section id="float">
            <style media="screen">
                #float{
                    background-color: blue;
                    /*float: left;*/
                    overflow: auto;
                }
                #float .float{
                    float: left;
                    font-size: 30px;
                }
            </style>
            <div class="float">我是浮动元素</div>
        </section>

让子元素为BFC的时候,父元素的高度不再为0px,会加上子元素的高度。

3.DOM事件

图片 11

image.png

基本概念:DOM事件的级别

图片 12

image.png

false用于判断捕获还是冒泡

dom1 没有跟事件相关的 所以这里跳过dom1

dom3增加了很多事件,比如:鼠标事件 键盘事件

DOM事件模型 (捕获+冒泡)
DOM事件流

图片 13

image.png

大白话来解释事件流:浏览器在当前这个页面,也用户做交互的时候,比如说,我点击了鼠标左键,这个左键传递到你的页面上。这就是个事件流。
一个完整的事件流分3个阶段:
1.捕获
2.目标阶段 比如我点了个按钮,这个按钮就是目标阶段
事件通过捕获,到达目标元素,这个就是目标阶段。
3.从目标元素上传到window对象,这就是冒泡

捕获—->目标元素—(上传到window 事件)—>冒泡

描述DMO事件捕获的具体流程

捕获 就是从上–>下

图片 14

image.png

冒泡的流程 刚好完全相反

如何获取html? 很简单 document.documentelement

Event对象的常见应用

1.捕获跟冒泡的事件流程
2.怎么去注册事件 监听用户的交互行为
3.响应的时候

图片 15

image.png

event.preventDefault()
作用:阻止默认事件

event.stopPropagation()
作用:阻止冒泡

event.stopImmediatePropagation()
作用:事件响应优先级
比如有2个事件,a和b,如果在a里面添加了这个,那么响应的时候,就会执行a不执行b;

<!DOCTYPE html>
<html>
    <head lang="en">
        <meta charset="utf-8" />
        <style>
            p { height: 30px; width: 150px; background-color: #ccf; }
            div {height: 30px; width: 150px; background-color: #cfc; }
        </style>
    </head>
    <body>
        <div>
            <p>paragraph</p>
        </div>
        <script>
            document.querySelector("p").addEventListener("click", function(event)
            {
                alert("我是p元素上被绑定的第一个监听函数");
            }, false);
            document.querySelector("p").addEventListener("click", function(event)
            {
                alert("我是p元素上被绑定的第二个监听函数");
                event.stopImmediatePropagation();
                //执行stopImmediatePropagation方法,阻止click事件冒泡,并且阻止p元素上绑定的其他click事件的事件监听函数的执行.
            }, false);
            document.querySelector("p").addEventListener("click", function(event)
            {
                alert("我是p元素上被绑定的第三个监听函数");
                //该监听函数排在上个函数后面,该函数不会被执行.
            }, false);
            document.querySelector("div").addEventListener("click", function(event)
            {
                alert("我是div元素,我是p元素的上层元素");
                //p元素的click事件没有向上冒泡,该函数不会被执行.
            }, false);
        </script>
    </body>
</html>

很多时候面试的时候会问一个问题:
用for循环给很多li加上点击事件,如何优化这种情况?
这个时候,可以回答使用事件代理,给li的父元素加上一个点击事件,然后当它的子元素得到点击的时候,再去寻找相应的子元素。
如何找到相应的子元素?event.target
事件代理 —> targe 当前被点击
currentTarget当前被绑定的事件 也就是那个父元素

这篇文章写的比较详细:
https://www.cnblogs.com/liugang-vip/p/5616484.html

自定义事件

图片 16

image.png

customEvent和event都是自定义事件,区别在于:customEvent可以加参数

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <div id="ev"></div>
        <script type="text/javascript">
            var ev=document.getElementById('ev');
            var eve = new Event('custome');
            //custom事件的func--->打印出cutsome
            ev.addEventListener('custome', function() {
                console.log('custome');
            })
            //触发
            ev.dispatchEvent(eve);
        </script>
    </body>

</html>

模拟捕获过程:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <div id="ev">
            <style>
                #ev{
                    width:300px;
                    height: 100px;
                    background-color: red;
                    color: white;
                    text-align: center;
                    line-height: 100px;
                }
            </style>
            鼠标元素
        </div>
        <script type="text/javascript">
            var ev=document.getElementById('ev');

            window.addEventListener('click',function(){
                console.log("window captrue")
            },true);
            //默认是false,当为true的时候说明该事件在捕获阶段触发

            document.addEventListener('click',function(){
                console.log("document captrue")
            },true);

            //html标签
            document.documentElement.addEventListener('click',function(){
                console.log("html captrue")
            },true);

            document.body.addEventListener('click',function(){
                console.log("body captrue")
            },true);

            ev.addEventListener('click',function(){
                console.log("ev captrue")
            },true);
        </script>
    </body>

</html>

图片 17

image.png

冒泡 反之

模拟自定义事件:
在这里模拟customEvent:

//customEvent
            var myEvent=new CustomEvent("userLogin",{
                detail:{
                    username:"zhangjing"
                }
            });

            ev.addEventListener('userLogin',function(e){
                console.log(e.detail.username)
            })

            ev.dispatchEvent(myEvent);

输出结果:

zhangjing

4.HTTP协议

HTTP协议的主要特点

图片 18

image.png

简单快速:因为为http中每一个资源
也就是uri的是固定的,比如一个页面一张图片都是固定的,叫做统一资源符(uri),所以要访问就很轻松快速。

灵活:它在头部有一个数据类型,通过一个http协议可以完成不同的数据类型的传输。

无连接:连接一次就会断掉 不会保存连接

无状态:不能区分2次连接者的身份

HTTP报文的组成部分

图片 19

image.png

请求行包含什么?HTTP方法、页面地址、HTTP协议、版本

图片 20

image.png

请求头包含什么?key value值 告诉服务端
我要的内容需要注意什么格式,协助客户端对服务器的请求

图片 21

image.png

空行:区分请求头跟请求体
请求体:请求的东西

响应实例:
响应行:

图片 22

image.png

响应头:

图片 23

image.png

HTTP方法

图片 24

image.png

POST和GET的区别

图片 25

image.png

get请求在url中传送的参数 一般<2kb
不要拼接太长,太长了服务器会截断,然后http就没法发出去,导致错误。

HTTP状态码

图片 26

image.png

图片 27

image.png

图片 28

image.png

401 一般来说该错误消息表明您首先需要登录(输入有效的用户名和密码)。
如果你刚刚输入这些信息,立刻就看到一个 401
错误,就意味着,无论出于何种原因您的用户名和密码其中之一或两者都无效(输入有误,用户名暂时停用等)

403被禁止 也可表示资源不可用

什么是持久连接

图片 29

image.png

http1.1版本才支持

什么是管线化

图片 30

image.png

->表示没有断开

图片 31

image.png

重点:1.2.3

5.原型链

图片 32

image.png

图片 33

image.png

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>原型链</title>
    </head>
    <body>
        <script type="text/javascript">
//          第一种方式 :字面量
            var o1={name:'o1'};
            var o2=new Object({name:'o2'});

//          第二种方式:通过构造 函数
            var m=function(name){
                this.name=name;
            }
            var o3=new m(o3);

//          第三种方式:object.create
            var p={name:'p'};
            var o4=Object.create(p);
        </script>
    </body>
</html>

输出结果:

图片 34

image.png

图片 35

image.png

注意:
任何一个函数 只要被new了 就可以被称为构造函数
for example:var o2=new M(); -》M是一个构造函数

强调:
函数才有prototype 对象是没有prototype的
只有对象才有proto 函数既是函数 也是对象 js万物皆对象

图片 36

image.png

图片 37

image.png

用constructor去判断o3是谁的实例 比
用instanceof判断更加准确。instanceof会将一整条原型链上的 都判断为true。

图片 38

image.png

//          第三种方式:object.create
            var p={name:'p'};
            //Object.create 创造的o4是通过原型链 来连接的
            var o4=Object.create(p);

            m.prototype.say=function(){
                console.log('say hi');
            }

            var o5=new m();

            //new 背后的工作原理
            var new2=function(func){
                var o=Object.create(func.prototype);
                var k=func.call(o);
                if(typeof k ==='object'){
                    return k
                }else{
                    return o
                }
            }

6.面向对象

图片 39

image

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>面向对象</title>
    </head>
    <body>
        <script type="text/javascript">
            //类的声明
            function Animal(){
                this.name='name';
            }
            //es6中class的声明
            class Animal2{
                //构造函数
                constructor(){
                    this.name=name;
                }
            }

            //实例对象
            console.log(new Animal(),new Animal2());
            //notice:如果没有参数 eg:this.namexxx这一类的话  不需要() 直接new Animal即可

        </script>
    </body>
</html>

输出结果

图片 40

image.png

继承的本质就是原型链

js的继承有几种方式,优缺点?

//借助构造函数实现继承(部分继承)
            function parent1(){
                this.name='parent1';
            }
            parent1.prototype.say=function(){
                this.say='123';
            }
            function child1(){
                //实现继承  将父级元素的this指向子构造函数上去
                parent1.call(this);//apply 皆可  
                this.type='child1';
            }
            console.log(new child1())

它的本质是将父元素的this指向子元素的构造函数上,并没有通过原型链,所以他只能部分继承,child1没有继承say方法。

//借助原型链实现继承
            function parent2(){
                this.name='parent2';
            }
            function child2(){
                this.type='child2';
            }
            child2.prototype=new parent2();

            console.log(new child2());
            console.log(new child2().__proto__);

输出

图片 41

image.png

图片 42

image.png

缺点:
先用代码演示一遍:
首先 我们在父级构造函数中加一个play属性

            function parent2() {
                this.name = 'parent2';
                this.play = [1, 2, 3]
            }

然后new 2个实例对象出来

            var s1 = new child2();
            var s2 = new child2();
            console.log(s1.play, s2.play);
            s1.play.push(4);

这时候我们在console去看一下

图片 43

改变s1的同时 s2也得到了改变 为什么呢?
因为他们俩的
proto”都是new出来的parent2对象,根据原型链,找到play,并且push一个4
,所以所有都会变

图片 44

但是不会改变父构造函数。
如果再加上这句:

s2.play.push(5);

图片 45

image.png

//组合方式
            function parent3(){
                this.name='parent3';
                this.play=[1,2,3];
            }
            function child3(){
                parent3.call(this);
                this.type='child3';
            }
            child3.prototype=new parent3();
            var s3=new child3();
            var s4=new child3();
            s3.play.push(4);console.log(s3.play,s4.play);

优点:结合了构造函数继承和原型链继承的优缺点,比较完美
缺点:new了2次parent3 将parent3实例化了2次 2次的意义不大,浪费资源

//组合继承的优化
            function parent4(){
                this.name='parent4';
                this.play=[1,2,3];
            }
            function child4(){
                parent4.call(this);
                this.type='child4';
            }
            child4.prototype=parent4.prototype;
            var s5=new child4();
            var s6=new child4();
            console.log(s5,s6);

            console.log(s5 instanceof child4,s5 instanceof parent4);
            console.log(s5.constructor,child4.constructor); 

优点:解决了上一个问题 不再new2次
缺点:他们的constructor指向的同一个构造函数,无法区分是又子类创建的还是由父类创建的

//组合继承优化2
            function parent5(){
                this.name='parent5';
                this.play=[1,2,3];
            }
            function child5(){
                parent5.call(this);
                this.type='child5';
            }
            child5.prototype=Object.create(parent5.prototype);
            //观察__.proto__,以下为优化步骤
            child5.prototype.constructor=child5;
            var s7=new child5();
            console.log(s7 instanceof child5,s7 instanceof parent5);
            console.log(s7.constructor);

输出:
在执行优化步骤之前:

图片 46

image.png

执行之后:

图片 47

image.png

完美解决。

Q4:typeof 和 instanceof 区别。
A:
typeof
的返回值为‘number’,‘string’,’boolean’,’function’,’undefined’,’object’。所以在判断数组时,返回值为
‘object’;
instanceof 是判断变量是否为某个对象的实例,返回值布尔值。

7.通信 跨域+普通前后端

图片 48

image.png

图片 49

image.png

IndexDB利用数据键(key)访问,通过索引功能搜索数据,适用于大量的结构化数据,如日历,通讯簿或者记事本。

一个源包含什么?协议+域名+端口(默认端口:80)
这3个当中 如果有一个不一样,那就是跨域通信

不是同一个源的文档 无法去操作另一个源的文档或者资源

这里的限制有这么几个:

图片 50

image.png

图片 51

image.png

图片 52

image.png

1.ajax是同源下面的通信
2.websocket 是没有限制的 就是不受同源限制
3.cors 支持跨域,支持同源

图片 53

image.png

XMLHttpRequest只有高级浏览器才支持 IE是不支持的 所以要考虑兼容性的处理

手写ajax,第一版本:

function ajax(url, fnSucc, fnFaild) {
                //1.创建Ajax对象
                if(window.XMLHttpRequest) { //该判断是为了兼容ie6
                    var oAjax = new XMLHttpRequest();
                } else {

                    var oAjax = new ActiveXObject("Microsoft.XMLHTTP");
                };

                //2.连接服务器
                //open(方法,文件名,异步传输)
                //'a.txt?t='+new Date().getTime()可以组织缓存
                oAjax.open('GET', url, true);

                //3.发送请求
                oAjax.send();

                //4.接收返回
                oAjax.onreadystatechange = function() {
                    //                          oAjax.readyState  //服务器和浏览器,进去到哪一步了
                    if(oAjax.readyState == 4) {
                        if(oAjax.status == 200) {
                            fnSucc(oAjax.responseText);
                        } else {
                            if(fnFaild) {
                                fnFaild(oAjax.status);
                            }
                        }

                    }
                }
            }

readyState的5个状态码:
0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了
版本二,详细版本:

if(opt.url){
                var xhr=XMLHttpRequest?new XMLHttpRequest():new window.ActiveXObject('Microsoft.XMLHTTP');
                var data=opt.data,
                      url=opt.url;
                      type=opt.type.toUpperCase(),
                      dataArr=[];
                for(var k in data){
                    dataArr.push(k+'='+data[k]);
                }
                if(type==='GET'){
                    url=url+'?'+dataArr.join('&');
                    xhr.open(type,url.replace(/\?$/g,''),true);
                    xhr.send();
                }
                if(type==='POST'){
                    xhr.open(type,url,true);
                    xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
                    xhr.send(dataArr.join('&'));
                }
                xhr.onload=function(){
                    //206  适用于媒体资源  可以再加一个xhr.status===206
                    if(xhr.status===200||xhr.status===304){
                        var res;
                        if(opt.success&&opt.success instanceof Function){
                            res=xhr.responseText;
                            if(typeof res==='string'){
                                res=JSON.parse(res);
                                opt.success.call(xhr,res);
                            }
                        }
                    }else{
                        if(opt.error && opt.error instanceof Function){
                            opt.error.call(xhr,res);
                        }
                    }
                }   
            }

框架下 如何使用ajax
1.jquery

$.ajax({
  type: 'POST',
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

2.mui下的

mui.ajax('http://server-name/login.php',{
    data:{
        username:'username',
        password:'password'
    },
    dataType:'json',//服务器返回json格式数据
    type:'post',//HTTP请求类型
    timeout:10000,//超时时间设置为10秒;
    headers:{'Content-Type':'application/json'},                  
    success:function(data){
        //服务器返回响应,根据响应结果,分析是否登录成功;
        ...
    },
    error:function(xhr,type,errorThrown){
        //异常处理;
        console.log(type);
    }
});

图片 54

image.png

jsonp应该接触的都比较多了

很简单,就是利用<script>标签没有跨域限制的“漏洞”(历史遗迹啊)来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个<script>元素,地址指向第三方的API网址,形如:
<script
src=”;
并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。
第三方产生的响应为json数据的包装(故称之为jsonp,即json
padding),形如: callback({“name”:”hax”,”gender”:”Male”})
这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。
补充:“历史遗迹”的意思就是,如果在今天重新设计的话,也许就不会允许这样简单的跨域了嘿,比如可能像XHR一样按照CORS规范要求服务器发送特定的http头。

hash是什么?就是你url地址中#后面的东西 hash的变动页面不会刷新
这就是用hash做页面快通讯的一个原理 hash改变 页面不刷新

search是url中?后面的东西,search改变,页面是会刷新的 search不能做快通讯

postMessage H5中新增的处理快通讯

websocket 不收同源限制

CORS支持跨域通讯的ajax
大白话来理解就是:浏览器在识别你发送了一个ajax的跨域请求的时候,它会在你的http头中加一个origin来允许跨域通信。这就是cors,如果是普通的ajax的话,如果要跨域请求的时候,浏览器就会把你拦截了。

jsonp的原理是什么?

<!--jsonp的原理  就是利用了 script标签的异步加载来完成的-->
        <!--你发出请求,并且要告诉服务端,你的callback的名称,然后它是以一个函数名的形式返回,
            既然要以函数名的形式返回,那是不是应该去创建一个jsonp的函数?
            所以你本地必须要有一个jsonp的函数,才能把那些东西执行出来-->
        <script src="http://www.abc.com/?data=name&callback=jsonp"></script>
        <script>
            jsonp({
                data:{

                }
            })
        </script>

这里data=name 这一块可要可不要 主要是要把callback=jsonp
然后jsonp是个本地的全局函数 执行了script的时候就会去找jsonp这一块。

var util = {};

            //在页面中注入js脚本
            util.createScript = function(url, charset) {
                var script = document.createElement('script');
                script.setAttribute('type', 'text/javascript');
                charset && script.setAttribute('charset', charset);
                script.setAttribute('src', url);
                //script标签异步执行
                script.async = true;
                return script;
            }

            util.jsonp = function(url, onsuccess, onerror, charset) {
                //告诉它回调名称
                var callbackName = util.getName('tt_player');
                //在全局注册这么个回调函数
                window[callbackName] = function() {
                    if(onsuccess && util.isFunction(onsuccess)) {
                        onsuccess(arguments);
                    }
                }
                //动态创建script标签
                var script = util.createScript(url + '&callback=' + callbackName, charset);
                //script加载
                script.onload = script.onreadystatechange = function() {
                    if(!script.readyState || /loaded|complete/.test(script.readyState)) {
                        script.onload = script.onreadystatechange = null;
                        // 移除该script的 DOM 对象
                        if(script.parentNode) {
                            script.parentNode.removeChild(script);
                        }
                        // 删除函数或变量
                        window[callbackName] = null;
                    }
                };
                script.onerror = function() {
                    if(onerror && util.isFunction(onerror)) {
                        onerror();
                    }
                };
                //向html中增加这个标签
                document.getElementsByTagName('head')[0].appendChild(script);
            }

使用jsonp的例子:

$.ajax({
            type: "get",
            async: false,
            url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
            dataType: "jsonp",
            jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
            jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
            success: function(json){
                alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
            },
            error: function(){
                alert('fail');
            }
        });

这里针对ajax与jsonp的异同再做一些补充说明:

1、ajax和jsonp这两种技术在调用方式上”看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装。

2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加
Hash:

 // 利用hash,场景是当前页面 A 通过iframe或frame嵌入了跨域的页面 B
      // 在A中伪代码如下:
      var B = document.getElementsByTagName('iframe');
      B.src = B.src + '#' + 'data';
      // 在B中的伪代码如下
   //当hash变化的时候
      window.onhashchange = function () {
          var data = window.location.hash;
      };

postMessage:

// postMessage
      // 窗口A(http:A.com)向跨域的窗口B(http:B.com)发送信息
      Bwindow.postMessage('data', 'http://B.com');
// 这里的data一般是string字符串, 'http://B.com'是源,也可以用*,*代表任意的都可以,但是不安全,不建议使用
      // 在窗口B中监听
      Awindow.addEventListener('message', function (event) {
          console.log(event.origin);
          console.log(event.source);
          console.log(event.data);
      }, false);

websocket:

 // Websocket【参考资料】http://www.ruanyifeng.com/blog/2017/05/websocket.html

      var ws = new WebSocket('wss://echo.websocket.org');
      //wss 用于加密
      ws.onopen = function (evt) {
          console.log('Connection open ...');
          ws.send('Hello WebSockets!');
      };

      ws.onmessage = function (evt) {
          console.log('Received Message: ', evt.data);
          ws.close();
      };

      ws.onclose = function (evt) {
          console.log('Connection closed.');
      };

CORS:

// CORS【参考资料】http://www.ruanyifeng.com/blog/2016/04/cors.html
      // url(必选),options(可选)
      fetch('/some/url/', {
          method: 'get',
      }).then(function (response) {

      }).catch(function (err) {
        // 出错了,等价于 then 的第二个参数,但这样更好用更直观
      });

8.安全 xss

图片 55

image.png

图片 56

image.png

图片 57

image.png

图片 58

image.png

用户–登录—>网站A 然后 网站A—下发cookie—>用户
这个过程就是一个网站登录验证的过程

这个用户必须要登录过
会产生csrf:
1.网站中某个接口有问题
2.用户在该网站登录过

图片 59

image.png

token验证:
比如:用户要去访问一个网站,然后服务器那边会自动给出一个token,这时候就不止是cookie还有token,如果想上一个环节那样,引诱用户去点一个链接,这个链接只会自动携带cookie而不会携带token,就避免了那个攻击。

referer验证:referer指的就是页面来源,服务器可以判断来的这个页面是不是我的站点下的页面,如果是,我就执行你的这个动作,如果不是,一律拦截,这样也可以避免攻击。

隐藏令牌:类似token,只是它放的比较隐蔽,比如说我隐藏在http
head头中,而不会放在链接上,这样比较隐蔽。

图片 60

image.png

图片 61

image.png

攻击原理:就是注入js脚本,找各种合法路径,然后给你注入js脚本。
防御措施:就是让xss不执行。

xss跟crfs的区别:
xss是向你的页面注入js脚本运行,在js函数体里面去做它想做的事情。
crfs是利用你本身漏洞,帮你去执行那些接口,且依赖于用户必须要登录注册该网站。

9.算法

图片 62

image.png

堆栈 先进后出 队列 先进先出

图片 63

image.png

图片 64

image.png

图片 65

image.png

图片 66

image.png

图片 67

image.png

发表评论

电子邮件地址不会被公开。 必填项已用*标注