题记

内容来源

文章内容输出来源:拉勾教育大前端高薪训练营一期

当前阶段的学习心得

我算是一个工作年限比较久的前端了,刚毕业时从事销售工作,后来在2015年想要从事脚踏实地的工作,便选择转行互联网。当时转行时我和我同学选择了不同的道路,她选择参加ios培训而我选择自学。刚入行时因为没有经验,所以拿着月薪1.5K的薪水做着很繁杂的工作,前端、php、测试、产品、需求都ok。但没有一个是我最擅长。忙碌的生活让我逐渐意识到我或许走的不会很长久,我在2017年惊醒便放弃了天津的2K薪资来到了北京。北京公司是个小公司,倒是成长很快但技术方面没有什么提升。在2018年进入目前这家公司之后,因为机缘巧合的原因带了小团队,但我越发恐慌,我好想并不能带给她们什么,也不能带领她们走向某一个方向,当我觉得自己’技’不配位的时候恰巧看到了拉勾的宣传,莫名的缘分让我成为了拉勾教育大前端高薪训练营一期的学员。

成为学员之后,刚开始还蛮焦虑的。早已习惯懒散的生活和规律的生活因为加入了拉勾而变得异常充实和快乐,每次看视频、听直播、看群内分享的时候就可以感知到原来自己太局限,我一个工作5年经验的人竟然还在做初级工程师的工作。以上种种让我很羡慕班里那些工作一年的小伙伴,她们的前途一片光明。虽然我也是。

从加入大前端高薪训练营到现在快3个月了,我对拉勾的课程质量绝对是非常满意了。之前也在其他网站陆续买过一些课程,从我的认知中拉勾是最全面的、最细致的一家。很多工作中我们不曾深入了解的工具、概念、实践,老师都会在课程中带领我们实践一次,真乃实践出真知呀。课程体系划分合理、课程内容充实且全面、老师知识储备超级丰富、讲解够细致,我想一定是经过了很长时间的打磨才会有如此多的好评。

授课的主讲老师是汪磊,我github唯一关注的粉丝(其实说明我太菜了),我这几年的工作经历也算见过一些大场面,但还是被汪老师的博学多识、幽默帅气所吸引。之前还特意关注过汪老师的微博,发现汪老师一直从事互联网教育培训方向,想来他的经验、学识、学习能力之所以如此优秀也是有原因的。持续深耕方可有今天的细致与宽广。

我们的班主任,一个细心且温柔且负责任的美少女,其实很多时候我都要作业要不明天再写吧(原谅我经常想偷懒),但老师常常会按时敲门来督促我们学习。我有想过,如果没人监督没人督促,我可能1个月都无法坚持。我的班主任总是晚上2点睡早晨6-7点起床,或许是我太不给力了。这些都是很细碎的点,但也正因为有她的陪伴、支持、鼓励,我才发现我现在可以逐渐摆脱之前不好的习惯,如果每天不学习我甚至会觉得她能感知到。现在真的变成了每天都要学习、每天都要记笔记的好习惯。

我们的助教老师熊熊老师和小北老师,常常在深夜或很早的时候就会回复我们的问题,每次的作业批改绝对是一丝不苟,我为什么会有这样的感触?因为有一次我的作业漏写了一道题老师还很认真的评价及解答_

总体来说,对主讲老师汪磊,心存敬意,因为尊敬也让我更加认真的对待每一节视频、每一次直播。对班主任,心存感恩,希望自己更自律可以让她早点休息。对助教老师心存感激与敬佩,他们对待工作的态度也是我这个职场老人应该学习的。

最后,再来说一下故事开头中我那位女同学的发展之路,在我持续3年拿月薪2K的时候,她早已月薪20K。其实我想说,成长有很多条路,真正走过(浪费)了这几年之后我才发现我在最开始入行的时候应该选择最快捷的那条路。不过现在的我已经在路上了,希望不会太晚。同时也希望各位小伙伴可以找到适合自己的学习方法。

以下这篇博客内容会比较多,建议大家重点关注前言、CommonJs、ES Module即可。后续还会有系列文章,欢迎大家多多捧场~

前言

1.1 模块化是什么?

