米娜桑, 哦哈哟~
该篇章主要基于链接中的参考内容和代码测试得出的结论, 面向具有一定基础的前端开发者. 如有错误, 请指出与包涵.
原型链的解释
https://juejin.im/post/5aa78fe66fb9a028d2079ca4
白话翻译: 原型链就相当于对象上的一个链条, 通过隐性原型属性__proto__ 将其他相关的属性绑定以达到引用的效果, 其链条的终点就是 Object.prototype, 这就是原型链.
Object.create() 声明的对象
Object.create({name: 1}) 相当于在这个对象的链条上再增加一条链条__proto__, 所以 Object.create(null) 的结果是没有任何隐藏属性非常纯净且可高度定制的 {} (一般用于一些开源项目), 当然通过
也可以获得纯净的对象, 不过生成的性能一般, 通过以下代码实现 Object.create().
Function.prototype.bind() 的特别之处
通过 Function.prototype.bind() 声明的函数不是 Function 的实例, 故不存在 class.prototype === obj.__proto__; 不过可以通过
Object.prototype.toString.call() 可以得知它依然是一个函数.
并与 Function.prototype 是一致的.
new
new 的过程如下
创建有 Object 函数实例出来的空对象;
将该对象绑定到相应的构造函数上, 其此为 this 的上下文, 如果没有返回对象的话, 就返回 this
原型链继承的方式
- https://juejin.im/post/5b654e88f265da0f4a4e914c
- https://github.com/mqyqingfeng/Blog/issues/16
原型继承
缺点: 属性共享, 不能传参
经典继承 -- 使用 call 方法借用构造函数的方式
缺点: 不能继承 prototype 上的属性
组合继承 -- 即原型链继承和经典继承的结合
缺点: 父类函数执行两次
组合继承的优化
缺点: prototype 的保存地址其实就是父级的保存地址, 也就是说如果改变 child.prototype 会直接影响到父级的 prototype, 所以需要加一个__proto__进行隔离
寄生组合的方式 -- 比较理想的组合方式
class 的继承方式
this 的指向
this 永远指向最后调用的对象.
也就是说 a.b.c.fn(), 那么 fn 里面的 this 的指向 c 的属性.
如果令 d = b.c.fn; 则 a.d() 中的 this 是指向 a 的.
setTimeout 的 function 中的 this 是指向 Windows 对象的. 因为 setTimeout 实则为 Windows.setTimeout.
可通过定义 this 的变量来调用或使用 apply/call/bind 的方式改变 this 指向.
箭头函数的 this
自身没有声明 this, 所以会在作用域链上找最近的 this.
不可以当作构造函数.
不能用作 Generator 函数.
不能使用 arguments,arguments 可以用 ...REST 取代.
- apply,call,bind
- https://juejin.im/post/59bfe84351882531b730bac2
- https://www.cnblogs.com/goloving/p/9380076.html
可以通过 apply 和 call 对对象进行调用, 使得函数内的 this 绑定到该调用的值.
apply 和 call 的区别就是传入方式的不一样, 前者是数组传参的方式, 后者是直接传参的方式.
bind 跟 call 一致, 只不过 bind 会创建并返回一个新的函数.
实现机制如下
- call (apply 同理, 只是改变参数的形式)
- bind
如果要模仿 Function.prototype.bind() 得到的函数 fn, 需要设置
事件循环
https://developer.mozilla.org/zh-CN/docs/web/JavaScript/EventLoop# 运行时概念
- https://juejin.im/post/59e85eebf265da430d571f89
- https://segmentfault.com/a/1190000011198232
事件循环是和消息队列共同实现 JS 同步异步运行的机制. 消息队列先进先出, 一个循环里, 先从队列中取出宏任务并执行, 如果存在异步任务, 便会将其回调函数注册发放到消息队列当中; 再执行微任务, 直到相应的执行栈为空为止; 执行完后启动新的循环; 事件循环是 JS 的运行机制.
事件循环还分宏任务和微任务
宏任务: 整体代码; setTimeout;setInterval, 宏任务消息队列
微任务: Promise; process.nextTick, 微任务消息队列
通过以下代码测试
节点操作
添加节点可以通过 appendChild
通过 innerText 对节点添加文本信息
也可以通过 innerHTML 对节点添加 HTML 文本
利用 document.createElement 添加对应元素.
通过 node.addEventListener(type,listener,capture) 添加事件. 第三参数为是否捕获, 默认 false, 即冒泡
document 为最大的节点.
当然也可以通过 DocumentFragment 来减少 dom 操作
以下是 ul 元素添加 li 元素的例子
来源: https://www.cnblogs.com/TensionMax/p/12640663.html