前端20个灵魂拷问,彻底看懂你是中级前端工程师。感觉大家比较喜欢看这类文章,以后还会多一些。欢迎加入我们第二个前端交流群。目前二群人很多,所以二群开放啦~欢迎各位小姐姐一起加入~~(包括师傅小姐姐)我的微信号在最后。需要了解底层实现原理,借鉴他们的思路实现业务需求,实现性能优化,在这些知识的基础上学习新的东西~事半功倍为什么我会把这些问题放在中间,这篇文章会在介绍完这些问题后,后面会给出原因。问题是1.为什么要模块化,各种模块化标准的移动端React开源项目。从头开始搭建webpack脚手架,前端模块化是不可避免的,而且非常复杂。应用程序的所有内容不可能都在一个文件里~模块化过程:传统命令空间代码实现:index.js(function(w){w.a=1})(window)原理:全局对象window下,挂载该属性,则可以全局获取该属性的值。原则上一个js文件作为一个模块就是一个IIFE函数->require.js是基于AMD规范的。AMD规范采用异步方式加载模块,模块的加载不影响后面语句的执行。所有依赖该模块的语句都定义在一个回调函数中,回调函数只有在加载完成后才会运行。这里介绍使用require.js实现AMD规范的模块化:使用require.config()指定引用路径等,使用define()定义模块,使用require()加载模块。代码实现://简单的对象定义define({color:"black",size:"unisize"});//当你需要一些逻辑来做准备工作时,你可以这样定义:define(function(){//这里可以做一些准备工作return{color:"black",size:"unisize"}});//依赖一些模块定义自己的模块define(["./cart","./inventory"],function(cart,inventory){//通过返回对象定义自己的模块return{color:"blue",size:"large",addToCart:function(){inventory.decrement(this);cart.添加(这个);}}});->sea.js基于CMD规范。CMD是另一种js模块化解决方案。它与AMD非常相似。靠就近,延迟执行。这个规范其实是sea.js在推广的时候产生的。代码实现:define(function(require,exports,module){var$=require('jquery');exports.sayHello=function(){$('#hello').toggle('slow');};});seajs.config({别名:{'jquery':'http://modules.seajs.org/jquery/1.7.2/jquery.js'}});seajs.use(['./hello','jquery'],function(hello,$){$('#beautiful-sea').click(hello.sayHello);});原理:在最上面导入sea.js的源码文件,在运行时转换代码,在开头指定入口文件,根据入口文件定义的数组(或者导入的数组)继续查找对应的依赖依赖)。->commonJsNode.js原生环境支持commonJs模块化规范。首先简单实现一个require:functionrequire(/*...*/){constmodule={exports:{}};((module,exports)=>{//模块代码在这里。在这个例子中,定义一个函数。//此时,exports不再是module.exports的快捷方式,//这个模块仍然会导出一个空的default对象。//当代码运行到这里时,exports不再是对module.exports的引用,//当前模块仍将导出一个Empty对象(就像上面声明的默认对象)module.exports=someFunc;//此时,模块现在将导出someFunc,而不是//默认对象。//当代码运行到这一点时,当前模块将导出someFunc而不是默认对象})(module,module.exports);returnmodule.exports;}require相当于将引用的模块复制到当前模块export和module.exports中,暴露接口export与module.exports的区别:export是对module.exports的引用。作为一个引用,如果我们修改它的值,实际上是修改了它对应的引用对象的值。commonJS同步加载模块。在服务器端,模块文件存放在本地磁盘上,读取速度很快,这样做没有问题。但在浏览器端,限于网络原因,更合理的方案是使用异步加载。简单总结就是exports->{}<-module.exports同时指向一个对象->ES6模块化是目前最常用的模块化规范:ES6模块化规范原生浏览器环境和Node.js环境不识别,但要使用它,必须使用babel将其编译成浏览器或Node.js可以识别的代码。为了节省时间,会有自动一键打包编译代码的工具。-webpack.ES6最强大的部分,它不仅支持静态验证,可以同步和异步加载,而且统一了前后端的模块化规范。Node和传统前端都可以使用这套规范。ES6模块和CommonJS模块的区别CommonJS模块输出一个值的副本,而ES6模块输出一个值的引用(第一次require一个不同路径的文件,会在require.cache中保存一个缓存,并且下次直接从缓存中读取)CommonJS模块在运行时加载,ES6模块是编译时输出接口。CommonJS加载的是一个对象(即module.exports属性),只有在脚本运行完毕后才会生成。ES6模块不是对象。它的对外接口只是一个静态定义,会在静态代码分析阶段生成。这就是TypeScript支持静态类型检查的原因,因为它使用了ES6模块化的解决方案。特别提醒:现在Node也可以如果你使用ES6模块化方案,可以用experimental看commonJs的index.jsconsta=require('./test1.js');constfunc=require('./test2');a.a=2;console.log(a.a,'test1');func()test2.jsconsta=require('./test1')module.exports=function(){console.log(a.a,'test2')}test1.jsleta={a:1}module.exports=a运行nodeindex.js看ES6的输出结果//math.jsexportletval=1exportfunctionadd(){val++}//test.jsimport{val,add}from'./math.js'console.log(val)//1add()console.log(val)//2ReactVue框架实现基本原理和设计思路~设计思路和基本原理:1.由传统的直接DOM操作改为数据驱动的方式来间接代替我们操作DOM。2、每次数据发生变化需要重新渲染时,只对DOM有差异的那部分进行操作。--diff算法有一系列的生命周期对,实际上是一种约定,在代码执行顺序中给出特定函数名的一部分来执行。常见的diff算法是比较上次的虚拟dom和更新后的虚拟dom,然后对真实dom进行patch,或者直接比较真实dom和虚拟dom。从头开始编写React框架。本文附带源代码。从零开始,实现了一个React框架前端需要理解的通用算法和数据结构。常见的数据结构:栈、队列、树、图、数组、单链表、双链表、图等……冒泡排序比较相邻的两个元素,如果前一个大于后一个,则交换位置。最后一个元素应该是第一轮中最大的一个。按照步骤1的方法比较两个相邻的元素。此时由于最后一个元素已经是最大的,所以不需要再比较最后一个元素functionbubble_sort(arr){for(vari=0;i
