ES5定义类以函数形式, 以prototype来实现继承
ES6以class形式定义类, 以extend形式继承css
ES6 提供的一种异步编程解决方案, Generator 函数是一个状态机,封装了多个内部状态。java
function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; } var hw = helloWorldGenerator();
调用后返回指向内部状态的指针, 调用next()才会移向下一个状态, 参数:python
hw.next() // { value: 'hello', done: false } hw.next() // { value: 'world', done: false } hw.next() // { value: 'ending', done: true } hw.next() // { value: undefined, done: true }
var myPromise = new Promise((resolve, reject) => { // 须要执行的代码 ... if (/* 异步执行成功 */) { resolve(value) } else if (/* 异步执行失败 */) { reject(error) } }) myPromise.then((value) => { // 成功后调用, 使用value值 }, (error) => { // 失败后调用, 获取错误信息error })
优势: 解决回调地狱, 对异步任务写法更标准化与简洁化
缺点: 首先,没法取消Promise,一旦新建它就会当即执行,没法中途取消; 其次,若是不设置回调函数,Promise内部抛出的错误,不会反应到外部; 第三,当处于pending状态时,没法得知目前进展到哪个阶段(刚刚开始仍是即将完成).
极简版promise封装:jquery
function promise () { this.msg = '' // 存放value和error this.status = 'pending' var that = this var process = arguments[0] process (function () { that.status = 'fulfilled' that.msg = arguments[0] }, function () { that.status = 'rejected' that.msg = arguments[0] }) return this } promise.prototype.then = function () { if (this.status === 'fulfilled') { arguments[0](this.msg) } else if (this.status === 'rejected' && arguments[1]) { arguments[1](this.msg) } }
又称发布-订阅模式, 举例子说明.
实现: 发布者管理订阅者队列, 并有新消息推送功能. 订阅者仅关注更新就行web
Function.prototype.bind = function () { // 保存原函数 var self = this // 取出第一个参数做为上下文, 至关于[].shift.call(arguments) var context = Array.prototype.shift.call(arguments) // 取剩余的参数做为arg; 由于arguments是伪数组, 因此要转化为数组才能使用数组方法 var arg = Array.prototype.slice.call(arguments) // 返回一个新函数 return function () { // 绑定上下文并传参 self.apply(context, Array.prototype.concat.call(arg, Array.prototype.slice.call(arguments))) } }
function Father () {} function Child () {} // 1\. 原型继承 Child.prototype = new Father() // 2\. 构造继承 function Child (name) { Father.call(this, name) } // 3\. 组合继承 function Child (name) { Father.call(this, name) } Child.prototype = new Father() // 4\. 寄生继承 function cloneObj (o) { var clone = object.create(o) clone.sayName = ... return clone } // 5\. 寄生组合继承 // 6\. ES6 class extend继承
四个小圆点一直旋转算法
// 父标签 animation: antRotate 1.2s infinite linear; // 子标签 animation: antSpin 1s infinite linear; @keyframe antSpin { to { opacity: 1 } } @keyframe antRotate { to { transform: rotate(405) } } // animation-delay: 逐个延迟0.4s
1**: 服务器收到请求, 需请求者进一步操做
2**: 请求成功
3**: 重定向, 资源被转移到其余URL了
4**: 客户端错误, 请求语法错误或没有找到相应资源
5**: 服务端错误, server error
304: Not Modified. 指定日期后未修改, 不返回资源typescript
变量对象,是执行上下文中的一部分,能够抽象为一种 数据做用域,其实也能够理解为就是一个简单的对象,它存储着该执行上下文中的全部 变量和函数声明(不包含函数表达式)。
活动对象 (AO): 当变量对象所处的上下文为 active EC 时,称为活动对象。编程
Generator函数的语法糖,将*改为async,将yield换成await。
是对Generator函数的改进, 返回promise。
异步写法同步化,遇到await先返回,执行完异步再执行接下来的.
内置执行器, 无需next()json
算法:
解决具体问题所须要的解决方法。执行效率最快的最优算法。时间复杂度。输入,输出,有穷性,肯定性,可行性。冒泡排序,二叉树遍历,最长回文,二分查找,指针,链表等,堆栈,队列等。力扣,codewar,算法导论。
数据结构:
逻辑结构:集合、线性、树形、图形结构
物理结构:顺序、链式存储结构数组
function jsonp ({url, param, callback}) { return new Promise((resolve, reject) => { var script = document.createElement('script') window.callback = function (data) { resolve(data) document.body.removeChild('script') } var param = {...param, callback} var arr = [] for (let key in param) { arr.push(`${key}=${param[key]}`) } script.src = `${url}?${arr.join('&')}` document.body.appendChild(script) }) }
// for循环实现 Array.prototype.myMap = function () { var arr = this var [fn, thisValue] = Array.prototype.slice.call(arguments) var result = [] for (var i = 0; i < arr.length; i++) { result.push(fn.call(thisValue, arr[i], i, arr)) } return result } var arr0 = [1, 2, 3] console.log(arr0.myMap(v => v + 1)) // forEach实现(reduce相似) Array.prototype.myMap = function (fn, thisValue) { var result = [] this.forEach((v, i, arr) => { result.push(fn.call(thisValue, v, i, arr)) }) return result } var arr0 = [1, 2, 3] console.log(arr0.myMap(v => v + 1))
<body> <button id="other">反选</button> <input type="checkbox" id="all" />全选 <input type="checkbox" class="check" />1 <input type="checkbox" class="check" />2 <input type="checkbox" class="check" />3 <script> var checkbox = document.getElementsByClassName('check') var checkAll = document.getElementById('all') var checkOther = document.getElementById('other') checkAll.onclick = function() { var flag = true for (var i = 0; i < checkbox.length; i++) { if (!checkbox[i].checked) flag = false } if (flag) { for (var i = 0; i < checkbox.length; i++) { checkbox[i].checked = false } } else { for (var i = 0; i < checkbox.length; i++) { checkbox[i].checked = true } } } checkOther.onclick = function() { for (var i = 0; i < checkbox.length; i++) { checkbox[i].checked = !checkbox[i].checked } } </script> </body>
在js里,继承机制是原型继承。继承的起点是 对象的原型(Object prototype)。
一切皆为对象,只要是对象,就会有 proto 属性,该属性存储了指向其构造的指针。
Object prototype也是对象,其 proto 指向null。
对象分为两种:函数对象和普通对象,只有函数对象拥有『原型』对象(prototype)。
prototype的本质是普通对象。
Function prototype比较特殊,是没有prototype的函数对象。
new操做获得的对象是普通对象。
当调取一个对象的属性时,会先在自己查找,若无,就根据 proto 找到构造原型,若无,继续往上找。最后会到达顶层Object prototype,它的 proto 指向null,均无结果则返回undefined,结束。
由 proto 串起的路径就是『原型链』。
经过prototype能够给全部子类共享属性
一般在通常的项目里不须要,由于应用简单,但你要用纯js作一些复杂的工具或框架系统就要用到了,好比webgis、或者js框架如jquery、ext什么的,否则一个几千行代码的框架不用继承得写几万行,甚至还没法维护
单线程, 先执行同步主线程, 再执行异步任务队列
先主线程后异步任务队列
先微任务再宏任务
块级做用域, 暂时性死区
函数节流是指必定时间内js方法只跑一次。好比人的眨眼睛,就是必定时间内眨一次。这是函数节流最形象的解释。
// 函数节流 滚动条滚动 var canRun = true; document.getElementById("throttle").onscroll = function(){ if(!canRun){ // 判断是否已空闲,若是在执行中,则直接return return; } canRun = false; setTimeout(function(){ console.log("函数节流"); canRun = true; }, 300); };
函数防抖是指频繁触发的状况下,只有足够的空闲时间,才执行代码一次。好比生活中的坐公交,就是必定时间内,若是有人陆续刷卡上车,司机就不会开车。只有别人没刷卡了,司机才开车。
// 函数防抖 var timer = false; document.getElementById("debounce").onscroll = function(){ clearTimeout(timer); // 清除未执行的代码,重置回初始化状态 timer = setTimeout(function(){ console.log("函数防抖"); }, 300); };
// 这种实现方式是利用一个伪死循环阻塞主线程。由于JS是单线程的。因此经过这种方式能够实现真正意义上的sleep()。
function sleep(delay) { var start = (new Date()).getTime(); while ((new Date()).getTime() - start < delay) { continue; } } function test() { console.log('111'); sleep(2000); console.log('222'); } test()
闭包属于一种特殊的做用域,称为 静态做用域。它的定义能够理解为: 父函数被销毁 的状况下,返回出的子函数的[[scope]]中仍然保留着父级的单变量对象和做用域链,所以能够继续访问到父级的变量对象,这样的函数称为闭包。
闭包会产生一个很经典的问题:
o多个子函数的[[scope]]都是同时指向父级,是彻底共享的。所以当父级的变量对象被修改时,全部子函数都受到影响。
解决:
o变量能够经过 函数参数的形式 传入,避免使用默认的[[scope]]向上查找
o使用setTimeout包裹,经过第三个参数传入
o使用 块级做用域,让变量成为本身上下文的属性,避免共享
Facebook出品, 倡导数据的不可变性, 用的最多就是List和Map.
// 检测l的原型链(__proto__)上是否有r.prototype,如有返回true,不然false function myInstanceof (l, r) { var R = r.prototype while (l.__proto__) { if (l.__proto__ === R) return true } return false }
// 严格模式下, 隐式绑定丢失后this不会指向window, 而是指向undefined
'use strict' var a = 2 var obj = { a: 1, b: function() { // console.log(this.a) console.log(this) } } var c = obj.b c() // undefined
并非严格意义的js的超集, 与js不彻底兼容, 会报错
更多的限制, 是一种桎梏
有些js第三方库没有dts, 有问题
构造函数中没有显示的建立Object对象, 实际上后台自动建立了
直接给this对象赋值属性和方法, this即指向建立的对象
没有return返回值, 后台自动返回了该对象
// 模拟构造函数实现 var Book = function(name) { this.name = name; }; //正经常使用法 var java = new Book(‘Master Java’); //使用代码模拟,在非IE浏览器中测试,IE浏览器不支持 var python = {}; python.__proto__ = Book.prototype; Book.call(python, 'Master Python');
for in遍历数组会遍历到数组原型上的属性和方法, 更适合遍历对象
forEach不支持break, continue, return等
使用for of能够成功遍历数组的值, 而不是索引, 不会遍历原型
for in 能够遍历到myObject的原型方法method,若是不想遍历原型方法和属性的话,能够在循环内部判断一下,hasOwnPropery方法能够判断某属性是不是该对象的实例属性
使用消息队列以及setInterval或promise进行入队和出队
Promise.prototype.finally = function (callback) { let P = this.constructor; return this.then( value => P.resolve(callback()).then(() => value), reason => P.resolve(callback()).then(() => { throw reason }) ); };
执行上下文中还包含做用域链。理解做用域以前,先介绍下做用域。做用域其实可理解为该上下文中声明的 变量和声明的做用范围。可分为 块级做用域 和 函数做用域
特性:
声明提早: 一个声明在函数体内都是可见的, 函数优先于变量
非匿名自执行函数,函数变量为 只读 状态,没法修改
let foo = function() { console.log(1) }; (function foo() { foo = 10 // 因为foo在函数中只为可读,所以赋值无效 console.log(foo) }()) // 结果打印: ƒ foo() { foo = 10 ; console.log(foo) }
咱们知道,咱们能够在执行上下文中访问到父级甚至全局的变量,这即是做用域链的功劳。做用域链能够理解为一组对象列表,包含 父级和自身的变量对象,所以咱们便能经过做用域链访问到父级里声明的变量或者函数。
由两部分组成:
o[[scope]]属性: 指向父级变量对象和做用域链,也就是包含了父级的[[scope]]和AO
oAO: 自身活动对象
如此 [[scopr]]包含[[scope]],便自上而下造成一条 链式做用域。
浅拷贝: 以赋值的形式拷贝引用对象,仍指向同一个地址,修改时原对象也会受到影响
oObject.assign
o展开运算符(...)
深拷贝: 彻底拷贝一个新对象,修改时原对象再也不受到任何影响
oJSON.parse(JSON.stringify(obj)): 性能最快
具备循环引用的对象时,报错
当值为函数、undefined、或symbol时,没法拷贝
o递归进行逐一赋值
新生成一个对象
连接到原型: obj.__proto__ = Con.prototype
绑定this: apply
返回新对象(若是构造函数有本身 retrun 时,则返回该值)
能在实例的 原型对象链 中找到该构造函数的prototype属性所指向的 原型对象,就返回true。即:`// __proto__: 表明原型对象链instance.[__proto__...] === instance.constructor.prototype// return true`