Giter VIP home page Giter VIP logo

blog's People

Contributors

gayechen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

blog's Issues

面试题系列-Webpack问题

webpack配置文件基本概念

  • entry
  • output
  • loaders: 编译转换文件
  • plugins: 扩展webpack功能,在构建流程里注入钩子函数
  • module:Webpack中一切皆模块,一个模块即一个文件。Webpack会从entry开始递归找出所有依赖的模块。
  • Chunk:代码块,一个Chunk由多个模块组合而成,用于代码合并和分割。
    一个Chunk,就是一个entry及其所有依赖的Module合并的结果,
  • DevServer:提供http服务,监听文件变化并实时刷新页面、支持source-map方便调试

webpack构建流程

  • Webpack在启动后,会从Entry开始,递归解析Entry依赖的所有Module,每找到一个Module,就会根据Module.rules里配置的Loader规则进行相应的转换处理,对Module进行转换后,再解析出当前Module依赖的Module,这些Module会以Entry为单位进行分组,即为一个Chunk。因此一个Chunk,就是一个Entry及其所有依赖的Module合并的结果。最后Webpack会将所有的Chunk转换成文件输出Output。在整个构建流程中,Webpack会在恰当的时机执行Plugin里定义的逻辑,从而完成Plugin插件的优化任务。

前端模块化的理解

打包很慢,怎么解决

  • DllPlugin

打包出来的文件很大,怎么解决?

  • 指定环境为‘production’
    new Webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify('production'),
     }), 
    
  • 关闭source-map: devtool选项设置为false
  • 提取样式到公共的css文件:ExtractTextPlugin
  • 压缩JS文件:UglifyJSPlugin
  • 提取公共依赖库:CommonsThunkPlugin
  • 压缩CSS,图片资源
  • 开启gzip压缩:compression-webpack-plugin
  • 开启html压缩,自动添加上面生成的静态资源
    new HtmlWebpackPlugin({
          title: '',
             template: __dirname + '/../public/index.html',
             minify: {
                 removeComments: true,
                 collapseWhitespace: true,
                 removeRedundantAttributes: true,
                 useShortDoctype: true,
                 removeEmptyAttributes: true,
                 removeStyleLinkTypeAttributes: true,
                 keepClosingSlash: true,
                 minifyJS: true,
                 minifyCSS: true,
                 minifyURLs: true,
             },
             chunksSortMode:'dependency'
         }),
    

loader,自己如何写一个loader

babel原理

plugin,自己如何写一个plugin

webpack原理之普通打包

webpack原理之多文件打包

webpack原理之提取公共文件

webpack如何做到tree shaking

面试题系列-Http问题

协商缓存与强缓存

  • 强制缓存直接从缓存中获取资源而不需要请求服务器
    • expires
    • cache-control:
      • 300
      • no-cache:不使用强缓存。需要使用协商缓存
      • no-store:禁止浏览器缓存资源,所以包括协商缓存也不能使用
  • 协商缓存需要和服务器协商,如果命中,状态码返回304
    • Last-Modified/ If-Modefied-Since
    • Etag/If-None-Match
  • 既生Last-Modified何生Etag
    • 文件周期性更改,但是内容却不更改,修改时间会变化
    • 文件修改过于频繁,在s级以下,If-Modified-Since能检查到的粒度是s级的
    • 某些服务器不能精确地得到Last-Modified

为什么传统上利用多个域名来提供网站资源会更有效

  • CDN更方便:静态内容和动态内容分服务器存放,使用不同服务器处理请求,处理动态内容的只处理动态内容,不处理别的,提高效率,这样使得CDN(内容分发网络)缓存更方便
  • 突破浏览器并发限制
  • 跨域不会传cookie,节省带宽

Long-Polling、Websockets和Server-Sent Event

常见的请求头和响应头

和缓存有关的HTTP首部字段,如何应用的?

  • expires
  • catch-control
  • Last-Modified/If-Modified-Since
  • Etag/If-None-Match

Http method

  • GET
  • POST
  • PUT
  • DELETE
  • HEAD与GET类似,但服务器只返回响应首部

HTTP状态码

  • 301:永久重定向
  • 302:临时重定向
  • 304:使用缓存
  • 403:服务器拒绝请求
  • 404:服务器找不到页面
  • 500:服务器内部错误
  • 502:错误网关

https加密过程

http2新特性

  • 二进制帧
  • 多路复用(Multipexing)
  • 服务端推送(Server Push)
  • 头部压缩

get和post的区别

  • get发送一个TCP数据包,post产生两个TCP数据包

    • 对于get请求,浏览器会把header和data一并发送,服务器响应200(返回资源)
    • 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
  • get向服务请求数据,post向服务器推送数据

  • get将请求参数放在url中,post放在请求体中(request body)

  • get请求参数,因浏览器有长度限制,post参数长度无限制

面试题系列-CSS问题

CSS问题

CSS3新增属性

  • 边框:border-radius、box-shadow、border-image
  • 背景:background-size、background-origin
  • 文字效果:text-shadow、word-wrap、word-break
  • 用户界面:resize、box-sizing、outline-offset
  • 多列:column-gap、column-count、column-rule
  • 转换:transform、transition
    • translate()
    • rotate()
    • scale()
    • skew()
    • matric
  • 动画:animation、animation-name、animation-duration
  • 新增伪类:
    • :nth-child()
    • :nth-last-child()
    • :only-child
    • :last-child
    • :nth-of-type()
    • :only-of-type()
    • :empty
    • :target
    • :enabled
    • :disabled
    • :checked
    • :not

CSS选择器的优先级如何计算?请问在确定样式的过程中优先级是如何决定的 (请举例)?如何有效使用此系统?

  • 权重 👍 !important>行内样式>ID选择器>类选择器>标签>通配符>继承>浏览器默认属性

请问 "resetting" 和 "normalizing" CSS 之间的区别?你会如何选择,为什么

  • 重置(Resetting): 重置意味着除去浏览器的所有默认样式。对于页面所有的元素,像margin、padding、font-size这些样式全部置成一样。你将必须重新定义各种元素的样式。
  • 标准化:没有去掉所有的默认样式,保留了一部分有用的,还纠正了一些常见错误

通常使用标准化就可以了
当需要实现非常个性化的网页设计时,我会选择重置的方式,因为我要写很多自定义的样式以满足设计需求,这时候就不再需要标准化的默认样式了。

请阐述Float定位的工作原理。

  • 浮动元素从网页的正常流动中移出,但保留了部分的流动性,会影响其他元素的定位(比如文字会围绕着浮动元素)。这一点与绝对定位不同,绝对定位的元素完全从文档流脱离
  • 如果浮动元素的父元素只包含浮动元素,那么该父元素的高度会坍塌为0,我们可以通过清除(clear)从浮动元素后到父元素关闭前之间的浮动来修复这个问题(clear: both | left | right)
  • 把浮动元素的父元素属性设置为overflow: auto或overflow: hidden,会使其内部子元素形成BFC,并且父元素会扩张自己,使其能够包围它的子元素

请阐述z-index,并说明如何形成层叠上下文,(stacking context)

  • z-index属性控制元素的层级(重叠元素的垂直叠加顺序),只能作用于position值不为static的元素
  • 未定义z-index时,按照元素在DOM中出现的先后顺序叠加
  • 非静态元素及其子元素将始终覆盖静态(static)定位元素之上
  • 在一组层叠上下文(即包含多个图层的元素),其子元素的z-index值是相对于该父元素而不是根节点元素,
  • 如果元素 B 位于元素 A 之上(兄弟关系),即使元素 A 的子元素 C 具有比元素 B 更高的z-index值,元素 C 仍然在B之下

详情:http://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/

请阐述BFC(Block Formatting Context)及其工作原理