模块化是一种思想,是一种解决问题的思路。
随着业务的发展我们的系统可能越来越复杂,那我们如何保证在复杂系统中代码可以方便维护、功能可以复用呢?模块化思想可以解决这个问题呀,可以将我们的复杂系统分解为可管理的模块、每个模块完成一个特定的子功能,所有的模块按某种方法组装起来,成为一个整体,完成整个系统所要求的功能。
我们

模块化只是一种思想

1.2 为什么会有模块化?

1.2.1 没有模块化,前端代码会怎样

  • 变量和方法不易维护,容易污染全局作用域。如要遵循一定的命名约定才不会产生重复命名
  • 我们加载资源的是通过script标签从上至下引入,还要注意引入时的依赖关系和前后顺序,如果先后顺序不对会无法启动项目
  • 大型项目资源越加难以维护、多人合作的情况下资源的引入会让人崩溃
    那么既然没有模块化会存在以上问题,我们应该如何解决呢?

1.2.2 模块化的演变

早期在没有工具和规范的情况下对模块化的落地方式:

  • 基于文件划分模块:早期的js文件,每个文件都是一个模块,但他们事实上都在全局工作。模块外部可以访问,会导致全局污染,并且会存在命名冲突
  • 每个模块只暴露一个全局对象,所有模块成员都挂载到这个全局对象上。缺点:没有私有空间,外部可以修改内部
  • 使用立即执行函数表达式IIFE,为模块提供私有空间

以上模块化方式都是通过scrip手动t引入模块。模块的引入与否取决于人也就是不受代码控制,如果我们引入了模块但未使用、使用了但模块被删除等都会对程序产生影响。
如何通过代码自动加载模块?需要一个模块化标准和自动加载模块的基础库

1.3 模块化的实现有哪几种

CommonJs,AMD,CMD,ES Module这四种

CommonJs

首先登场的是commonJS,commonJS是一套规范、它约定实现模块化要遵守的规范,它是nodejs在服务端遵守的规范。

2.1 概述

简单的描述就是:

  • 约定每个文件就是一个模块。
  • 每个模块都有单独的作用域,文件内的变量、函数、类都是私有的,对其他文件不可见。
  • 通过module.exports导出成员,
  • 通过require引入模块。

2.2 module对象

每个文件就是一个模块,每个模块都有一个module对象,代表当前模块。它有以下属性:

  • module.id 模块的识别符,通常是带有绝对路径的模块文件名。
  • module.filename 模块的文件名,带有绝对路径。
  • module.loaded 返回一个布尔值,表示模块是否已经完成加载。
  • module.parent 返回一个对象,表示调用该模块的模块。
  • module.children返回一个数组,表示该模块要用到的其他模块。

module.exports 表示模块对外输出的值。
我们新建一个文件aa.js,此文件内容为

console.log(module)

然后执行node aa.js 可以看到打印的结果如下:

2.3 exports 导出对象

2.3.1 module.exports

我们在上一节也说过module对象下有一个exports属性,表示模块对外输出的值,这样别的模块就可以引入此值。它输出的是一个对象。

// 创建文件aa.jslet a = '模块内的变量a'
function add(x,y){console.log('模块内的求和函数')return x+y
}
module.exports.a = a
module.exports.add = add// 或者简写为
module.exports = {a,add:add,d: function(x,y){return x}
}

利用 module.exports.name = 值,可以导出,导入的时候是一个利用moduleName.name即可接收

// 创建文件bb.js,导入aa.jslet moduleAA = require('./aa.js')
console.log(moduleAA.a)
console.log(moduleAA.add(3,4))

执行node bb可看到效果如下:

我发觉,如果是变量常量对象(不包括函数)这一类型的,都需要先定义再导出,函数可以先定义再导出也可以导出的时候直接定义。如下:

module.exports.c = function(x,y){return x+y
}

2.3.2 exports

为了方便,Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部都有了一行隐形的命令:let exports = module.exports。 所以我们在对外输出或暴露的时候就看可以利用exports.name = xx进行暴露。
上述示例中暴露全可以简写为:

let a = '模块内的变量a'
function add(x,y){console.log('模块内的求和函数')return x+y
}
exports.a = a
exports.add = add
exports.c = function(x,y){return x+y
}

简单理解exports可以说与module.exports指向同一内存地址,属于浅拷贝过程,任何一方的修改都会导致另一方可以感知到变化。最终导出的时候将内存地址里的值导出即可。

