Coder Social home page Coder Social logo

blogs's People

Contributors

dujuncheng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

blogs's Issues

高级前端面试题——es6

es6

前言

  • 开发环境已经普及使用
  • 浏览器环境支持不够
  • 内容很多,重点了解常用语法
  • 面试�: 开发环境的使用 + 重点语法的掌握

模块化的使用和编译环境

模块化基本语法

// util1.js
export default {
  a:1 
}
// util2.js
export function f1(){}
export function f2(){}

// index.js
import obj from 'util1.js'
// 哪怕只引入一个也需要添加花括号
import { f1, f2 } from 'util2.js'

主要分为导出模块和引入模块:

导出模块

有两种方式可以导出模块

  • 在定义的语句面前,加export
export var a =1;
export let myVar= 'sss';
export const MYVAR = 'ssss';
export function Myfunc(){
   ……
  }
export class myclass{
   ……
 }
  • 另一种,写代码的时候不用考虑外部世界,在最后把想要导出的东西(变量,对象,方法)塞进一个对象里面。
    导入绑定列表看起来和解构赋值一样,但并不是
const my_const ='ssss';
function my_func () {
.....
}
export { my_const, my_func}

这两种方法以外的方法,比如说直接导出一个简单的值,是错误的:

//报错
export 1;
//报错
var m = 1;
export m;
//报错
function f () {}
export f ;
//正确
export function f (){};

简单来说,es6的export只有两种,要么在声明的时候导出,要么在花括号内导出

导入模块

import 必须把文件的拓展名加上,node 遵循基于文件系统前缀区分本地文件和包的惯例,example 是一个包,而 ./example.js 是一个文件。

import {test1, test2 } from './example.js'
import {test1} from './example.js'
import {test2} from './example.js'
import * as example from './example.js'

注意,要有大括号,和结构赋值很像。如果没有大括号,这是导入一个默认值

默认值

default 只能使用一次。如export default, 则不需要import {},如果export 哪怕是一个值,也需要在import时需要 import {}

//第一组
export default function crc32 (){
 //...
}
import crc32 from'crc32'; //输入
//第二组
export function crc32(){//输出
//...
};
import {crc32} from'crc32';//输入

export a = 1
export default function () {}

// 默认值在前,使用逗号分隔
import sum, { a } from 'example.js'

重命名

在导入导出的时候,都可以重命名

// 重命名
export { test as name }
import{ name as name2 }from'./example.js'

只读绑定

简单来说,就是导入的东西,无法重名,无法修改

当从一个模块导入一个绑定时,就如同const, 无法重名声明,重名声明会报错,导入其他模块也不能重名。
不管导入的东西,是个简单值还是引用类型,都不能修改。如果想修改,只能回退到被导入的模块。

// export.js
var name= 'test1'
function changeName (name) {
 name = name
}
export {name, changeName }
//import.js
import { name,changeName }from'./export.js'
console.log(name)//test1
changeName('test2')
console.log(name)//test2
name = 'test3'//报错
  • 模块顶部创建的变量不会添加到全局作用域,只会存在模块的顶级作用域中。
  • 模块的顶部,this是undifined
  • 不能 if(){ 导入或导出 }, 这是为了让javascript引擎静态的确定有哪些可以导出。
  • import 会被提升到顶部,因此代码中“先使用,再导入也是可以”
foo();
import { foo } from 'my_module';

更深入细节可以学习 http://exploringjs.com/es6/ch_modules.html 这片博客

class

promise 用法

其他es6的功能

如何用gulp构建一个es6项目

一般前端基础架构

  1. 业务逻辑
  2. 页面(html+css)
  3. 交互(js)
  4. 自动构建
  5. 编译(es6转成es5,甚至es3)
  6. 辅助
    1. 自动刷新
    2. 文件合并
    3. 资源压缩
  7. 服务接口
  8. 数据
  9. 接口

