更新:谢谢你们的支持,最近折腾了一个博客官网出来,方便你们系统阅读,后续会有更多内容和更多优化,猛戳这里查看javascript
------ 如下是正文 ------css
这里分享过去一周高级前端进阶群里的学习汇总,天天会在群里给你们发一些资料一块儿学习,晚上会上传个人笔记,内容之前端基础、源码分析、面试题解为主,若是你上班没时间看,那周末能够好好学习了,弯道超车重在坚持。html
vue-router
默认使用hash 模式来模拟一个完整的 URL,当 URL 改变时,页面不会从新加载。vue
用路由的 history 模式替换hash模式,利用 history.pushState
API 来完成 URL 跳转而无须从新加载页面。java
const router = new VueRouter({
mode: 'history',
routes: [...]
})
复制代码
后台须要对路由进行配置react
理解 Javascript 执行上下文和执行栈(优)webpack
执行上下文总共有三种类型:全局执行上下文、函数执行上下文(只有在函数被调用的时候才会被建立)、Eval 函数执行上下文git
LIFO原则,引擎首次读取脚本时,会建立一个全局执行上下文并将其推入当前的执行栈。每当发生一个函数调用,引擎都会为该函数建立一个新的执行上下文并将其推到当前执行栈的顶端。函数运行完成后,其对应的执行上下文将会从执行栈中弹出,上下文控制权将移到当前执行栈的下一个执行上下文。github
执行上下文分两个阶段建立:1)建立阶段; 2)执行阶段
建立阶段发生三件事:1)肯定 this 的值,也被称为 This Binding。2)LexicalEnvironment(词法环境) 组件被建立。3)VariableEnvironment(变量环境) 组件被建立。
环境记录 还包含了一个 arguments
对象,该对象包含了索引和传递给函数的参数之间的映射以及传递给函数的参数的长度(数量)。
function foo(a, b) {
var c = a + b;
}
foo(2, 3);
// arguments 对象
Arguments: {0: 2, 1: 3, length: 2},
复制代码
在建立阶段,函数声明存储在环境中,而变量会被设置为 undefined
(在 var
的状况下)或保持未初始化(在 let
和 const
的状况下)。因此这就是为何能够在声明以前访问 var
定义的变量(尽管是 undefined
),但若是在声明以前访问 let
和 const
定义的变量就会提示引用错误的缘由。这就是所谓的变量提高。
若是 Javascript 引擎在源代码中声明的实际位置找不到 let
变量的值,那么将为其分配 undefined
值。
对于 Object
来讲,它是一个 Function
的实例,由于 Object instanceof Function // true
;对于 Function
来讲,它是 Object
的实例,由于 Function instanceof Object // true
,因此究竟是先有 Object
仍是先有 Function
呢?
一种理解:Object
基于 null
为模板(__proto__
),因此Object.prototype.__proto__ === null
new Object
建立一个对象,基于Object.prototype
为模板,因此new Object({}).__proto__ === Object.prototype
// Object
new Object().__proto__ === Object.prototype;
Object.__proto__ === Function.prototype;
Object.prototype.__proto__ === nulll;
// Function
Function.prototype === Function.__proto__;
Function.prototype.__proto__ === Object.prototype;
// Foo
new Foo().__proto__ === Foo.prototype;
Foo.prototype.__proto__ === Object.prototype;
Foo.__proto__ === Function.prototype
复制代码
ES6 系列之 Babel 是如何编译 Class 的(下)(优)
寄生组合式继承优势在于只调用一次 Parent 构造函数,避免了在 Parent.prototype 上面建立没必要要的、多余的属性,同时原型链还能保持不变。
ES6的super 关键字表示父类的构造函数,至关于 ES5 的 Parent.call(this)。因此子类只有调用 super 以后,才可使用 this 关键字
子类的 __proto__
属性,表示构造函数的继承,老是指向父类。
子类 prototype 属性的__proto__
属性,表示方法的继承,老是指向父类的 prototype 属性。
相比寄生组合式继承,ES6 的 class 多了一个 Object.setPrototypeOf(Child, Parent)
的步骤。
语法糖其实用的就是Object.create()
,第一个参数是新建立的对象,第二个参数表示要添加到新建立对象的属性,注意这里是给新建立的对象即返回值添加属性,而不是在新建立对象的原型对象上添加。
首先执行 _inherits(Child, Parent)
,创建 Child 和 Parent 的原型链关系,即Object.setPrototypeOf(Child.prototype, Parent.prototype)
和 Object.setPrototypeOf(Child, Parent)
。而后调用 Parent.call(this, name)
,根据 Parent 构造函数的返回值类型肯定子类构造函数 this 的初始值 _this。最终,根据子类构造函数,修改 _this 的值,而后返回该值。
场景:有a、b、c三个异步任务,要求必须先执行a,再执行b,最后执行c,且下一次任务必需要拿到上一次任务执行的结果,才能作操做。
解决方法一:使用then链式操做
//链式调用
a()
.then(function (data) {
return b(data)
})
.then(function (data) {
return c(data)
})
.then(function (data) {
console.log(data) // abc
})
复制代码
解决方法二:构建队列
// 构建队列
function queue(arr) {
let sequence = Promise.resolve()
arr.forEach(function (item) {
sequence = sequence.then(item)
})
return sequence
}
// 执行队列
queue([a, b, c])
.then(data => {
console.log(data) // abc
})
复制代码
解决方法三:使用async、await构建队列
async function queue(arr) {
let res = null
for (let promise of arr) {
res = await promise(res)
}
return await res
}
queue([a, b, c])
.then(data => {
console.log(data) // abc
})
复制代码
javascript 能够经过 window.location.hash来读取或改变 #
location.href += '#caper';
浏览器滚动到新的位置,但页面不会刷新,改变了浏览器记录,能够经过浏览器上一页
按钮回到原始的位置。
HTML 5新增onhashchange 事件,对于不支持onhashchange的浏览器,能够用setInterval监控location.hash的变化。
// 使用方法有三种
window.onhashchange = func;
<body onhashchange="func();"> window.addEventListener("hashchange", func, false); 复制代码
SyntheticEvent
采用了池的思想,从而达到节约内存,避免频繁的建立和销毁事件对象的目的。setState
)React都会将中间过程保存起来,留到最后面才flush掉。setState
还未最终被commit到DOM树上,这时须要把第一次按钮的结果先给flush掉并commit到DOM树,才可以保持一致性。ES6 系列之 Babel 是如何编译 Class 的(上)
一、ES5 的构造函数对应 ES6 的constructor 方法。
二、ES6定义的全部方法,都是不可枚举的。
三、在方法前加上 static 关键字不会被实例继承,是直接经过类来调用,这个是"静态方法"。
四、类和普通构造函数的一个主要区别是类必须使用 new 调用,不然会报错。
五、使用 get 和 set 关键字拦截属性默认行为
六、Babel 转换经过_classCallCheck检查类是不是经过 new 的方式调用
七、静态属性static bar = 'bar'
转换成Person.bar = 'bar'
八、Babel 生成了一个 _createClass 辅助函数,该函数传入三个参数,第一个是构造函数,在这个例子中也就是 Person,第二个是要添加到原型上的函数数组,第三个是要添加到构造函数自己的函数数组,也就是全部添加 static 关键字的函数。该函数的做用就是将函数数组中的方法添加到构造函数或者构造函数的原型中,最后返回这个构造函数。
使用Promises(优)
Promise 本质上是一个绑定了回调的对象,而不是将回调传进函数内部。
在 JavaScript 事件队列的当前运行完成以前,回调函数永远不会被调用
经过 .then 形式添加的回调函数,甚至都在异步操做完成以后才被添加的函数,都会被调用
若是想要在回调中获取上个 Promise 中的结果,上个 Promise 中必需要返回结果
在一个.catch
操做以后能够继续使用链式.then
操做
一般递归调用一个由异步函数组成的数组时至关于一个 Promise 链式:Promise.resolve().then(func1).then(func2)
传递到then中的函数被置入了一个微任务队列,而不是当即执行,这意味着它是在JavaScript事件队列的全部运行时结束了,事件队列被清空以后才开始执行
嵌套的 catch 仅捕捉在其以前同时还必须是其做用域的 failureres,而捕捉不到在其链式之外或者其嵌套域之外的 error。
一个好的经验法则是老是返回或终止 Promise 链,而且一旦你获得一个新的 Promise,返回它。
实现静态资源的按需加载,最大程度的减少首页加载模块体积和首屏加载时间,其提供的Code Splitting(代码分割)特性正是实现模块按需加载的关键方式。
将某些第三方基础框架模块(例如:moment、loadash)或者多个页面的公用模块(js、css)拆分出来独立打包加载,一般这些模块改动频率很低,将其与业务功能模块拆分出来并行加载,一方面能够最大限度的利用浏览器缓存,另外一方面也能够大大下降多页面系统的代码冗余度。
CommonsChunkPlugin
将公共基础库模块
单独打包到一个文件中
常用webpack的css-loader
来将css样式导入到js模块中,再使用style-loader
将css样式以<style>
标签的形式插入到页面当中,缺点是没法单独加载并缓存css样式文件,页面展示必须依赖于包含css样式的js模块,从而形成页面闪烁的不佳体验。
将js模块当中import的css模块提取出来,须要用到extract-text-webpack-plugin
使用React动态路由来按需加载react组件
scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
,以上规则中,只有 #
后面的 fragment
发生改变时,页面不会从新请求,其它参数变化,均会引发页面的从新请求,而在Js中偏偏还有事件 window.onhashchange
能监听到 fragment
的变化,因而就利用这个原理来达到一个修改局部内容的操做。#fragment
部分就是对应到Js中的 location.hash
的值。本人Github连接以下,欢迎各位Star
我是木易杨,网易高级前端工程师,跟着我每周重点攻克一个前端面试重难点。接下来让我带你走进高级前端的世界,在进阶的路上,共勉!
若是你想加群讨论每期面试知识点,公众号回复[加群]便可