interview

es6中有哪些新特性:

新的变量声明方式 let/const

// 没有变量提升
console.log(a); //error
let a = 3; 
// 增加了块级作用域
{
    let b = 10
    console.log(b);
}
console.log(b);  // error

我们常常使用let来声明一个值会被改变的变量,而使用const来声明一个值不会被改变的变量,也可以称之为常量

const a = 5;
a = 7;   // Uncaught TypeError: Assignment to constant variable.
const b = {};
b.a = 5 ; //ok can change
b = []; // Uncaught TypeError: Assignment to constant variable.

如何实现const定义的引用类型也不能改变?

https://mathiasbynens.be/notes/es6-const

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

// 结合freeze和const
const foo = Object.freeze({
    'bar': 27
});

箭头函数的使用

//其次还有一个至关重要的一点,那就是箭头函数中,没有this。如果你在箭头函数中使用了this,那么该this一定就是外层的this。
var a = ()=> {
    // do something
}

模板字符串

var a = 'world';
var b = `hello ${a}`;

解析结构

const props = {
    className: 'tiger-button',
    loading: false,
    clicked: true,
    disabled: 'disabled'
}

const {loading, clicked} = props;

默认参数

function add(num1=10,num2=20){
    return num1 + num2;
}

扩展运算符

在ES6中用...来表示展开运算符,它可以将数组方法或者对象进行展开

var a = [1,2,3];
var b = [...a, 4,5,6];

function addAll(...num){
    return num.reduce((num1,num2)=>{return num1 + num2})
}

对象字面量简写

// 如果变量名和属性值相同时
var name = 'zhangzhuo';
var age = 18;
// es6
const person = {
    name,
    age
}
// es5
person1 = {
    name: name,
    age: age
}

// 在对象字面量中可以使用中括号作为属性,表示属性名也能是一个变量了。
const person = {
  [name]: true,
  [age]: true
}

class

// es6
class Person{
    constructor(name, age){
        this.name = name;
        this.age = age;
    }
    sayName(){
        console.log(this.name)
    }
}

//es5
function Person(name, age){
    this.name = name;
    this.age = age;
}
Person.prototype.sayName = function(){
     console.log(this.name)
}

继承extends

// es6
class Person{
    constructor(name, age){
        this.name = name;
        this.age = age;
    }
    sayName(){
        console.log(this.name)
    }
}

class Student extends Person{
    constructor(name, age, gender, classes) {
        super(name, age);
        this.gender = gender;
        this.classes = classes;
    }
  getGender() {
    return this.gender;
  }
}

// es5
function Person(name, age){
    this.name = name;
    this.age = age;
}
Person.prototype.sayName = function(){
     console.log(this.name)
}
function Student(name, age, gender, classes){
    Person.call(this,name,age);
    this.gender = gender;
    this.classes = classes;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
Student.prototype.getGender = function(){
     return this.gender;
}

Promise

var getJson = function(){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve(1000);
            console.log(1)
        }, 1000)
    })
}

var getJson2 = function(){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve(1000);
            console.log(2)
        }, 1000)
    })
}

getJson().then(function(){
    return getJson2()
}).then(function(){
    console.log(33333)
});


then之后return是一个新的promise

es7 Async/await语法

function getSomething() {
    return "something";
}

async function testAsync() {
    return Promise.resolve("hello async");
}

async function test() {
    const v1 = await getSomething();
    const v2 = await testAsync();
    console.log(v1, v2);
}

test();

模块 modules

引入模块

import test from './test'
  • import表示引入一个模块,
  • test 我们暂时理解为引入模块的名字,
  • from表示从哪里引入
  • ./test./test.js的简写,表示将要引入模块的路径
对外提供接口
// test.js
const num = 20;
const arr = [1, 2, 3, 4];
const obj = {
    a: 0,
    b: function() {}
}
const foo = () => {
    const a = 0;
    const b = 20;
    return a + b;
}

export default {
    num,
    arr,
    obj,
    foo
}

test.js中,我们使用export default对包暴露了一个对象。他的意思就是当我们使用import test from './test'时,这个test对象就默认等于export default暴露的对象。

我们还可以在test.js中,仅仅通过export暴露几个方法与属性,我们来看看index.js中test会变成什么样子。

// src/test.js
export const bar = () => {}
export const zcar = 12345;