创建BFC的条件(只要元素满足下面任一条件即可触发 BFC)

  • 浮动元素:float不是none,(left | right | inherit)
  • 绝对定位元素:position(absolute,fixed)
  • display 为以下其中之一的值:table-cells、table-caption、inline-block、flex、或inline-flex。
  • overflow不是visible:(hidden,auto,scroll)

作用

有哪些清除浮动的技术,都适用哪些情况?

  • 添加一个空div作为兄弟:<div style="clear: both;"/>
  • Clearfix方法,伪元素选择器::after
.clearfix::after {
   content: '',
   display: block;
   clear: both;
}

  • 父级元素设置overflow:hidden | auto

大型项目中一般使用第二种,当子元素高度大于父元素时,设置overflow:hidden可能使其子元素显示不完整

请解释什么是雪碧图(css sprites),以及如何实现

雪碧图是把多张图片整合到一张图片上。他被运用在众多使用了很小图标的网站上。实现方式:

  • 使用生成器将多张图片打包成一张雪碧图,并为其生成合适的CSS
  • 每张图片都有相应的CSS类,该类定义了background-image、background-position、和background-size属性
  • 使用图片时,将相应的类添加到你的元素中

好处:

  • 减少请求多张图片的HTTP请求数(一张雪碧图只需一个请求)。对于HTTP2而言,加载多张图片不再是问题
  • 提前家在资源,防止在需要时才开始下载引发的问题,比如只出现在:hover伪类中的图片,不会出现闪烁

生成器:https://www.toptal.com/developers/css/sprite-generator

你最喜欢的图片替换方法是什么,你如何选择使用。

如何解决不同通过浏览器样式兼容性问题

  • 使用autoprefixer自动生成css属性前缀
  • 直接兼容不同浏览器的CSS库,如Bootstrap
  • 使用reset CSS 或者normalize.css
  • 在确定问题原因和有问题的浏览器后,使用单独的样式表,仅供出现问题的浏览器加载。这种方法需要使用服务器端渲染。

如何为有功能限制的浏览器提供网页?使用什么样的技术和流程?

  • 优雅降级:为现代浏览器构建应用,同时确保它在旧版本浏览器中正常运行
  • 渐进增强:构建基于用户体验的应用,但在浏览器支持时添加新增功能
  • 利用caniuse.com检查特性支持;
  • 使用Modernizr进行特性检测
  • 使用autoprefixer解决css的兼容性

有哪些的隐藏内容的方法 (如果同时还要保证屏幕阅读器可用呢)?

  • visibility: hidden: 元素仍在页面流中,并占用空间
  • width: 0; height: 0: 使元素不占用空间,导致不显示它
  • position: absolute; left: -99999px: 将它置于屏幕之外
  • text-indent: -9999px: 这是适用于block元素中的文本
  • Metadata:
  • WAI-ARIA:

你使用过栅格系统吗?偏爱哪一个?

  • 使用过antd和bootstrap的栅格系统,看项目需求和使用的库

你是否使用过媒体查询或移动优先的布局?

  • 根据屏幕的尺寸改变导航栏的样式

你熟悉 SVG 样式的书写吗?

如何优化网页的打印样式?

  • 分开屏幕显示与打印的样式

    <link rel="stylesheet" type="text/css" media="screen" href="/css/styles.css" />

    <link rel="stylesheet" type="text/css" media="print" href="/css/print.css" />

  • 设计一份打印样式表
    i. 用点单位(pt)指定大小

body {

  font-family: "Times New Roman", serif;

  font-size: 12pt;

  }

实在太简单了,比起用像素单位来说,这个应该更能想象12点字体会印多大,同时我们也选用serif字体,这种字体打印出来比较细致,而且比较容易阅读.
ii. 隐藏不必要的标签节省墨水

body {

  font-family: "Times New Roman", serif;

  font-size: 12pt;

  }

#nav, #sidebar, #advertising, #search {

  display: none;

  }

iii. 去掉背景图片和颜色

body {

   background: none;

   }

除了screen,你还能说出一个 @media 属性的例子吗?