任务自动化gulp

  1. grunt操作慢,gulp通过stream提高了操作速度
  2. gulp基于nodejs开发,背后有很多插件

什么是gulp

理想中前端开发流程是

  1. 写业务代码,es6, sass
  2. 处理成浏览器认识的
  3. 刷新浏览器

后两步(也就是 2 和 3)应该是自动化的, 交由构建工具来做, gulp就是一种流行的构建工具。
开发工作中痛苦耗时的任务有哪些?

  1. 用 es6,typescript编译成javascript
  2. 用 scss,less编译成css
  3. 检查代码,单元测试和集成测试
  4. 开发环境sourcemaps 的话调试,热更新
  5. 生产环境中代码需要压缩合并资源

这些痛苦的过程,gulp可以帮我们自动化的完成

如何使用gulp

全局安装和本地安装

npm install gulp -g 
npm install gulp --save-dev

根目录下新建gulpfile.js文件,是gulp的配置文件

gulpfile.js大小写不敏感,最好放在根目录下,否则需要gulp yourtask --gulpfile yourpath来指定

最简单的gulp任务

gulpfile.js里面就是gulp脚本

// 引入gulp脚本
var gulp = require('gulp')
// 创建一个sayhi的任务
gulp.task('sayhi', ()=>{
  console.log('hi')
})

然后在命令行里面执行gulp sayhi的命令就可以了。

gulpfile.js和es6的关系

gulpfile.js里面不能写es6
gulp3.9版本之后可以和babel配合在gulpfile.babel.js里面写es6

1、 安装babel

cnpm install babel-core babel-preset-es2015 --save-dev

2、 创建.babelrc文件

touch .babelrc
注意是JSON格式
{
  "presets":["es2015"]
}
  1. 创建gulpfile.babel.js (之前创建的是gulpfile.js, 需要把该文件删除)
// 引入gulp脚本
import gulp from 'gulp'
// 创建一个sayhi的任务
gulp.task('sayhi', ()=>{
  console.log('hi')
})

到现在,我们就可以在gulpfile.babel.js里面开心的使用es6的语法了

稍微难一点的gulp任务

通常会有两个特定的gulp方法和一些gulp插件
gulp.src()是打开路径的文件,gulp.dest()是把文件放在指定路径

gulp.task('task-name', ()=>{
  return gulp.src('source-files')
  .pipe(gulpPlugin())
  .pipe(gulp.dest('destination'))
})

下面以sass文件的编译为例:
安装gulp-sass

cnpm install gulp-sass --save-dev

新建测试用的sass文件

// app/sass/styles.scss
.testing {
  width: percentage(5/7)
}

编写脚本

import gulp from 'gulp'
import sass from 'gulp-sass'
gulp.task('css', ()=> {
  return gulp.src('app/css/styles.scss')
  .pipe(sass())
  .pipe(gulp.dest('app/css'))
})

app/css/styles.scss目录里就会被编译到gulp.dest('app/css')里面

Node中的通配符

使用通配符,计算机检查文件名和路径进行匹配。
常用的4种匹配模式:
*.scss:*号匹配当前目录任意文件
**/*.scss:匹配当前目录及其子目录下的所有scss文件。
!not-me.scss:!号移除匹配的文件,这里将移除not-me.scss
*.+(scss|sass):+号后面会跟着圆括号,里面的元素用|分割,匹配多个选项。这里将匹配scss和sass文件。

上面的例子改造一下:

gulp.task('sass', function() {
  return gulp.src('app/scss/**/*.scss') 
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
})

监听文件

Gulp提供watch方法给我们,语法如下:

gulp.watch('file-to-watch',['tasks', 'to', 'run'])

我们把watch方法放在任务里面:

gulp.task('watch', ()=>{
  gulp.watch('app/**/*.scss',['css'])
})

有了监听,每次修改文件,Gulp都将自动为我们执行任务。

自动刷新浏览器

Browser Sync 帮助我们搭建简单的本地服务器并能实时刷新浏览器