保存运行后,我们发现,index.js中的test对象并没有变化,因为它仅仅等于export default抛出的对象,因此,为了获得模块test.js暴露的所有接口,我们得通过如下的方式。

// src/index.js
import * as test from './test';

其中的 * 表示所有,这是比较常用的通配符,as表示别名,* as test的意思是将test.js暴露的所有接口组成的对象,命名为test。那么我们在index.js中log出test,结果就如下。

如果大家还记得前面一篇文章里,我所讲的ES6解析结构的语法,那么对于如下的用法相信就不难理解。

// src/index.js
import test, { bar, zcar } from './test';

console.log(test);
console.log('bar:', bar);
console.log('zcar:', zcar);

test,仍然表示为export default暴露的对象,而 { bar, zcar }则表示利用解析结构的语法,从整个返回对象中去取得对应的接口。输出结果也就很清晰了。

这种方式还是比较常见,比如我们在使用react时,常常这样使用:

import React, { Component } from 'react'

它其实暗示了React的封装方式,也暗示了我们应该如何去封装我们的模块。


webpack的优化

引用自https://segmentfault.com/a/1190000007891318

方案一、合理配置 CommonsChunkPlugin

webpack的资源入口通常是以entry为单元进行编译提取,那么当多entry共存的时候,CommonsChunkPlugin的作用就会发挥出来,对所有依赖的chunk进行公共部分的提取,但是在这里可能很多人会误认为抽取公共部分指的是能抽取某个代码片段,其实并非如此,它是以module为单位进行提取。

假设我们的页面中存在entry1,entry2,entry3三个入口,这些入口中可能都会引用如utils,loadash,fetch等这些通用模块,那么就可以考虑对这部分的共用部分机提取。通常提取方式有如下四种实现:

1、传入字符串参数,由chunkplugin自动计算提取

new webpack.optimize.CommonsChunkPlugin('common.js')

这种做法默认会把所有入口节点的公共代码提取出来, 生成一个common.js

2、有选择的提取公共代码

new webpack.optimize.CommonsChunkPlugin('common.js',['entry1','entry2']);

只提取entry1节点和entry2中的共用部分模块, 生成一个common.js

3、将entry下所有的模块的公共部分(可指定引用次数)提取到一个通用的chunk中

new webpack.optimize.CommonsChunkPlugin({
    name: 'vendors',
    minChunks: function (module, count) {
       return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
       )
    }
});

提取所有node_modules中的模块至vendors中,也可以指定minChunks中的最小引用数;

4、抽取enry中的一些lib抽取到vendors中

entry = {
    vendors: ['fetch', 'loadash']
};
new webpack.optimize.CommonsChunkPlugin({
    name: "vendors",
    minChunks: Infinity
});

添加一个entry名叫为vendors,并把vendors设置为所需要的资源库,CommonsChunk会自动提取指定库至vendors中。

方案二、通过 externals 配置来提取常用库

在实际项目开发过程中,我们并不需要实时调试各种库的源码,这时候就可以考虑使用external选项了。

简单来说external就是把我们的依赖资源声明为一个外部依赖,然后通过script外链脚本引入。这也是我们早期页面开发中资源引入的一种翻版,只是通过配置后可以告知webapck遇到此类变量名时就可以不用解析和编译至模块的内部文件中,而改用从外部变量中读取,这样能极大的提升编译速度,同时也能更好的利用CDN来实现缓存。

external的配置相对比较简单,只需要完成如下三步:

1、在页面中加入需要引入的lib地址,如下:

<head>
<script src="//cdn.bootcss.com/jquery.min.js"></script>
<script src="//cdn.bootcss.com/underscore.min.js"></script>
<script src="/static/common/react.min.js"></script>
<script src="/static/common/react-dom.js"></script>
<script src="/static/common/react-router.js"></script>
<script src="/static/common/immutable.js"></script>
</head>

2、在webapck.config.js中加入external配置项:

module.export = {
    externals: {
        'react-router': {
            amd: 'react-router',
            root: 'ReactRouter',
            commonjs: 'react-router',
            commonjs2: 'react-router'
        },
        react: {
            amd: 'react',
            root: 'React',
            commonjs: 'react',
            commonjs2: 'react'
        },
        'react-dom': {
            amd: 'react-dom',
            root: 'ReactDOM',
            commonjs: 'react-dom',
            commonjs2: 'react-dom'
        }
    }
}