但有一点需要注意,我们不能使用直接赋值的形式,这样会切断exports的指向。
如下:

exports = {name: '呼呼',age: 18
}
或
exports = function(x){return x
}

此时已经切断了两者的联系,并不能被导出。真正被导出的还是module.exports指向的内存地址。

所以我们建议使用module.exports而不用exports,避免出错

2.4 require

2.4.1 require 概述

require命令的基本功能是,读入并执行一个JavaScript文件,然后返回该模块的exports对象。如果没有发现指定模块,会报错。

2.4.2 加载规则

默认加载.js 文件,所以我们在加载模块时可以省略.js后缀

根据参数的不同格式,require命令去不同路径寻找模块文件。

  • 如果参数字符串以“/”开头,则表示加载的是一个位于绝对路径的模块文件。比如,require(’/home/marco/foo.js’)将加载/home/marco/foo.js。

  • 如果参数字符串以“./”开头,则表示加载的是一个位于相对路径(跟当前执行脚本的位置相比)的模块文件。比如,require(’./circle’)将加载当前脚本同一目录的circle.js。

  • 如果参数字符串不以“./“或”/“开头,则表示加载的是一个默认提供的核心模块(位于Node的系统安装目录中),或者一个位于各级node_modules目录的已安装模块(全局安装或局部安装)。

  • 如果参数字符串不以“./“或”/“开头,而且是一个路径,比如require(‘example-module/path/to/file’),则将先找到example-module的位置,然后再以它为参数,找到后续路径。

  • 如果指定的模块文件没有发现,Node会尝试为文件名添加.js、.json、.node后,再去搜索。.js件会以文本格式的JavaScript脚本文件解析,.json文件会以JSON格式的文本文件解析,.node文件会以编译后的二进制文件解析。

  • 如果想得到require命令加载的确切文件名,使用require.resolve()方法。

我们之前看module输出的时候有一个path属性,表示模块加载顺序。
如果我们在bb.js中输出module会发现path的顺序为:
paths: [
‘D:\webStudy\vue-router\node_modules’,
‘D:\webStudy\node_modules’,
‘D:\node_modules’
]
假设我们引入了一个三方模块require(‘vue’),则它的查找顺序为先从"D:/webStudy/vue-router/node_modules"中查找,如果找不到向上一层到 “D:/webStudy/node_modules” 查找,如果还找不到则会从’D:\node_modules’查找。这样设计的目的是,使得不同的模块可以将所依赖的模块本地化。

2.4.3 模块缓存

第一次加载某个模块时,Node会缓存该模块。以后再加载该模块,就直接从缓存取出该模块的module.exports属性。
所有缓存的模块保存在require.cache之中,如果想删除模块的缓存,可以像下面这样写。

// 删除指定模块的缓存
delete require.cache[moduleName];// 删除所有模块的缓存
Object.keys(require.cache).forEach(function(key) {delete require.cache[key];
})

注意,缓存是根据绝对路径识别模块的,如果同样的模块名,但是保存在不同的路径,require命令还是会重新加载该模块。

2.4.4 模块加载机制

假设我们的b引入了a暴露的数据或函数,模块内部的变化就影响不到这个值。可以理解为两者是深拷贝,也就是相互独立。

2.4.5 require的内部处理流程

  1. 检查 Module._cache,是否缓存之中有指定模块
  2. 如果缓存之中没有,就创建一个新的Module实例
  3. 将它保存到缓存
  4. 使用 module.load() 加载指定的模块文件,读取文件内容之后,使用 module.compile() 执行文件代码
  5. 如果加载/解析过程报错,就从缓存删除该模块
  6. 返回该模块的 module.exports

所以我们会发现一个模块被多次引入并不会被执行多次。

2.5 关于最后

commonjs是一个文件就是一个模块,每个模块是如何做到作用域相互独立的呢?事实上每个文件都是很一个函数,我们的代码逻辑都是在函数内部。
如何验证呢?
我们可以打印arguments,只有函数内部才有的参数列表,如下图:

这个函数有5个参数:

(function (exports, require,  module,__filename, __dirname) {});
  • exports初始值是{},用来存放我们要导出的变量或函数,是module.exports 的一个引用
  • require 是一个函数
  • module 代表当前模块
  • __filename 此文件的路径+文件名.扩展
  • __dirname:不含文件名,所在路径