npm install browser-sync --save-dev

这里没有gulp-前缀,因为browser-sync支持Gulp,所以没有人专门去搞一个给Gulp用哈哈
我们创建一个broswerSync任务,我们需要告知它,根目录在哪里。

import browserSync from 'browser-sync'
gulp.task('browserSync', ()=> {
  browserSync({
    server: {
      baseDir: 'app'
    }
  })
})

我们稍微修改一下之前的代码,让每次css文件更改都刷新一下浏览器:

gulp.task('sass', function() {
  return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
    .pipe(browserSync.reload({
      stream: true
    }))
});

我们可以在watch任务之前告知Gulp,先把browserSync和Sass任务执行了再说。

gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], function (){
  // ...
})

应用下来是这样:

gulp.task('watch', ['browserSync', 'sass'], function (){
  gulp.watch('app/scss/**/*.scss', ['sass']);
  // Other watchers
})

现在你执行gulp watch命令,在执行完browserSync和Sass,才会开始监听。

优化CSS和JavaScript文件

我们需要想到:压缩,拼接。也就是减少体积和HTTP次数
开发者面临的主要问题是很难按照正确的顺序合并文件。

gulp-useref会将多个文件拼接成单一文件,并输出到相应目录。

<!-- build:<type> <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->

type 可以是js,css,或者remove。如果你设为remove,Gulp将不会生成文件。

path指定产出路径。

我们想最终产出main.min.js。可以这样写:

<!--build:js js/main.min.js -->
<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>
<!-- endbuild -->

我们来安装gulp-useref。

npm install gulp-useref --save-dev

引用

var useref = require('gulp-useref');

使用也非常简单

gulp.task('useref', function(){

  return gulp.src('app/*.html')
        .pipe(useref())
        .pipe(gulp.dest('dist'));
});

执行useref命令,Gulp将合并三个script标签成一个文件,并保存到dist/js/main.min.js。

合并完之后,我们再来压缩。使用gulp-uglify插件。

npm install gulp-uglify --save-dev

使用

// Other requires...
var uglify = require('gulp-uglify');
gulp.task('useref', function(){
  return gulp.src('app/*.html')
    .pipe(uglify()) // Uglifies Javascript files
    .pipe(useref())
    .pipe(gulp.dest('dist'))
});

注意:执行完useref后,html中的script路径将只剩下main.min.js。

gulp-useref同样可以用在css上。除了压缩,需要区分,其它内容同js一样。所以我们使用gulp-if来做不同处理。

使用gulp-minify-css压缩css。

npm install gulp-if gulp-minify-css --save-dev
var gulpIf = require('gulp-if');
var minifyCSS = require('gulp-minify-css');

gulp.task('useref', function(){

  return gulp.src('app/*.html')
    // Minifies only if it's a CSS file
    .pipe(gulpIf('*.css', minifyCSS()))
    // Uglifies only if it's a Javascript file
    .pipe(gulpIf('*.js', uglify()))
    .pipe(useref())
    .pipe(gulp.dest('dist'))
});

优化图片

使用gulp-imagemin插件。

npm install gulp-imagemin --save-dev
var imagemin = require('gulp-imagemin');
gulp.task('images', function(){
  return gulp.src('app/images/**/*.+(png|jpg|gif|svg)')
  .pipe(imagemin())
  .pipe(gulp.dest('dist/images'))
});

清理生成文件

我们不想旧文件掺杂进来,使用del

npm install del --save-dev
var del = require('del');
gulp.task('clean', function() {
  del('dist');
});

但是我们又不想图片被删除(图片改动的几率不大),启用新的任务。

gulp.task('clean:dist', function(callback){
  del(['dist/**/*', '!dist/images', '!dist/images/**/*'], callback)
});

组合Gulp任务

废话了这么多,我们主要有两条线路。

第一条是开发过程,我们便以Sass,监听文件,刷新浏览器。