<style type="text/css">
@import url("screenstyles.css") screen;
 @media print {
     /* 打印时使用的样式放置在此 *
}

在书写高效 CSS 时会有哪些问题需要考虑?

  • 避免使用标签和通用选择器作为关键选择器,因为它们会匹配大量的元素,浏览器必须要进行大量的工作,去判断这些元素的父元素们是否匹配。
  • 原则上建议为独立的样式使用 CSS 类命名,并且在需要层级关系时,将关系也体现在命名中,这自然会使选择器高效且易于覆盖。
  • 搞清楚哪些 CSS 属性会触发重新布局(reflow)、重绘(repaint)和合成(compositing)。在写样式时,避免触发重新布局的可能。

用 CSS 预处理的优缺点分别是什么?请描述你曾经使用过的 CSS 预处理器的优缺点。

优点:

  • 提高CSS可维护性
  • 易于编写嵌套选择器
  • 引入变量,增加主题功能,可在不同项目**享主题文件
    缺点:
  • 需要预处理工具
  • 重新编译的时间可能会很慢

sass的优缺点
通过node-sass使用sass,它用 C ++ 编写的 LibSass 绑定,在Node版本切换时,必须重新编译
less用javascript编写,与NodeJS高度结合

如果设计中使用了非标准的字体,你该如何去实现?

  • 使用@font-face并为不同的font-weight定义font-family

请解释浏览器是如何判断元素是否匹配某个CSS选择器

  • 浏览器从最右边的选择器(关键选择器)开始,从 DOM 中筛选出元素,然后向上遍历被选元素的父元素,判断是否匹配。选择器匹配语句链越短,浏览器的匹配速度越快。
  • 浏览器先产生一个元素集合,这个集合往往由最后一个部分的索引产生(如果没有索引就是所有的元素集合)。
    然后向上匹配,如果不符合上一个部分,就把元素从集合中删除,知道整个选择器匹配完,还在集合中的元素就匹配这个选择器了

请描述伪元素及其用途。

  • CSS伪元素是添加到选择器的关键字,去选择元素的特定部分。它们可用于装饰(:first-line, :first-letter)或将元素添加到标记中(与content:...)组合,而不必修改标记(:before,:after)

说说你对盒模型的理解,以及如何告知浏览器使用不同的盒模型渲染布局。

请解释 * { box-sizing: border-box; } 的作用, 并且说明使用它有什么好处?

  • 元素默认box-sizing: content-box,元素的宽高width和height只会取决于内容(content)的大小
  • border-box改变计算元素width和height的方式,border和padding的大小也会计算在内

display的属性值有哪些?

  • none, block, inline, inline-block, table, table-row, table-cell, list-item, flex

请解释 inline 和 inline-block 的区别?

block inline-block inline
大小 填充父容器的宽度 取决于内容 取决于内容
定位 从新的一行开始,并且不允许旁观有HTML元素(除非是float) 与其他内容一起流动 与其他内容一起流动
能否设置width和height 不能
能否使用vertical-align对齐 不可以 可以 可以
边距和填充 各个方向都存在 各个方向都存在 只有水平方向存在。尽管border和padding在content周围,垂直方向上的空间取决于line-height

relative、fixed、absolute、和static四种定位有什么区别?

  • static: 默认定位属性值。指定元素使用正常的布局行为,此时给top,right,bottom,left,z-index属性设置值无效
  • relative: 参照物为元素原来所处文档流中的位置
  • absolute: 不为元素预留空间,参照物为该元素最近的非static祖先元素
  • fixed: 不为元素预留空间,参照物为屏幕视口(viewport),即使页面滚动时也不改变
    fixed属性会创建新的层叠上下文,当元素祖先的transform属性非none时,容器由视口改为该祖先
  • sticky:

你使用过哪些现有的 CSS 框架?你是如何改进它们的?

  • Blueprint是比较早的基于静态CSS的框架
  • Bootstrap是基于less的框架。模块化的框架你要修改起来也是很方便的,基本上修改变量就可以了。

你了解 CSS Flexbox 和 Grid 吗?

  • Flexbox 解决了 CSS 中的许多常见问题,例如容器中元素的垂直居中,粘性定位(sticky)的页脚等。
    Bootstrap 和 Bulma 基于 Flexbox,这是创建布局的推荐方式。
  • Grid 创建基于栅格的布局,是迄今为止最直观的方法(最好是!),但目前浏览器支持并不广泛。

为什么响应式设计 (responsive design) 和自适应设计 (adaptive design) 不同?

你有没有使用过视网膜分辨率的图形?当中使用什么技术?

— 使用更高分辨率的图形(显示尺寸的两倍)来处理视网膜显示。
更好的方法是使用媒体查询,像@media only screen and (min-device-pixel-ratio: 2) { ... },然后改变background-image。

  • 对于图标类的图形,可能使用 svg 和图标字体,因为它们在任何分辨率下,都能被渲染得十分清晰。
  • 响应式图片。通过设置img标签的srcset, sizes属性

什么情况下,用translate()而不用绝对定位?什么时候,情况相反,

  • 使用绝对定位、相对定位属性加上 top、left ,会影响offsetTop和 offsetLeft (元素相对于父级参照物的偏移距离)的值;使用translate(),offsetTop和 offsetLeft 的值都是固定不变的。

如果实现一个高性能的CSS动画效果?

CSS3动画

  • transition动画
  • 帧动画,用animate属性

哪些方式实现垂直居中和水平居中

实现圣杯布局,双飞翼布局

  • 双飞翼是通过中间box新建子元素并设置外边距隔离各列
    圣杯布局是通过设置父容器的内边距来隔离各列

面试题系列——怪异/趣味问题

实现lazyman
一道被人轻视的JS面试题
获取元素最终的backgroundColor

实现lazyman

(function(window, undefined) {
    var taskQueue = [];

    // 订阅
    function subscribe() {
        var params = {},
            args = [].slice.call(arguments);
        if (args.length < 1) {
            throw new Error('subscribe 参数不能为空');
        }
        params.msg = args[0];
        params.args = args.slice(1);

        if (params.msg == 'sleepFirst') {
            taskQueue.unshift(params);
        } else {
            taskQueue.push(params);
        }
    }

    // 发布
    function publish() {
        if (taskQueue.length > 0) {
            run(taskQueue.shift());
        }
    }

    function LazyMan() { }

    LazyMan.prototype.eat = function (str) {
        subscribe('eat', str);
        return this;
    };

    LazyMan.prototype.sleep = function (num) {
        subscribe('sleep', num);
        return this;
    };

    LazyMan.prototype.sleepFirst = function (num) {
        subscribe('sleepFirst', num);
        return this;
    };

    // 暴露接口
    window.LazyMan = function (str) {
        subscribe('lazyMan', str);

        setTimeout(function () {
            publish();
        }, 0);

        return new LazyMan();
    };


    function lazyManLog(str) {
        // console.log(str);
        alert(str);
    }

    // 具体方法
    function lazyMan(str) {
        lazyManLog('Hi!This is ' + str + '!');

        publish();
    }

    function eat(str) {
        lazyManLog('Eat ' + str + '~');
        publish();
    }

    function sleep(num) {
        setTimeout(function () {
            lazyManLog('Wake up after ' + num);

            publish();
        }, num * 1000);
    }

    function sleepFirst(num) {
        setTimeout(function () {
            lazyManLog('Wake up after ' + num);

            publish();
        }, num * 1000);
    }

    // 鸭子叫
    function run(option) {
        var msg = option.msg,
            args = option.args;

        switch (msg) {
            case 'lazyMan':
                lazyMan.apply(null, args);
                break;
            case 'eat':
                eat.apply(null, args);
                break;
            case 'sleep':
                sleep.apply(null, args);
                break;
            case 'sleepFirst':
                sleepFirst.apply(null, args);
                break;
            default:
        }
    }
})(window);

一道被人轻视的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();

获取元素最终的backgroundColor

(function(WDS, undefined) {
    function camelize(params) {
        return str.replace(/-(\w)/g, function(strMatch, p1) {
            return p1.toUpperCase();
        });
    }

    function getStyle(ele, property) {
        if (!ele || !property) {
            return false;
        }
        var value = ele.style[camelize(property)],
            css;

        if (!value) {
            if (document.defaultView && document.defaultView.getComputedStyle) {
                css = document.defaultView.getComputedStyle(ele, null);
                value = css ? css.getPropertyValue(property) : null;
            }
        }
        return value;
    }

    function checkBgValue(ele) {
        var value = getSyle(ele, 'background-color'),
            hasColor = value ? true : false;
        if (value == 'transparent' || value == 'rgba(0, 0, 0, 0)') {
            // 未设置background-color,或者设置为跟随父节点
            hasColor = false;
        } else if (getSyle(ele, 'opacity') == '0') {
            // dom节点透明度为全透明
            hasColor = fasle;
        } else if (getStyle(ele, 'visibility') == 'hidden') {
            // dom节点不可见
            hasColor = false;
        } else if (getStyle(ele, 'display' == 'none')) {
            hasColor = false;
        }
        return hasColor ? value : hasColor;
    }

    function getRealBg(ele) {
        if (checkBgValue(ele)) {
            return checkBgValue(ele);
        } else if (ele != document.documentElement) {
            return getRealBg(ele.parentNode);
        }
        return ''
    }
})(window.WDS || (window.WDS = {}));

面试题系列-算法问题

常见排序算法:冒泡,快排,插入排序

实现二分搜索法:递归和非递归

数组去重

树的遍历

面试题系列-HTML问题

doctype的作用是什么

浏览器标准模式 (standards mode) 、准标准模式(almost standards mode)和混杂(怪异)模式 (quirks mode) 之间的区别是什么?

  • 怪异模式:不同的浏览器在页面的渲染上没有统一的规范,产生了差异,那些网页是按照当时占**地位的浏览器的渲染模式来渲染的,因为不同浏览器解析方式不同,所以称之为怪异模式
  • 标准模式是指,浏览器按照W3C的最新标准解析执行代码
  • 浏览器解析时到底使用标准模式还是怪异模式,与你网页中的DTD声明直接相关,DTD声明定义了标准文档的类型(标准模式解析)文档类型,会使浏览器使用相应的方式加载网页并显示,忽略DTD声明,将使网页
  • 详细https://blog.csdn.net/xujie_0311/article/details/42044277

HTML 和 XHTML 有什么区别?

  • 实际上 W3C 下与网页(超文本)相关的标准有两个系列:HTML 系列和 XHTML 系列。
    前者从 HTML 第一版一直发展到 HTML 4.x、HTML5,
    而 XHTML 系列从 XHTML 1.0、1.1、2.0 跳跃到 HTML5 的一部分:所谓的“XHTML5”。
    HTML 系列的工作重点在于丰富与超文本相关的功能、标记,提供较好的兼容性,更加面向“人”;
    而 XHTML 系列的工作重点在于将 HTML 改为更加符合 XML 严格规范的格式,更加面向“机器”。

主要区别

  • XHTML 元素必须被正确地嵌套。
  • XHTML 元素必须被关闭。
  • 标签名必须用小写字母。
  • XHTML 文档必须拥有根元素。

使用 data- 属性的好处是什么?

  • 在JavaScript框架变得流行之前,前端开发者经常使用data-属性,把额外数据存储在 DOM 自身中。当时没有其他 Hack 手段(比如使用非标准属性或 DOM 上额外属性)。
  • 这样做是为了将自定义数据存储到页面或应用中,对此没有其他更适当的属性或元素。
  • 而现在,不鼓励使用data-属性。
    原因之一是,用户可以通过在浏览器中利用检查元素,轻松地修改属性值,借此修改数据。数据模型最好存储在 JavaScript 本身中,并利用框架提供的数据绑定,使之与 DOM 保持更新。

将HTML5看做开放的网络平台,它的基本构成条件是什么

  • 语义-提供更准确的描述内容
  • 连接-提供新的方式与服务器通信
  • 离线和存储-允许网页在本地存储数据并有效地离线运行
  • 多媒体-在Open Web中,视频和音频被视为一等公民
  • 2D/3D图形和特效-提供更多更富有表现力的演示选项
  • 性能和集成-提供更快的访问速度和性能更好的计算机硬件
  • 设备访问-允许使用各种输入、输出设备
  • 外观-可以开发丰富的主题

请描述cookie、sessionStorage和localStorage的却别

上面提到的技术名词,都是在客户端以键值对存储的存储机制,并且只能将值存储为字符串。

  • 后两者都由客户端初始化,cookie也可以有服务器使用set—Cookie请求头初始化
  • cookie手动设置过期时间,session页面关闭时过期,local永不过期
  • Cookies会通过Cookie请求头自动发给服务器,而后两者不会
  • cookie容量为4KB,后两者都是5MB
  • cookie和local任一窗口都可访问,session仅在当前窗口
cookie localStorage sessionStorage
由谁初始化 客户端或服务器,服务器可以使用Set-Cookie请求头。 客户端 客户端
过期时间 手动设置 永不过期 当前页面关闭时
在当前浏览器会话(browser sessions)中是否保持不变 取决于是否设置了过期时间
是否随着每个 HTTP 请求发送给服务器 是,Cookies 会通过Cookie请求头,自动发送给服务器
容量(每个域名) 4kb 5MB 5MB
访问权限 任意窗口 任意窗口 当前页面窗口

<script>、<script async>和<script defer>的区别?

  • script- HTML解析中断,脚本被提取并立即执行。执行解析后,HTML解析继续
  • script async - 脚本的提取、执行与HTML的解析并行,不会阻塞页面继续解析,脚本执行完毕可能在HTML解析完毕之前。
    当脚本与页面上其他脚本独立式,可以使用async
  • script defer- 仅仅是脚本的提取和HTML解析并行,脚本执行将在HTML执行完解析完成后进行。
    如果有多个含defer的脚本,脚本的执行顺序按照在document中出现的位置,从上到下顺序执行。

注意:没有src属性的脚本,async和defer属性会被忽略。

为什么最好把CSS的<link>标签放在<head></head>之间?

为什么最好把JS的<script>标签恰好放在</body>之前,有例外情况吗?

把<link>放在<head>;

  • <link>标签放在<head></head>之间是规范要求的内容
    。此外,这种做法可以让页面逐步呈现,提高了用户体验。
    将样式表放在文档底部附近,会使许多浏览器(包括 Internet Explorer)不能逐步呈现页面。
    一些浏览器会阻止渲染,以避免在页面样式发生变化时,重新绘制页面中的元素。这种做法可以防止呈现给用户空白的页面或没有样式的内容。

<script>标签恰好放在</body>之前

  • 脚本在下载和执行期间会阻止HTML解析,把<script>标签放在底部,保证HTML首先解析完成,将页面呈现给用户。
    同时,将<script>标签放在底部,意味着浏览器不能开始下载脚本,直到整个文档(document)被解析。也许,对此比较好的做法是,<script>使用defer属性,放在<head>

什么是渐进式渲染

  • 渐进式渲染是用于提高网页性能(尤其是提高用户感知的加载速度),以尽快呈现页面的技术
    一些举例:
  • 图片懒加载:——页面上的图片不会一次性全部加载。当用户滚动页面到图片部分时,JavaScript 将加载并显示图像。
  • 确定显示内容的优先级(分层次渲染)——为了尽快将页面呈现给用户,页面只包含基本的最少量的 CSS、脚本和内容,然后可以使用延迟加载脚本或监听DOMContentLoaded/load事件加载其他资源和内容。
  • HTML异步加载: HTML 片段——当页面通过后台渲染时,把 HTML 拆分,通过异步请求,分块发送给浏览器。更多相关细节可以在。
  • 框架中的路由懒加载,代码分离

HMTL5新标签

  • video, audio、source、track、canvas、 svg
  • code、 figure、figcaption
  • time 、mark、datalist
  • keygen、output、progress、menu、menuitem、template
  • 语义化标签:header,footer,main,section,nav,aside,article

为什么在<img>标签中使用srcset属性?请描述浏览器遇到该属性后的处理过程

  • 因为需要设计响应式图片。我们可以使用两个新的属性——srcset 和 sizes——来提供更多额外的资源图像和提示,帮助浏览器选择正确的一个资源。

    srcset 定义了我们允许浏览器选择的图像集,以及每个图像的大小。

    sizes 定义了一组媒体条件(例如屏幕宽度)并且指明当某些媒体条件为真时,什么样的图片尺寸是最佳选择

    所以,有了这些属性,浏览器会

    1. 查看设备宽度
    2. 检查size列表中哪个媒体条件威震
    3. 查看给予该媒体查询的槽大小
    4. 加载srcset列表中引用的最接近所选槽大小的图片
    <img srcset="elva-fairy-320w.jpg 320w,
                 elva-fairy-480w.jpg 480w,
                 elva-fairy-800w.jpg 800w"
         sizes="(max-width: 320px) 280px,
                (max-width: 480px) 440px,
                800px"
         src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
    

你有过使用不同模版语言的经历吗?

  • 有过,比如 Pug (以前叫 Jade)、ejs 等等。
    在我看来,这些模版语言大多是相似的,都提供了用于展示数据的内容替换和过滤器的功能。大部分模版引擎都支持自定义过滤器,以展示自定义格式的内容。

面试题系列-安全问题

xss

  • 跨站脚本攻击: 是代码注入的一种,恶意用户通过将代码注入到网页上(例如论坛或贴吧发布含有恶意的js代码,就是代码注入,如果这个代码内容有请求外部服务器,就叫做xss),其他用户在浏览网页后受到影响。这类攻击通常包含了HTML和用户端脚本语言。

csrf

  • 跨站请求伪造:是一种挟制用户在当前已登录的web应用程序中执行非本意的操作的攻击方法;例如,冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)

Chrome及Webstorm快捷键

  • 必不可少的快捷键📝📝📝

mac系统

快捷键 作用
Ctrl + 关机 关机
⌘ + Option + Esc 强制退出

Chrome

标签页和窗口快捷键

快捷键 作用
⌘ + N 打开新窗口
⌘ + T 打开新标签页
⌘ + O 通过浏览器打开本地文件
⌘ + Shift + N 打开新的无痕窗口
⌘ + Shift + T 重新打开上次关闭的标签页(浏览器可记住最多10个标签)
⌘ + W 关闭当前标签页
⌘ + Shift + W 关闭当前窗口
⌘ + Option + 左/右箭头 切换到上一个/下一个标签页
⌘ + [ ,⌘ + ] 历史记录后退/前进
⌘ + L, 选中地址栏
⌘ + D 收藏标签页
⌘ + L, ⌘ + Enter 复制当前url到一个新的标签页

浏览器功能快捷键

快捷键 作用
⌘ + , 打开设置
⌘ + Option + B 打开书签管理器
⌘ + Y 打开历史记录
⌘ + Shift + Delete 打开“清除数据”对话框

面试题系列-React问题

react事件绑定

  • 与原生DOM事件绑定的区别;
    • React事件的用驼峰法命名,DOM事件事件名是小写;
    • 通过jsx,传递一个函数作为event handler,而不是一个字符串(DOM元素)。
    • React事件处理函数阻止默认事件,不能通过返回false来实现,必须显示调用event.preventDefault()
  • 绑定this的几种方式(如果不绑定this,那么方法执行的时候是找不到this的)
    • 调用时bind
    • constructor里面bind
    • 类的属性初始化语法,箭头函数
    • 调用时使用箭头函数

React生命周期

image

函数式编程,纯函数

  • 函数副作用是指调用函数时,除了返回函数值外,还对调用函数产生附加的影响,例如修改函数外部的变量或修改参数;函数副作用,给程序带来十分难以查找的错误,并且降低程序的可读性。严格的函数式语言必须无副作用;
  • 纯函数:输入输出数据流全是显式(Explicit)的。函数与外界交换数据只有唯一渠道——参数和返回值

React创建组件的方式

  • 无状态函数组件

    • 组件不会被实例化,整体渲染性能提升
    • 无法访问this对象
    • 无法访问生命周期方法
    • 只能访问props,无副作用
  • React.createClass

    • React.createClass创建的组件,其每一个成员函数的this都由React自动绑定,任何时候使用,直接使用this.method即可,函数中的this会被正确设置;React.Component创建的组件,其成员函数不会自动绑定this,需要手动绑定,否则this不能获取当前组件实例对象
var Greeting = React.createClass = ({
    getInitialState: function() {
        return {
            work_list: []
        };
    },
    render: function () {
        return (
            <div>
                <input type="text" ref="myWork" placeholder="What need to be done?" onKeyUp={this.Enter}/>

                <ul>
                    {
                        this.state.work_list.map(function (textValue) {
                            return <li key={textValue}>{textValue}</li>;
                        })
                    }
                </ul>

            </div>
        );
    },

  • React.Component

组件性能优化

  • shuouldComponentUpdate
shouldComponentUpdate(nextProps, nextState) {
    // 如果当前的value值与待更新不相等,才执行更新
    return this.props.value !== nextProps.value;
} 
  • pureComponent
import React, { PureComponent } from 'react'

class Example extends PureComponent {
  render() {
    // ...
  }
}
  • immutablejs
  • key
    • 不要使用index作为key,因为index和具体的项并没有一一对应关系,对象的index可能会变
array.map(val, key) => {
   return <span key={key}>{val}</span>
})

注意:1. PureRenderMixin、PureComponent 内进行的仅仅是浅比较对象(shallowCompare)

如何设计好一个组件

    1. render过长:切割 render() 方法
    1. 模板化组件
    1. 高阶组件

哪个生命周期进行网络请求?为什么?

componentDidMount,因为:

  • componentDidMount指的是第一次插入dom完毕,无论在同步和异步模式下都仅会触发一次
  • 在16.3之前的react版本,react是同步渲染的,在componentWillMount中调用接口,有可能不会触发界面渲染;而在componentDidMount中渲染一定会触发界面渲染
  • React 下一代调和算法 Fiber 会通过开始或停止渲染的方式优化应用性能,其会影响到 componentWillMount 的触发次数。对于 componentWillMount 这个生命周期函数的调用次数会变得不确定,React 可能会多次频繁调用 componentWillMount。如果我们将 AJAX 请求放到 componentWillMount 函数中,那么显而易见其会被触发多次,自然也就不是好的选择
  • 至于componentWillMount比componentDidMount执行早,页面渲染更快的说法,其实这一说法一直来并不成立; 因为componentWillMount会立即执行,执行完之后会立即进行render

调用setState之后发生了什么

  • 调用setState之后,React会将传入的参数与组件的当前状态合并,然后触发调合过程(Reconciliation),然后React会以相对高效的方式根据新状态构建React的虚拟DOM树,然后根据VDOM diff算法对界面进行最小化重渲染;VDOM diff算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。

React 中 refs 的作用是什么?

  • refs是React提供的安全访问真实DOM元素或者某个组件实例的句柄,添加到component上,返回的是component的实例;
  • React.findDomNode的:当传入参数是DOM,返回的就是DOM, 当参数是Component,返回的是Component render方法中返回的DOM;

在React中,Element和Component有什么区别

  • Component是由Element构成的。Element的数据结构是普通对象,而Component的数据结构是类或纯函数。
  • Element是 React 中最小基本单位,我们可以使用 JSX 语法轻松地创建一个 React 元素,也可以用React.createElement() 和 React.cloneElement() 来构建 React 元素;而组件Component是可以接收参数输入并且返回某个 React Element 的函数或者类

React key是干嘛的

  • Key是React用来追踪列表中哪些元素被修改,添加或删除的辅助标识
  • 在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性

组件间通信

  • 父传子:props
  • 子传父:回调函数
  • 跨级组件通信:组件props层层传递props或者context
  • 非嵌套组件通信:自定义事件(观察者模式)
  • 引入redux或者mobx

容器组件和展示组件(smart和dumb组件)

  • Redux 的 React 绑定库包含了 容器组件和展示组件相分离 的开发**。明智的做法是只在最顶层组件(如路由操作)里使用 Redux(容器组件)。其余内部组件仅仅是展示性的,所有数据都通过 props 传入。

props.children

  • 三种可能:
    • undefined:当前组件没有子节点
    • Object类型;有且仅有一个子节点
    • Array类型:多个子节点
  • React.Children
    • 我们可以用 React.Children.map(已对上述三种情况进行处理) 来遍历子节点;

React16新特性(尤其理解time slice和suspense)

新的核心架构Fiber

  • render支持返回数组
//string
render(){
  return 'hello,world'
}
 
//number
render(){
  return 12345
}
 
//boolean
render(){
  return isTrue?true:false
}
 
//null
render(){
  return null
}
 
//fragments,未加key标识符,控制台会出现warning
render(){
  return [
    <div>hello</div>,
    <span>world</span>,
    <p>oh</p>
  ]
}
  • 使用Error Boundary处理错误组件
//最佳实践:将ErrorBoundary抽象为一个公用的组件类
export default class ErrorBoundary extends Component {
  constructor(props) {
    super(props)
    this.state = { hasError: false }
  }
  componentDidCatch(err, info) {
    this.setState({ hasError: true })
    //sendErrorReport(err,info)
  }
  render(){
    if(this.state.hasError){
      return <div>Something went wrong!</div>
    }
    return this.props.children
  }
}

//使用方式
render(){
  return (
    <div>
      <ErrorBoundary>
        <Profile user={this.state.user} />
      </ErrorBoundary>
      <button onClick={this.onClick}>Update</button>
    </div>
  )
}
  • 支持自定义DOM属性
    • React会忽略无法识别的HTML和SVG属性,自定义属性只能通过data-*形式添加,现在它会把这些属性直接传递给DOM(这个改动让React可以去掉属性白名单,从而减少了文件大小
  • portal机制:使用createPortal将组件渲染到当前组件树之外
  • setState传入null不会触发更新
  • 更好的服务端渲染,接近3倍性能于React 15
  • 新的打包策略
    • 新的打包策略中去掉了process.env检查。
      React 16的体积比上个版本减小了32%(30% post-gzip),文件尺寸的减小一部分要归功于打包方法的改变

高阶组件HOC是什么以及常用的高阶组件

  • 高阶组件:就是接受一个组件作为参数并返回一个新组件的函数(高阶组件是一个函数,而不是组件)
  • 使用高阶函数的好处或用途:
    • 代码复用,模块化
    • 增删改props
    • 渲染劫持
  • 常见实现方式
    • 基于属性代理方式
    • 基于反相继承方式
    • 组合多个高阶组件(比如compose)
  • 注意事项:
    • 参数组件静态方法static丢失;解决办法:hoist-non-react-statics
    • Refs属性不能传递,解决办法
      • a) 像React Redux的connect方法一样,在里面添加一个参数,比如withRef,组件中检查到这个flag了,就给下级组件添加一个ref,并通过getWrappedInstance方法获取。

React的setState同步还是异步?

  • 严格来说不保证是同步的
  • 在组件生命周期中或者react事件绑定中,setState是通过异步更新的。
  • 在延时的回调或者原生事件绑定的回调中调用setState不一定是异步的。

面试题系列-Javascript问题

解释事件委托

  • 事件委托就是将事件监听器添加到父元素,而非每个子元素设置事件监听器。当子元素事件产生,冒泡到父元素,监听器就会触发
  • 好处:
    • 内存占用减少,只需要父元设置监听函数,而不必为每个子元素都设置
    • 无需从已删除的子元素解绑事件监听函数,也不必为新增的子元素绑定监听函数

请简述js中的this

符合以下规则:

    1. 调用函数时使用new关键字,函数内的this指向新生成的对象
    1. applay,call,bind等函数被调用后,函数内的this,是传入的context
    1. 当函数作为对象的方法被调用,函数内的this指向调用函数的对象本身
    1. 如果调用函数不符合以上规则,this指向全局对象。浏览器环境下是window;严格模式向,this为undefined。按顺序匹配以上规则,匹配后即决定this指向。
  • 5.如果该函数是ES6的箭头函数,this指向函数创建时的上下文。

解释原型的工作原理

  • 通过new Function()创建的对象都是函数对象;Function和Object也是通过new Function()创建的
  • 实例的constructor指向创建该实例的构造函数
  • 每个对象都有__proto__属性,但只有函数对象有prototype属性,
  • Person.prototype.constructor === Person
  • 原型对象是构造函数的一个实例
  • 当试图访问一个对象某个属性时,如未找到,会通过__proto__指向逐级查找,直到找到一个名字匹配的属性或到达原型链的末尾

你怎么看 AMD vs. CommonJS?

  • AMD: 异步,适合浏览器环境,依赖前置,实现:requireJS
  • CommonJS:同步,依赖就近,适合服务器环境,实现:Node
  • CMD:依赖就近,延迟执行,实现:sea.js
  • ES6的import,export

sea.js跟AMD的规范在预加载这一点上是相同的,明显不同的地方是调用,和声明依赖的地方

// CMD
define(function(require, exports, module) {
  var a = require('./a');
  a.doSomething();
  var b = require('./b');
  b.doSomething();
})

// AMD

define(['a', 'b'], function(a, b){
    a.doSomething()
    b.doSomething()
})

请解释下面代码为什么不能用作 IIFE:function foo(){ }();? 需要作出哪些修改才能使其成为 IIFE?

  • js解析器会将funciton(){} ()解析成function(){}和();其中,前者是函数声明后者是试图调用一个函数,但没有指定名称,会抛出Uncaught SyntaxError: Unexpected token )的错误
  • 修改方法有两种形式:(function(){})()和(function(){}()); 以上函数即IIFE,不会暴露到全局作用域,省略了函数名称

null,undefined和未声明(undeclared)变量有什么区别,如何检测他们

  • 未声明变量:当未使用var,let或 const去声明一个变量,该变量就是undeclared variable,未声明变量会脱离当作用域,成为全局作用域下的变量。在严格模式下,给未声明变量赋值,会抛出ReferenceError错误;要检查判断它们,需要将用到它们的代码放在try/catch语句中捕获
  • undefined:当变量已经声明,但是未赋值,改变量值为undefined,使用 === undefined或者typeof的值为‘undefined’
  • null:只能被显式的赋值给变量,表示空值,是能使用严格相等 === null检测

建议不要使用未声明变量。如果定义了暂时没有用到的变量,声明时赋值为null,养成良好习惯。

什么是闭包?如何使用?为什么要使用它?

  • 有权访问其他函数作用域变量的函数叫做闭包
  • 闭包就是由函数创建的一个词法作用域,里面创建的变量被引用后,可以在这个此法作用域之外引用

作用:

  • 闭包通常用来创建内部变量,这些变量不会暴露到全局作用域,不会被外部随意修改,,同时又可以通过指定的函数接口来操作。
  • 利用闭包实现数据私有化或者模拟私有方法,这种方式即模块模式
  • 柯里化

forEach和map的区别,使用场景分别是什么

  • forEach无法回执,对每个元素执行回调;map是将每个元素映射到新元素,会返回一个新数组

匿名函数典型使用场景

  • IIFE
  • 闭包中,内部函可以匿名数被返回

如何组织自己的代码?是模块模式(module pattern),还是经典继承(classical inheritance)

  • 使用es6的模块机制

宿主对象和原生对象的区别

  • 宿主对象:运行时环境(浏览器或者Node)提供的对象,如window,XmlHTTPRequest等
  • 原生对象:由ECMAScript规范定义的javascript内置对象,如String,Math,RegExp,Object,Function等

请指出以下代码的区别:function Persion(){} var persion = Persion();

var persion = new Persion()

  • 作为普通函数使用,返回undefined
  • 加new关键字,会产生一个对象,并且constructor属性指向Person,__proto__属性指向Person.prototype

apply,call,bind,如何实现这三个功能的。

 // call实现
 Function.prototype.mycall = function (context, ...args) {
   context = context || window
   context.fn = this
   var result = null;
   if(window.JSON) {
     result = context.fn(...args)
   } else {
     var args2 = [];
     var args3 = [];
     for(var i = 1, len = arguments.length; i < len; i++) {
       args2.push('arguments[' + i + ']')
     }
     result = eval('context.fn(' + args2 + ')')
   }
   delete context.fn
   return result
 }
 
 // apply实现
 Function.prototype.myapply = function (context, args) {
  context = context || window
  args = args || []
  context.fn = this
  var result = null;
  if (window.JSON) {
    result = context.fn(...args)
  } else {
    var args2 = [];
    for (var i = 0, len = args.length; i < len; i++) {
      args2.push('args[' + i + ']')
    }
    result = eval('context.fn(' + args2 + ')')
  }
  delete context.fn
  return result
}

// bind实现
Function.prototype.mybind = function (context, ...args) {
  if (typeof this !== "function") {
    throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
  }
  var self = this
  var args = [].slice.call(arguments, 1);
  var fnNOP = function () {};
  var resFn = function (...params) {
    if(window.JSON) {
      return self.apply(context, [...args, ...params])
    }
    var bindArgs = [].slice.call(arguments);
    return self.apply(context, args.concat(bindArgs))
  }
  // 修改返回函数的 prototype 为绑定函数的 prototype,实例就可以继承绑定函数的原型中的值
  fnNOP.prototype = this.prototype
  resFn.prototype = new fnNOP();
  return resFn
}

new模拟实现

  • 构造函数返回值如果是引用类型,会改变其返回值,非引用类型,不影响生成对象
function myNew() {
 var obj = {};
 Constructor = [].shift.call(arguments);
 obj.__proto__ = Constructor.prototype;
 Constructor.apply(obj, arguments);
 return (ref = typeof Constructor === "object" ? ref || obj : obj);
}

document.write()

  • 当页面加载后执行document.write()时,它将调用document.open(),会清除整个文档(<head/>和<body/>会被移除),将文档内容替换成函数传入的字符串参数。因此这个函数被认为是危险并且容易被误用。

特性检测feature detection) 特性推断(feature inference) UA字符串嗅探

  • 功能检测:在使用某些可能存在兼容性的特性时,判断浏览器是否支持,不支持的情况有相应流程处理
  • 功能推断:判断功能是否可用,从而推断出另一特性是否可用
  • UA字符串:这是一个浏览器报告的字符串,它可以通过navigator.userAgent访问,这个字符串很难解析可能存在欺骗;Chrome浏览器会同时作为Chrome、Safari进行报告。因此,要检测 Safari,除了检查 Safari 字符串,还要检查是否存在 Chrome 字符串。不要使用这种方式。
// 功能检测
if ('geolocation' in navigator) {
  // 可以使用 navigator.geolocation
} else {
  // 处理 navigator.geolocation 功能缺失
}

// 功能推断
if (document.getElementsByTagName) {
  element = document.getElementById(id);
}

请解释变量提升

  • 使用var声明的变量会将声明提升到作用域的顶部,function开头函数声明也会使函数的定义提升,但是如果使用函数表达式定义的函数只会将变量提升

请描述事件冒泡

  • 当一个事件在dom元素上触发时,如果该元素上绑定了函数监听器,则会尝试处理该事件。然后这个事件会逐级往父级元素传递,直至最外层元素;

attribute和property

  • attribute是HTML标签上的属性,通过dom.getAttribute(属性名),得到,
  • property是DOM中的属性,dom.属性名,可以取得
  • attribute和property之间的数据绑定是单向的,attribute->property;attribute的值能同步到property;但是property的值不能同步到attribute

为什么不建议扩展javascript内置对象

  • 扩展内置对象意味着将某些属性或方法添加到该对象的prototype,真是很危险的,如果你引用了不同的库,然后这些库对某个对象扩展了同名的属性。会互相覆盖,你的代码将将不能正常运行;
  • 唯一使用场景是创建polyfill,本质上为老版浏览器缺失的方法提供自己的实现,该方法是javascript新标准定义的;

document中的load和DOMContentLoaded事件的区别是什么?

  • 当初始的HTML文档被完全加载和解析完成以后,DOMContentLoaded事件触发;无需等待样式表,图像和子框架的加载
  • load事件在DOM和所有相关资源完全加载完成时触发;

==” 和 “===” 的区别

  • “===”是严格相等,只要类型不同,就会返回false;
  • “==”是抽象相等运算符,只要等式两边经过类型转换后的值相等,就会返回true

什么是“use strict”?它有什么优缺点?

  • ES5的严格模式是采用具有限制性javascript变体的一种方式,从而使代码显式的脱离sloppy模式,
  • 优点:
    • 无法意外常见全局变量
    • 会使引起静默失效的赋值操作抛出异常;例如,正常模式下,给NaN赋值不会产生任何作用;严格模式下,会抛出异常;任何在正常模式下引起静默失败的赋值操作 (给不可写属性赋值, 给只读属性(getter-only)赋值赋值, 给不可扩展对象(non-extensible object)的新属性赋值) 都会抛出异常
    • 试图删除不可删除的属性会抛出异常
    • 函数参数性唯一
    • 重名属性会报错
    • 禁止八进制数字语法(ES6支持已“0O”前缀表示八进制)
    • ES6中的严格模式,禁止设置原始值的属性,将抛出TypeError错误
    • 严格模式禁用with
    • 不再支持arguments.callee
    • arguments[i] 的值不会随与之相应的参数的值的改变而变化,同名参数的值也不会随与之相应的 arguments[i] 的值的改变而变化
  • 缺点:
    • 无法访问function.caller和function.arguments,
    • 以不同严格模式编写的脚本合并后可能导致问题

fizzbuzz实现

for(var i = 0; i < 100; i++) {
  let f = i % 3 === 0
  let b = i % 5 === 0
  console.log(f ? b ? 'Fizzbuzz' : 'Fizz' : b ? 'Buzz' : i )
}

为什么建议不要使用全局作用域?

  • 防止命名冲突
  • 使用模块模式(IIFE),将函数封装在本地命名空间

为什么要使用load事件?有什么缺点吗?知道一些代替方案吗,为什么使用它们?

  • load事件仅在DOM和所有相关资源全部加载后才会触发,
  • 当初始的 HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表、图像和子框架的完成加载。如果在初始化之前不需要装入整个页面,这个事件是使用首选。

请解释单页应用是什么,如何使其对 SEO 友好

  • SPA的概念是随着Ajax一同火起来的,Ajax支持异步刷新,不会有传统后端渲染的网站哪种整个页面刷新跳转;SPA不会触发页面刷新。该页面的 URL 通过 HTML5 History API 进行更新
  • 优点:
    • 用户感知响应更快,用户切换页面时,不会有页面跳转时那种白屏
    • 对于每个页面加载,不必再次下载相同的资源
    • 前后端分离
  • 缺点:
    • 首屏时间增加,因为一开始要下载多个页面所需的框架、库,应用代码和资源
    • 不利用SEO
    • 服务器需额外配置,需要将所有请求路由配置到单个入口,由客户端接管路由。

使用一种可以编译成的 JavaScript的语言来写JavaScript 代码有哪些优缺点?

包括 CoffeeScript、TypeScript、Elm、ClojureScript、PureScript

  • 优点:
    • 修复了 JavaScript 中的一些长期问题,并摒弃了 JavaScript 不好的做法
    • 在 JavaScript 的基础上提供一些语法糖,使我们能够编写更短的代码,ES5 缺乏语法糖的支持,但 ES6 非常好
    • 对于需要长时间维护的大型项目,静态类型非常好用(针对 TypeScript
  • 缺点:
    • 增加了编译过程
    • 学习成本
    • 增加调试难度,如果source map 不能很好地映射到预编译的源代码,调试会很痛苦
    • 这些语言将始终落后于最新的 JavaScript 标准

你使用什么工具和技巧调试 JavaScript 代码?

  • React Devtools 、Redux Devtools、Chrome Devtools

你使用什么语句遍历对象的属性和数组的元素?

  • 遍历对象:
    • for:遍历到对象所有属性,包括继承属性
    • Object.keys:自身可枚举属性
    • Object.getOwnPropertyNames:所有自身属性,包括不可枚举属性
  • 遍历数组:
    • for:
    • forEach:

请解释可变对象和不可变对象的区别

  • 可变对象:创建之后可以被改变
  • 不可变对象:创建之后不可以被改变
    • 优点:测试友好,可回溯,减少了任何副作用
    • 缺点:更多的内存消耗

请解释同步函数和异步函数的区别

  • 同步函数阻塞
  • 异步函数不阻塞

使用let、var和const创建变量有什么区别

  • let和const有块级作用域,var只有全局作用域和函数作用域
  • var会使变量提升;let和const不会,不需先声明,后使用
  • var重复声明不会报错;let和const会
  • const声明的变量,只可以赋值一次,即常量;let可以多次赋值;

高阶函数(higher-order)的定义是什么?

  • 高阶函数是将一个或多个函数作为参数的函数

请给出一个解构(destructuring)对象或数组的例子

// 变量交换
let a = 1;
let b = 3;
[a, b] = [b, a];

ES6 的模板字符串为生成字符串提供了很大的灵活性,你可以举个例子吗?

console.log(`string text line 1
string text line 2`);
// "string text line 1
// string text line 2"

var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and\nnot ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."

你能举出一个柯里化函数(curry function)的例子吗?它有哪些好处

  • 柯里化是一种模式,具有多个参数的函数被分解成多个函数- 好处:这种技术帮助编写函数式风格的代码,使代码更易读、紧凑
function add(a, b) {
  return a + b;
}

var curriedAdd = curry(add);
var addFive = curriedAdd(5);

var result = [0, 1, 2, 3, 4, 5].map(addFive); // [5, 6, 7, 8, 9, 10]

使用扩展运算符(spread)的好处是什么,它与使用剩余参数语句(rest)有什么区别?

  • 可以轻松创建数组和对象的拷贝,而无需使用Object.create、slice或其他函数库
  • ES6 的剩余参数语句提供了一个简写,允许我们将不定数量的参数表示为一个数组。它就像是扩展运算符语法的反面,将数据收集到数组中,而不是解构数组

箭头函数ES5如何实现?箭头函数和普通函数的区别

  • ES6箭头函数内部没有this,使用时会上朔寻找最近的this
  • 不可以用做构造函数,不能使用new命令,因为没有this
  • 函数体内没有arguments,可以使用rest参数代替
  • 不能用yield,不能使用generator函数

图片懒加载咋实现的?

  • 当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样就只需请求一次),只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。

网页各种高度(js盒子模型)

  • client系列
    • clientWidth/clientHeight:width + 左右padding/ height + 上下padding
    • clientLeft/clientTop:左/上边框的宽度
  • scroll系列
    • scrollWidth/scrollHeight:
      • 在没有内容溢出的情况下和clientWidth/clientHeight是一样的
      • 有内容溢出时:scrollHeight约等于 真实内容的高度(包含溢出的内容) + 上padding
    • scrollLeft/scrollTop(可读写):滚动条卷去的宽度/高度
  • offset系列
    • offsetWidth/offsetHeight:clientWidth + 左右边框 / clientHeight + 上下边框
    • offsetLeft/offsetTop: offsetLeft:当前元素的外边框距离父级参照物的左偏移量/上偏移量
    • offsetParent

我们通过以上这些属性值获取的结果永远不可能出现小数,都是整数;浏览器获取结果的时候,会在原来真实结果的基础上进行四舍五入。

深拷贝和浅拷贝? 手写深拷贝

在存入数组或对象时,会在浏览器的栈空间,存储指向堆空间的指针(及地址),而在堆空间存储真正的内容,访问时通过栈空间的地址来访问;

  • 浅拷贝:对引用地址的复制,这样的拷贝之后的数据
  • 深拷贝:对占空间真正内容的拷贝;
    • 数组:slice(), concat()
    • 对象:
// 所以对于一个对象的深拷贝
var cloneObj={};
function deepCopy(obj,newObj) {
    newObj=newObj || {};
    for (var i in obj){
        if(obj.hasOwnProperty(i)) {
            if (typeof obj[i]==="object"){
                newObj[i]=obj[i].constructor===Array?[]:{};
                deepCopy(obj[i],newObj[i])
            } else {
                newObj[i]=obj[i]
          } 
        }
    }
    return newObj
 }

实现页面加载进度条

  • main.html
<div class="loading" id="loading">
    <div class="progress" id="progress">0%</div>
</div>
var $loading = $('#loading')
        var $progress = $('#progress')
        var prg = 0

        var timer = 0
        var now = new Date()  // 记录当前时间
        var timeout = 5000  // 超时时间

        progress([80, 90], [1, 3], 100)

        window.onload = () => {
            console.log('onLoad');
            complete()
        }

        function complete() {
            progress(100, [1, 5], 10, () => {
                window.setTimeout(() => {  // 延迟了一秒再隐藏loading
                    $loading.hide()
                }, 1000)
            })
        }

        // window.setTimeout(() => {  // 设置5秒的超时时间
        //     complete()
        // }, timeout - (now - loadingStartTime))

        if (now - loadingStartTime > timeout) {  // 超时
            complete()
        } else {
            window.setTimeout(() => {  // 未超时,则等待剩余时间
                complete()
            }, timeout - (now - loadingStartTime))
        }

        function progress(dist, speed, delay, callback) {
            var _dist = random(dist)
            var _delay = random(delay)
            var _speed = random(speed)
            window.clearInterval(timer)
            timer = window.setTimeout(() => {
                if (prg + _speed >= _dist) {
                    window.clearInterval(timer)
                    if (callback) {
                        prg = _dist
                        callback()
                    }
                } else {
                    prg += _speed
                    progress(_dist, speed, delay, callback)
                }

                $progress.html(parseInt(prg) + '%')
                console.log(prg)
            }, _delay)
        }

        function random(n) {
            if (typeof n === 'object') {
                var times = n[1] - n[0]
                var offset = n[0]
                return Math.random() * times + offset
            } else {
                return n
            }
        }

web worker

  • web worker是通过构造函数Worker()创建的对象,参数就是一个js文件的路径,能执行位于指定 URL 上的脚本,脚本将运行在主线程之外的worker线程,脚本路径必须遵循同源策略。

请尽可能详细地解释 Ajax。

    1. 创建ajax对象XMLHttpRequest/ActiveXObject(Microsoft.XMLHttp)
    1. 判断数据传输方式,GET/POST
    1. 设置服务端的返回数据的类型
    1. xhr.open() 打开连接
    1. xhr.send() 发送数据

给xhr对象的onreadystatechange事件设置监听器函数,判断http响应状态(status)200-300之间或者304(缓存)执行回调函数

  • 注意:检测XMLHttpRequest对象的readyState属性,该属性表示请求/响应过程的当前活动阶段,属性值如下:
    • 0:未初始化:尚未调用open()方法
    • 1: 启动:已经调用open()方法,但尚未调用send()方法
    • 2:发送:已经调用send()方法,但尚未接收到响应
    • 3:接受:已经接收到部分响应数据
    • 4:完成:已经接收到全部响应数据,而且已经可以在客户端使用了(如果写原生的js ajax请求需要等到 readyState==4的时候再做处理)其他的js库已经做好处理了

请说明 JSONP 的工作原理,它为什么不是真正的 Ajax?

  • 动态创建一个script标签,利用script标签的src属性访问无限制的特性,来接受不同源服务器的数据,从而实现跨域。

  • web客户端定义一个全局函数,将这个函数名作为callback参数值作为传递给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹json数据,客户端的函数便可以拿到服务器端返回的数据并进行处理

  • jsonP与ajax的区别:

    • ajax的核心是通过xmlHttpRequest获取非本页内容;jsonp的核心是动态添加script标签调用服务器提供的js脚本(后缀.json)
    • jsonp只支持get请求,ajax支持get和post请求

同源策略 (same-origin policy);Cookie,iframe,AJAX同源

  • 如果两个页面的协议,域名和端口相同,则两个页面具有相同的源;web浏览器允许某个页面的脚本访问其其同源页面里的数据

同源策略限制以下几种行为:

  • 1.) Cookie、LocalStorage 和 IndexDB 无法读取
  • 2.) DOM 和 Js对象无法获得
  • 3.) AJAX 请求不能发送

跨域,图片ping,JSONP,CORS(这是面试必问。注意一定要完全理解,完全!)

  • 图片ping:图片可以从任何URL中加载,所以将img的src设置成其他域的URL,即可以实现简单的跨域
  • jsonp
  • CORS:跨域资源共享,后台设置Header
  • nodejs中间件代理
  • document.domain
  • ( 还有webSocket/ postMessage)

什么是 Event loop?调用堆栈和任务队列之间有什么区别?(非常重要,面试必问。深入原理,宏任务,微任务等等)

Promise实现

函数节流和函数防抖的区别

  • 函数节流的原理是:在某一定时间内只执行一次js
  • 函数防抖的原理是:频繁触发的情况下,会用最后一次的时间覆盖前面的事件,只有足够的空闲时间,才执行代码一次。
// 函数节流
var canRun = true;
document.getElementById("throttle").onscroll = function(){
    if(!canRun){
        // 判断是否已空闲,如果在执行中,则直接return
        return;
    }

    canRun = false;
    setTimeout(function(){
        console.log("函数节流");
        canRun = true;
    }, 300);
};
// 函数防抖
var timer = false;
document.getElementById("debounce").onscroll = function(){
    clearTimeout(timer); // 清除未执行的代码,重置回初始化状态

    timer = setTimeout(function(){
        console.log("函数防抖");
    }, 300);
};  

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.