commonJS是以同步的方式加载模块,node是在启动时加载模块,在执行过程中不会再次进行加载。但如果在浏览器端使用commonJS、页面加载都会导致大量的同步请求出现,性能比较低下。故而为浏览器重新设计了一个规范AMD,也就是异步模块定义规范,其中require.js库实现了AMD。

AMD

AMD(Asynchronous Module Definition)异步模块定义,它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
主要作用有2个:

  • 实现js文件的异步加载,避免网页失去响应;
  • 管理模块之间的依赖性,便于代码的编写和维护。

3.1 定义模块

define(id?, dependencies?, factory);

  • id:可选参数,用来定义模块的标识,如果没有提供该参数,则默认使用文件名
  • dependencies:是一个当前模块依赖的模块名称数组,可以为空
  • factory:工厂方法,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值
  // 定义模块math.jsdefine(function (){var add = function (x,y){return x+y;};return {add: add};});// main.js引入math模块require(['math'], function (math){alert(math.add(1,1));});

3.2 引入模块

  require(['jquery', 'underscore','backbone'],function ($, _, Backbone){// some code here});

require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是[‘moduleA’, ‘moduleB’, ‘moduleC’],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。

require()异步加载moduleA,moduleB和moduleC,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。

3.3 AMD缺点

  • 使用起来比较复杂,模块定义和导出需要指定的语法来实现
  • 模块js文件请求频繁:如果我们将模块拆分的比较独立会导致依赖的js变多,请求变多

CMD

CMD(Common Module Definition)通用模块定义,对应SeaJS,是阿里玉伯团队首先提出的概念和设计。跟requireJS解决同样问题,只是运行机制不同。

4.1 定义模块

define(id?, deps?, factory)

  • id,模块名称可省略。省略采用文件名作为模块名
  • deps,依赖文件
  • factory:function(require, exports, module),有三个参数
    • require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口
    • exports 是一个对象,用来向外提供模块接口
    • module 是一个对象,上面存储了与当前模块相关联的一些属性和方法
define(function(require, exports, module) {// 通过 require 引入依赖var otherModule = require('./otherModule');// 通过 exports 对外提供接口exports.myModule = function () {};// 或者通过 module.exports 提供整个接口module.exports = function () {};
})

4.2 引入模块

define(function(require, exports, module) {
// 通过 require 引入依赖
var math = require(‘math’);
return math.add(1,2)

})

AMD与CMD的对比

- AMD CMD
原理 define(id ?,dependencies ?,factory)定义了一个单独的函数“define”。id为要定义的模块。依赖通过dependencies传入factory是一个工厂参数的对象,指定模块的导出值。 CMD规范与AMD类似,并尽量保持简单,define(id?, deps?, function(require, exports, module){})
优点 特别适用于浏览器环境的异步加载 ,且可以并行加载。依赖前置,提前执行。 定义模块时就能清楚的声明所要依赖的模块 依赖就近,延迟执行。 按需加载,需要用到时再require
缺点 开发成本较高,模块定义方式的语义交为难理解,不是很符合通过的模块化思维方式 依赖SPM打包,模块的加载主观逻辑交重。
体现 require.js sea.js

ES Module

在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。

5.1 ES Module 简介

通过给页面中的script添加一个type=module属性,就可以以ES Module的标准来执行该模块了。

ES Module特性:

  • 自动采用严格模式,无论文件头是否拥有use strict
    <script type="module">console.log(this) //undefined</script>
  • 每个module都运行在独立的私有作用域中,可以解决全局作用域污染问题
    <script type="module">var foo = 'lm'console.log(foo) // 运行结果:lm</script><script type="module">console.log(foo) //运行结果:Uncaught ReferenceError: foo is not defined</script>
  • ES Module 是通过cors请求外部js模块的,如果想不产生跨域需要外部资源支持
    <script type="module" src="https://lib.baidu.com/jquery/2.0.0/jquery.min.js"></script>//也就是需要我们引入网址支持跨域访问,百度不支持跨域,所以引入外部资源时会报跨域错误
  • ES Module 中script会自动延迟执行脚本、等待网页渲染完成后再自动加载/执行脚本

5.2 export 命令

ES Module主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。下面是一个 JS 文件,里面使用export命令输出变量。

  • 导出变量
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;或者
let firstName = 'Michael'
let lastName = 'Jackson'
let year = 1958
export {firstName, // es6新语法,对象中key与value相同时可简写即key:key=》keylastName,year
}
  • 导出函数
function f1(){console.log('f1')
}function f1(){console.log('f2')
}
export {f1,f2}
  • 导出时重命名
    我们在导出时默认的名字就是变量名、函数名,但假设我们使用了as进行重命名,使用时就需要使用新名字才可访问。可以导出多次
function f1(){console.log('f1')
}function f1(){console.log('f2')
}export {f1 as add,f2 as hh,f2 as hell
}

需要注意的有2点:

  1. 无论是变量、常量、函数、class等,导出的方式有两种,

    • export 声明语句
    • export {变量名称/常量名称/函数名称/class名称}
      举例:
    
    导出方式一:
    export let firstName = 'Michael'
    export lastName = 'Jackson'
    export function f1(){console.log('f1')
    }
    或者采用导出方式二let firstName = 'Michael'
    let lastName = 'Jackson'
    function f1(){console.log('f1')
    }
    export {firstName,lastName,f1
    }

    但如果我们先定义变量、常量、函数、class,然后再export 变量名/常量名/函数名/class名则会报错,原因在于export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。

    let firstName = 'Michael'
    export firstName
    结果会报错
    
  2. export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错。

5.3 import 命令

使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

  • import命令接受一对大括号,括号内是要接受的变量名,但变量名要和导出时的名称一致
import { firstName, lastName } from './profile.js';
  • 如果导入后想要重命名可以使用 as
import { firstName as xing } from './index.js'
  • import命令输入的变量都是只读的,不允许改写 但如果是对象改写属性是ok的。
import {a} from './xxx.js'a = {}; // Syntax Error : 'a' is read-only;
a.foo = 'hello'; // 合法操作
  • from后可以是绝对路径、相对路径、三方模块,.js可以省略

  • import命令不能出现在块级作用域中,只能出现在模块顶层就行。

function foo() {import { aa } from  './aa.js' //报错
}
foo()
  • import命令具有提升效果,会提升到整个模块的头部,首先执行
console.log(aa)
import { aa } from  './aa.js'
  • 如果多次重复执行同一句import语句,那么只会执行一次,而不会执行多次
import { aa } from  './aa.js'
import { aa } from  './aa.js'
但如果是同一个模块中的不同输入,是都会被执行的。
import { aa } from  './aa.js'
import { bb } from  './aa.js'
等同于
import { aa, bb } from  './aa.js'
  • 加载整个模块 用 *
假设aa.js中有aa和bb两个方法导出,可以逐一列出导入也可以利用*
import * as module from  './aa.js'

5.4 export default命令与import如何使用

从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。

为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

// a.js
export default function(){console.log('a')
}
//b.js
加载该模块时,import命令可以为该匿名函数指定任意名字
import a from './a.js'
  • 如果我们使用了export default 导出,则应该配套的使用方式是 不用大括号且需要起个名字。import a from ‘./a.js’
  • 用export default 可以导出非匿名函数,等同于匿名函数
  • 一个模块只能有一个默认输出,因此export default命令只能使用一次
  • 如果想在一条import语句中,同时输入默认方法和其他接口,参考如下:
import _, { each, forEach } from 'lodash';

5.5 export 与 import 的复合写法

如果在一个模块之中,先输入后输出同一个模块,import语句可以与export语句写在一起。

export { foo, bar } from ‘my_module’;

// 可以简单理解为
import { foo, bar } from ‘my_module’;
export { foo, bar };

总结

目前的最佳实践为:
服务器开发遵守 commonjs 规范
浏览器开发遵守 es module

AMD\CMD不再是主流,可以不关注。

  • commonjs主要是exports或module.exports导出,require引入,但引入的时候是一个对象。let moduleAA = require(’./aa.js’)
  • es module 如果采用export导出,引入方式为import {name} from ‘./a’
  • es module 如果采export default 导出, 引入方式为import name from ‘./a’

因为内容比较多,所以后面还会再有一篇博客进行对比分析、外加讲解如何兼容使用。欢迎继续关注,也欢迎有不同意见的小伙伴提出建议。微信lm13821687665

前端模块化,有这一篇就够了(上)相关推荐

  1. 前端SEO优化 看这篇就够了

    转载 https://blog.csdn.net/yuyuking/article/details/89374794

  2. 华为2020校招笔试编程题 看这篇就够了(上)

    背景 近日一位在华为的师兄整理了一份内部的提纲给我们,想着以后肯定不会去华为,于是乎分享给大家,看看菊花厂今年的笔试题目是什么样子的. 编程题范围 这好像来自一个华为内部的文档,据说今年华为内部也在进 ...

  3. api网关选型_如何轻松打造百亿流量API网关?看这一篇就够了(下)

    如何轻松打造百亿流量API网关?看这一篇就够了(上) 上篇整体描述了网关的背景,涉及职能.分类.定位环节,本篇进入本文的重点,将会具体谈下百亿级流量API网关的演进过程. 准备好瓜子花生小板凳开始积累 ...

  4. 「 Java开发规范 」10人小团队Java开发规范参考这篇就够了

    <菜鸟程序员成长计划>之团队高效合作[开发规范篇] 1.「 Java开发规范 」10人小团队Java开发规范参考这篇就够了! 2.「 前端开发规范 」10人小团队前端开发规范参考这篇就够了 ...

  5. docker 删除所有镜像_关于 Docker 镜像的操作,看完这篇就够啦 !(下)| 文末福利...

    紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌 ...

  6. 前端模块化开发学习之gulpbrowserify篇

     随着web应用的发展,前端的比重占得越来越多,编写代码从而也越来越复杂.而通常我们需要将不同功能或者不同模块的代码分开写,最后在html中一起加载,这样做是可以的,但是当你需要进行维护或者是二次开发 ...

  7. 前端linux基础,这一篇就够了

    前端linux基础,这一篇就够了 退出当前操作 清理命令窗口 关闭命令窗口 创建文件 创建文件夹 删除文件 删除文件夹 重命名文件 发起请求(curl) 切换工作目录 查看当前完整路径 查看当前目录下 ...

  8. 前端需要了解的计算机网络知识, 这一篇就够了!(图文并茂,万字长文!)

    作者:lio-mengxiang 原文链接:https://juejin.im/post/5e51febde51d4526c932b390 本文主要目的也是为了非科班前端补充计算机科班基础知识,比如你 ...

  9. 前端开发工程化探讨--基础篇(长文)

    转载自UC资深前端工程师张云龙的github 喂喂喂,那个切图的,把页面写好就发给研发工程师套模板吧. 你好,切图仔. 不知道你的团队如何定义前端开发,据我所知,时至今日仍然有很多团队会把前端开发归类 ...

最新文章

  1. TinyMind邀你写诗!100小时GPU,等你来领取!
  2. 重写selenium 的 click()操作,使得脚本更稳定
  3. faiss(1):简介 安装 与 原理
  4. 初步学习pg_control文件之八
  5. [2014.3.23]cse::lab2::partD 简明攻略
  6. LeetCode 22. Generate Parentheses
  7. 对*.ini文件的增删改查
  8. 【大厂面试必备系列】滑动窗口协议
  9. 最全办公室租赁技巧,让你找到心仪的办公室
  10. 微软 Dynamics CRM 开发学习01
  11. 360篡改Edge、Google浏览器主页的应对方法
  12. iPhone SE2外观酷似iPhone 8,香吗?
  13. 基于51单片机智能可控洗衣机控制系统设计
  14. 网上店铺怎样给宝贝定价
  15. Libev源码分析05:Libev中的绝对时间定时器
  16. 第18章异步编程-bloc-自定义状态管理示例-BlocProvider
  17. 网上书城项目分析及前端页面
  18. WEB渗透SQL注入【3】[access数据库注入](2)
  19. Python源码学习(三)
  20. 如何对身份证号上的信息进行提取

热门文章

  1. Maven依赖版本号不生效
  2. cf反恐穿越前线java,穿越前线反恐使命
  3. leveldb:Arena浅析
  4. 未来世界,已经不在遥远
  5. php添加本地搜索,十分钟,在本地搭建一个搜索引擎
  6. 计算机主机寿命多长,一般电脑的寿命是多久
  7. php的核心架构如下图,thinksns 核心架构及目录结构
  8. 【人脸识别】基于dlib库实现人脸特征值提取
  9. 删除打开方式中的选项
  10. Legacy与UEFI