第二条是优化,我们优化CSS,JavaScript,压缩图片,并把资源从app移动到dist。

开发过程上面已经写好了,下面我们主要来写优化过程

gulp.task('build', [`clean`, `sass`, `useref`, `images`, `fonts`], function (){
  console.log('Building files');
})

但是这样Gulp会同时触发[]的事件。我们要让clean在其他任务之前完成, 需要用到run-sequence

var runSequence = require('run-sequence');

gulp.task('task-name', function(callback) {
  runSequence('task-one', 'task-two', 'task-three', callback);
});

执行task-name时,Gulp会按照顺序执行task-one,task-two,task-thre。
RunSequence也允许你同时执行多个任务。

gulp.task('task-name', function(callback) {
  runSequence('task-one', ['tasks','two','run','in','parallel'], 'task-three', callback);
});
gulp.task('build', function (callback) {
  runSequence('clean:dist',
    ['sass', 'useref', 'images', 'fonts'],
    callback
  )
})

小结

上面的的内容搭建了一个基本的Gulp工作流。还有更精彩的内容等着你去开发。这里提供些插件:
开发过程:

使用 Autoprefixer,你不再需要写CSS浏览器内核前缀
增加 Sourcemaps,让你更方便的调试Sass,coffeescript
使用 sprity创建精灵图
gulp-changed 只允许通过修改的文件
Babel 或 Traceur 写ES6
Browserify , webpack , jspm 模块化JavaScript
Handlebars ,Swing 模块化Html
require-dir 分割gulpfile成多个文件
gulp-moderinizr 自动生成Modernizr脚本
优化:

unCSS 移除多余的CSS
CSSO 更深入地优化CSS
Critical 生成行内CSS
除了开发和优化过程,你可以使用gulp-jasmine写JavaScript单元测试,甚至使用gulp-rync直接部署dist文件到生产环境。

接下来是使用gulp更大型的一个项目:
假设我们的项目目录为:

项目目录

-- es6-gulp     项目的根目录
    -- app      前端业务代码
        -- js
            -- class 类目录
                -- index 
        -- css 
        -- views  模板目录
            -- error.ejs
            -- index.ejs (ejs)
    -- server   服务器代码
        -- 使用express来创建
    -- tasks    自动化构建工具
        -- util
             -- args

在server目录下,运行 express -e . cd install, 就可以初始化服务器的目录啦

到目前为止,我们已经创建了app(前端代码)、server(服务器代码)、tasks(前端构建)

创建并配置package.json

在根目录下,运行npm init命令,生成package.json文件

创建.babelrc

在根目录下,运行touch .babelrc, 生成babel的配置文件

创建gulp文件

在根目录下,运行touch gulpfile.babel.js, 生成gulp文件。

gulp官网上建议是gulpfile.js, 我们这里gulpfile.babel.js的原因是该文件我们使用es6的语法编写,如果是运行touch gulpfile.js, 会进行报错

截止现在,我们的准备工作已经做好了。

编写脚手架工具

创建tasks/utils/args.js文件,处理命令行内容

import yargs from 'yargs'

const args = yargs
		// 命令行中是否有production参数 区分是否是开发环境
		.options('production', {
			boolean: true,
			default: false,
			describe: ' '
		})
		// 是否监听文件
		.options('watch', {
			boolean: true,
			default: false,
			describe: ''
		})
		// will autoly create the log files
		.options('verbose',{
			boolean: true,
			default: false,
			describe: ''
		})
		.options('sourcemaps',{
			describe:'force the creation of sourcemap'
		})
		.options('port',{
			string: true,
			default: 8080,
			describe: "watch the port"
		})
		.argv

使用watch模式可以更高效的开发,监听到改动就自动执行任务,但是如果过程中遇到错误,gulp就会报错并终止watch模式,必须重新启动gulp,简直神烦!
利用gulp-plumber可以实现错误自启动,这样就能开心的在watch模式下开发且不用担心报错了。