适用场景

在实际的开发过程中,可灵活地选择适合自身业务场景的优化手段。

优化手段 开发环境 生产环境
CommonsChunk
externals
DllPlugin
Happypack
uglify-parallel

工程演示demo

event中target和currentTarget的区别?

document.body.onclick = function(event){
    
}

this和currentTarget都等于document.body。 然而target指向真正触发的元素。

css让元素垂直居中

有2个元素,让子元素相对于父元素水平垂直居中。

<div class="box">  
    <div class="innerbox">css设置元素水平垂直居中显示</div>  
</div>  

已知元素的宽度

1、利用定位及设置元素margin值为自身的一半

.box{  
    width: 400px;  
    height: 200px;   
    border: 5px solid #ddd;   
    margin: 50px auto;   
    position: relative;  
}  
.innerbox{  
    width: 300px;  
    height: 100px;   
    border: 5px solid #f00;   
    font-size: 16px;   
    position: absolute;   
    left: 50%;   
    top: 50%;   
    margin: -50px 0 0 -150px;  

说明:此方法,在我们工作中经常用到,兼容性好。demo

2、margin:auto

.box{  
    width: 400px;   
    height: 200px;   
    border: 5px solid #ddd;   
    margin: 50px auto;   
    position: relative;  
}  
.innerbox{  
    position: absolute;   
    left: 0;   
    top: 0;   
    right: 0;   
    bottom: 0;   
    width: 300px;   
    height: 100px;   
    margin: auto;   
    border: 5px solid #f00;  
}  

说明: position: absolute; left: 0; right: 0; top: 0; bottom: 0;这是自动填充父元素的可用空间。然而给子元素设定了宽高,那么多余的空间,会被margin:auto平均分配。

实现未知元素宽高

1、利用css3属性transform实现

.box{  
    width: 400px;   
    height: 200px;   
    border: 5px solid #ddd;   
    margin: 50px auto;   
    position: relative;  
}  
.innerbox{  
    position: absolute;   
    left: 50%;   
    top: 50%;   
    border: 5px solid #f00;   
    transform: translate(-50%,-50%);  
}  

说明:这种方法在移动端被广泛使用。但是,只支持高版本浏览器(IE9+以上的浏览器支持)。

2、将父元素设置成display: table, 子元素设置为单元格 display: table-cell

这个方法跟上面介绍的方法不同,它不是让元素居中,而是让元素包含的内容居中

.box{  
    width: 400px;  
    height: 200px;   
    border: 5px solid #ddd;   
    margin: 50px auto;   
    display: table;  
}  
.innerbox{  
    display: table-cell;  
    vertical-align: middle;   
    text-align: center;   
    border: 5px solid #f00;  
}  

说明:利用表格的特性,将子元素看成行内元素,实现元素中的文字(文字可以是单行的,也可以是多行的)或图片水平垂直居中。demo

3、css3新的布局方法,弹性布局 display: flex

.box{  
    width: 400px;   
    height: 200px;   
    border: 5px solid #ddd;   
    margin: 50px auto;   
    display: flex;   
    align-items: center;   
    justify-content: center;  
}  
.innerbox{  
    width: 300px; /*宽度可以省略*/  
    height: 100px; /*高度可以省略*/  
    border: 5px solid #f00;   
    font-size: 16px;  
}  

说明: 此方法只支持IE9+以上的浏览器。display: flex代表弹性布局,align-items: center 代表垂直方向上的居中,justify-content: center代表水平方向上的居中。这些是css3中的新属性,感兴趣的同学可以查找相关资料学习。这里不多介绍。demo

移动端300ms延迟的解决方案

原来的解决方案:fastclick

其实现在已经不需要了, 浏览器自己做了处理:

https://developers.google.com/web/updates/2013/12/300ms-tap-delay-gone-away?hl=en

lib-flexible的多分辨率解决方案

引用项目里面的话https://github.com/amfe/lib-flexible

由于viewport单位得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方案。vw的兼容方案可以参阅《如何在Vue项目中使用vw实现移动端适配》一文。

在内在都用vw单位了, 关于rem中的问题可以参考:谈谈 rem 与 vw -- rem

RESTful协议的理解

什么是DOM树,浏览器又是如何渲染的?什么是CSS树?

webpack的原理

babel的原理

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

推荐阅读更多精彩内容