gulp.task('scripts', ()=>{
	// gulp.src是打开目录的文件
	return gulp.src(['app/js/index.js'])
		//  处理错误逻辑,集中处理错误
		.pipe(plumber({
			errorHandle: function(){

			}
		}))
		// 对文件重新命名
		.pipe(named())
		// 进行编译, 借助webpack的功能gulpwebpack, webpack - module - loaders
		.pipe(gulpwebpack({
			module:{
				loaders:[
						{
							test: /\.js$/,
							loader: 'babel'
						}
						],
			}
		}), null, (err, stats) => {
			log('finished ')
		})
		// 编译完了放在哪里 gulp.dest()api 放在server里面
		.pipe(gulp.dest('server/publick/js'))
		// 混淆压缩,先拷贝一份重命名
		.pipe(rename({
			basename: 'cp',
			extname: '.min.js'
		}))
		.pipe(uglify(
				{
					compress:{properties: false},
					output:{'quoto_keys': true}
				}
				))
		.pipe(gulp.dest('server/public/js'))
		// 监听热更新
		.pipe(gulpif(args.watch, livereload()))
	
})

接下是监听编译模板

import gulp from 'gulp'
import gulpif from 'gulp-if'
import livereload from 'gulp-livereload'
import args from './util/args'

gulp.task('pages', ()=>{
	// 监听app 目录下的所有的ejs
	return gulp.src('app/**/*.ejs')
			// 拷贝到 server的目录下
			.pipe.dest('server')
			// 热更新
			.pipe(gulpif(args.watch, livereload()))
})

接下来是监听css文件

import gulp from 'gulp'
import gulpif from 'gulp-if'
import livereload from 'gulp-livereload'
import args from './util/args'

gulp.task('css', () => {
	return gulp.src('app/**/*.css')
			.pipe(gulp.dest('server/public'))
})

构建服务器脚本

import gulp from 'gulp'
import gulpif from 'gulp-if'
// 启动服务器
import liveserver from 'gulp-live-server'

import args from './util/args'

gulp.task('server',()=> {
	if(!args.watch) return cb()
	// 创建一个服务器
	var server = liveserver.new(['--harmony','server/bin/www'])
	server.start()
	
//	实现浏览器的自动刷新
	gulp.watch(['server/public/**/*.js', 'server/views/**/*.ejs'], function (file) {
		// 通知服务器做响应的改变
		server.notify.apply(server, [file])
	})
	
	gulp.watch(['server/routes/**/*.js','server/app.js'], function () {
		server.start.bind(server)()
	})
})

接下来,我们需要让所有的任务都自动化,app是我们前端的原始目录,如何让我们app下的文件发生了变化,自动写入到public的目录下面呢�

import gulp from 'gulp'
import gulpif from 'gulp-if'
import gutil from 'gulp-util'
import args from './util/args'

gulp.task('browser', (cb) => {
	if(!args.watch) return cb()
	// 第一个参数指定监听的目录,第二个参数指定执行的脚本
	gulp.watch('app/**/*.js', ['scripts'])
	gulp.watch('app/**/*.css', ['css'])
	gulp.watch('app/**/*.ejs', ['pages'])
	
})

同时,我们还需要要一个清空指定目录文件的脚本

import gulp from 'gulp'
import args from './util/args'
import def from 'del'

gulp.task('clean', ()=>{
	return del(['server/public','server/views'])
	
})

build.js把任务都关联起来,处理任务之间的先后顺序,server.js启动之前,pages.js和script.js必须先执行。

import gulp from 'gulp'
import gulpSequence from 'gulp-sequence'

// serve 一定要放在最后面
gulp.task('build', gulpSequence('clean','css','pages','scripts',['browser','serve']))

gulp scripts这个命令是执行名为scripts的gulp脚本,如果gulp 不指定脚本,则是执行default这个gulp脚本

import gulp from 'gulp'

gulp.task('default', ['build'])

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.